0%

SWPU2019 Web4

[SWPU2019]Web4

buu上的一分题,说实话这个难度我是不相信它只有一分的

题解

打开是一个登录框,简单测试发现添加单引号会出现一个PHP的报错,而不是MySQL的报错,存在注入点,但不可使用报错注入
测了半天,感觉有关键词屏蔽,但是无论如何返回值就三种,登录成功,登录失败,PHP报错。那想直接查询回显也没机会了,只能盲注,并且登录成功啥也不给呜呜呜。
简单测一下发现select,sleep,or,逗号,大小于号,井号还有些七七八八的盲注需要的东西都给禁用了,但是另一个注释符–还能用,最主要的是回显根本没有帮助,完全不知道后台到底在干什么。
后来拿到源码之后看见了超级过滤select|information|insert|union|ascii|,|like|outfile|join|<|>|and|substr|#|or|\|\||sleep|benchmark|if|&&
最后看wp说是堆叠注入,并且使用预处理将语句变为16进制表示,直接绕过超级过滤

MySQL堆叠注入预处理

思路是输入分号后返回的是登录失败而不是PHP报错,判断能够执行堆叠注入
预处理可以使转换为16进制的MySQL语句被执行
1';set @a=0x{0}prepare payload from @a;execute payload--
a的内容用常规时间盲注脚本跑就可以了
注意这里数据是用json格式提交的,记得把数据转换一下json格式
贴一个常见payload
select if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))={1},sleep(3),1)

一直注到最后会看见一个叫赵总想要一个女朋友的zip,下载下来就是源码

代码审计

index.php里面指明了Common文件夹里面的内容,只有fun.php有实际内容,写明了对r参数的解析

    $r = explode('/', $_REQUEST['r']);
    list($controller,$action) = $r;
    $controller = "{$controller}Controller";
    $action = "action{$action}";
    ........
    $data = call_user_func(array((new $controller), $action));

就是前面半边是controller,后半边是action,如果存在对应的controller和action就调用对应的controller类下的action方法
接下来看controller类,登录类毫无作用,就是返回之前注入时的写死的回显
在basecontroller类中发现函数loadView

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

有一句include $this->viewPath;,且viewPath似乎可控,继续看看。可惜看完了所有loadView函数的调用,它的$viewPath都是写死的,但是这里还有一句extract($viewData);如果$viewData可控,也可以进行变量覆盖
在UserController中发现actionIndex()函数

    public function actionIndex()
    {
        $listData = $_REQUEST;
        $this->loadView('userIndex',$listData);
    }

其中的$listData完全可控,本来想直接覆盖$this->viewPath,后来想起来怎么可能覆盖类的私有成员变量,只得作罢。
那就只能看看我们老老实实包含的页面有什么东西了,userIndex.php就实现了一个功能,返回一个文件的base64编码,而文件路径$img_file刚好可以通过$_REQUEST来覆盖,这样一来我们就能直接获得flag.php的base64编码,获取flag了。
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 . '">';

小坑点

dirname(__FILE__)返回的是该文件的目录位置,所以是/var/www/html/View,并且目录没有一个斜杠结尾。所以最后试了半天r=../flag.php没有回显,又想不出来到底哪错了。。。

感觉吧第二个点引导的东西很直接,也不难,但是开局那个SQL注入的回显真的是恶心死人了,太难了呜呜呜