最近接触到了xctf的OJ后,不得不感慨,有牌面就是不一样。整个界面做的赏心悦目,而且题目也更接近渗透过程(也许吧)。
新手区很快ak暂且不表,这里就不间断更新一下高手进阶区的题目吧。
链接:https://adworld.xctf.org.cn/task/task_list?type=web&number=3&grade=1
ics-06
不得不说这道题就是个坑。首先进去看到是个常见的管理系统的平台前端,当然页面上各种xx中心的button都是假的,果断先试试admin.php尝试找后台,无果。于是转而输入index.php,发现到了一个表单页面。
这不就很清楚了嘛,id都在 url里面,当然是,当然是。。。。。。注入了!于是就陷入了id可以注入的误区。然而,手工试了下1, 1' , 1" 以及其他标准盲注手段,全都没有回显或报错。。。。。。这种时候,与其考虑是不是进行了各种过滤,不如换个思路:底下送分题三个大字暗示着我们这个id也许不是用来注入的,只是用来爆破的呢?
于是用bp抓包,考虑到初始id为1 ,选择直接用数字序列来爆破。果然id=2333时有结果出flag了。
//不得不说这脑洞真的可以,作为一道简单题成功在思路上把人引向了注入。
NewsCenter
这道题相比起来就简单许多了,进入后有一个很显眼的提交框,盲猜sql注入且是post提交。因此直接在所给的提交框里构造语句就很简单了。本题没有任何为难人的过滤(发现#没被过滤但是--+被过滤了,有点难堪),一步步用union select 爆出库,表,列,字段值即可。
NaNNaNNaNNaN-Batman
这道题老实说有点蒙,因为题目所给的附件解压后得到的文件内容web100是这样的:
<script>_='function $(){�e=�getEle�ById("c").value;�length==16�^be0f23�233ac�e98aa$�c7be9�){�tfl�s_a�i�e}�na�_h0l�n�rg{�e�_0�iit\'�_�n�s=[t,n,r,i];for(�o=0;o<13;++o){ �[0]);�.splice(0,1)}}} \'<input id="c">< onclick=$()>Ok</>\');delete _����var �","�docu�.�)�match(/�"];��/)!=null=[" �write(�s[o%4]button�if(e.�ment';for(Y in $='��� �������')with(_.split($[Y]))_=join(pop());alert(_)</script>
显然这是段js代码,但是中间出现的各种乱码让我不太理解。可能是因为编码方式出现了乱码?于是我尝试用记事本打开修改编码方式却无济于事。
所以其实js代码中的<0x..>之类的标签用其他方式打开都是乱码,那么怎样才能看到真实正确的代码呢?
这里我在网上求助了下,发现首先应该将web100改为html后缀,打开后执行发现是一个提交框。
这里进行代码审计可以发现,最后一句eval()执行的变量是也就是上述包括了一个函数 $()的一大串字符串。所以这里是把这个字符串解释为代码执行,但因为乱码的缘故不能正确执行,只显示了提交框。所以,把eval()改为alert(),就能成功看到完整的源码。
function $(){
var e=document.getElementById("c").value;
if(e.length==16)
if(e.match(/^be0f23/)!=null)
if(e.match(/233ac/)!=null)
if(e.match(/e98aa$/)!=null)
if(e.match(/c7be9/)!=null)
{var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
for(var o=0;o<13;++o){
document.write(s[o%4][0]);s[o%4].splice(0,1)}}}
document.write('<input id="c"><button onclick=$()>Ok</button>');
delete _
仔细阅读源码,发现有两种getflag方式,一种是按正则执行,所以构造符合要求的字符串:
1.开头要有be0f23
2.结尾要是e98aa
3.整个字符串能匹配到233ac与c7be9子串
所以构造e=be0f233ac7be98aa即可
第二种方式就很简单了,因为源码其实已经告诉你了flag就是后面正则绕过后这段代码执行的结果,甚至不需要执行,直接看这几个字符列表里字母顺序,从上到下就是flag也能知道要按什么规则求flag的值。当然,最简单的还是直接执行这段js代码,可以放在chorme控制台中运行或者自己用编辑器也可以。
PHP2
这道题自己还是吃了没水平的亏。开始上来就问你能否向网站进行身份验证?然后我操起常规操作,先看index.php,再上Fiddler抓包,再用御剑扫描,结果一无所获。。。。。。难道还有别的办法获取有用信息吗?老实说我一时想不到,直到看了网上题解才知道可以直接输入index.phps查看index.php的源码。。。 `76TRTD
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>
略显熟悉的代码。。。仔细一想,诶我好像还做过。无非就是“==”的绕过,那么进行审计吧,首先get传参id,要求不能是id严格等于admin,但是得在经历一次url解码后=admin......那就好办了,还记得之前说浏览器输入内容会先进行一次解码,而函数又会再解一次码,所以这里只需编码两次就好
tip:这里有一个小技巧:实际上大家应该都有所体会,那就是你实际输入的字符串在各种textwizard中进行urlencode后还是原字符串,按照这种规则,我们在需要对字符串进行url编码时,最好是写脚本或者搜索十六进制转字符串(url编码规则实际上是对其进行10进制转16进制,比如a的ascii码是97,十六进制为61)因此构造payload就是对admin编码两次为%2561%2564%256d%2569%256e......
等等,真的需要编码这么多吗?其实不然,相信有很多人明白了,其实只需对其中一个字母编两次码就可以绕过强相等判断了,后面解码其实不影响字符串内容。所以最简单的payload应该是id=%2561dmin
unserialize3
相比上题,这道题可谓提示的仁至义尽了。上来标题告诉我们肯定跟php序列化有关,且打开后有代码:
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
定义了一个类,变量已经告诉我们是flag了,以及一个魔术方法退出程序,最后还有一个暗示get传参code的。到这里如果做过一两次php序列化的题目的应该就很熟悉了,肯定是php脚本运行得到flag序列化后的值传参。
但是,这道题难点在于怎么解决 __wakeup()函数的问题.百度发现,__wakeup()函数与反序列化函数一起使用,反序列化函数执行前,就会检查这个魔术方法的存在与否,有则执行。但它同样也有漏洞,那就是当序列化值的属性大于类本身的属性值时,会跳过这个魔术方法。
所以,我们只需先写脚本
<?php
class xctf
{
public $flag = '111';
public function __wakeup()
{
exit('bad requests');
}
}
$a=new xctf();
echo(serialize($a));
?>
得到O:4:"xctf":1:{s:4:"flag";s:3:"111";}
序列化字符串各部分简单释义:
O代表结构类型为:类:4表示类名长度:接着是类名:属性(成员)个数
大括号内分别是:属性名类型;长度:名称:值类型:长度:值
因此,把属性从1 改为2 ,成功拿到flag。
mfw
这道题老实说我肯定不会做,因为自己对git源码泄露没有概念。en一开始进页面时就忽略了,因此它提示了可能是git源码泄露(当前大量开发人员使用git进行版本控制,对站点自动部署。如果配置不当,可能会将.git文件夹直接部署到线上环境。这就引起了git泄露漏洞),输入/.git/可以看到
这时可以在linux系统下使用GitHack-master还原源代码。
这时先看index.php源码(cat index.php),如下:
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
根据php源码,肯定要在assert()函数上下手了,同时注意是get传参page进行绕过,,,这里又是我一大盲区,通过题解得知,有一个通过system()函数绕过的方法,payload如下
?page=').system("cat templates/flag.php");//
当然良好的习惯是先检查system()函数能否使用,构造page=').phpinfo();//即可
打开flag.php后查看源码得flag
lottery
本来很简单一道题的,不过自己之前因为没装好githack就没做。下面简单提一下流程
首先,目标是最终页面里claim you prize 中9990000的奖励,估计就是flag了。首先开始没什么信息提示,尝试了下robots.txt发现/.git/被ban了。那么这里就要用到githack将.git泄露源码下载下来。这里还是建议直接下载在虚拟机里的kali上吧。因为githack是python2写的,自己win10系统上装的3。基于python2今年之后就不再更新,还是老老实实在虚拟机里用现成的2吧。
之后下载下源码,在api.php中可以发现存在弱类型比较的漏洞:
用户输入的数据: {"action":"buy","numbers":"1234567"}
用于比较的数字是随机生成的数字字符串,且只是==弱类型比较。那么只需给numbers传七个true就行了。
payload:
{"action":"buy","numbers":{true,true,true,true,true,true,true}}
把钱攒够了就可以买flag了。
bug
又是一道之前自己不知怎么没做出来的题。。。这一会再做感觉比较轻松。不过查看了题解才发现仍然很有的位置套路满满。首先经过几番尝试后发现可以在首页的改密码处抓包,发现传值包括username与password。那么把username改为admin就可以用自己改好的密码登录进去了。进去后一无所获,然后发现提示ip不匹配,于是老套路改xff头尾127.0.0.1。 从返回源码处发现提示要改do参数,这里正确答案是令do=upload。不过我也不知道为什么要upload?zhiji