0%

[XDCTF2015] filemanager

[XDCTF2015] filemanager

BUU上一个15年的题,二次注入

源码泄漏

www.tar.gz。。。我试了www.zip和robots.txt,结果源码是另一个圧缩形式
有用的就两个文件,upload.php和rename.php
提交的所有数据都被转义加了斜杠,直接注入无果,事实上测试一下就发现把文件名改成1’之类的时候,再去修改会触发二次注入

二次注入

看一下关键部分代码
rename.php

if (isset($req['oldname']) && isset($req['newname'])) {
    $result = $db->query("select * from `file` where `filename`='{$req['oldname']}'");
    if ($result->num_rows > 0) {
        $result = $result->fetch_assoc();
    } else {
        exit("old file doesn't exists!");
    }

    if ($result) {

        $req['newname'] = basename($req['newname']);
        $re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");
        if (!$re) {
            print_r($db->error);
            exit;
        }
        $oldname = UPLOAD_DIR.$result["filename"].$result["extension"];
        $newname = UPLOAD_DIR.$req["newname"].$result["extension"];
        if (file_exists($oldname)) {
            rename($oldname, $newname);
        }

可以看出来,实际上的文件名和数据库中的数据是分离的,而真正对文件的重命名是最后的rename函数,但仔细看oldname和newname,他们的后缀都由查询的result给出,而在upload.php中后缀只能是白名单中的几个项,所以看起来无法完成攻击
但是如果extension为空,那么可控的$req[“newname”]就可以重命名出任意后缀的文件,自然可以重命名出一个php来getshell
而这里的update语句刚好可以修改extension,$req[‘newname’]因为被转义无法完成注入,但是$result[‘filename’]如果事先构造的足够好,当其被从数据库取出时,则会发生二次注入

目前的思路:上传一个名为1’,extension=’.jpg的文件,然后将其重命名为1.jpg,则在update时的语句为update \file` set `filename`=’1.jpg’, `oldname`=’1’,extension=’’ where `fid`=1`
文件名变为1.jpg.jpg

现在我们再次重命名,将含有extension=’’的这条result拿出来,所以提交一个oldname=1.jpg,这样子查询语句就会把我们刚才二次注入的result取出,再令newname=1.php,就可以将一个名为1.jpg的文件重命名为1.php,因为之前上传的那个文件名被修改后为1.jpg.jpg,因此额外上传一个名为1.jpg的shell即可

后记

SQL注入真难啊,新题目的注入思路已经超乎常人,老题目的二次注入思路也挺复杂的,不拿纸笔划一划都理不清楚什么情况