【安全漏洞】ThinkPHP 3.2.3 漏洞复现

本文详细分析了ThinkPHP 3.2.3版本中的安全漏洞,包括因`$this->show`引起的命令执行、SQL注入的各种形态如通过数组传参绕过过滤等,并探讨了反序列化、EXP注入、BIND注入及变量覆盖导致的命令执行等,通过实例展示了漏洞利用的过程。
摘要由CSDN通过智能技术生成

$this->show 造成命令执行

在 Home\Controller\IndexController 下的index中传入了一个可控参数,跟进调试看一下。

class IndexController extends Controller
{
   
    public function index($n='')
    {
   
        $this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 24px 48px;"> <h1>:)</h1><p>欢迎使用 <b>ThinkPHP</b>!</p><br/>版本 V{$Think.version}</div><script type="text/javascript" src="http://ad.topthink.com/Public/static/client.js"></script><thinkad id="ad_55e75dfae343f5a1"></thinkad><script type="text/javascript" src="http://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script></p>Hello '.$n, 'utf-8');
    }
}

跟进 display()

protected function show($content,$charset='',$contentType='',$prefix='') {
   
    $this->view->display('',$charset,$contentType,$content,$prefix);
}

一路跟进到 fetch(),然后一路进入 Hook::listen(‘view_parse’, $params);

public function fetch($templateFile='', $content='', $prefix='')
{
   
    if (empty($content)) {
   
        $templateFile   =   $this->parseTemplate($templateFile);
        // 模板文件不存在直接返回
        if (!is_file($templateFile)) {
   
            E(L('_TEMPLATE_NOT_EXIST_').':'.$templateFile);
        }
    } else {
   
        defined('THEME_PATH') or    define('THEME_PATH', $this->getThemePath());
    }
    // 页面缓存
    ob_start();
    ob_implicit_flush(0);
    if ('php' == strtolower(C('TMPL_ENGINE_TYPE'))) {
    // 使用PHP原生模板
        $_content   =   $content;
        // 模板阵列变量分解成为独立变量
        extract($this->tVar, EXTR_OVERWRITE);
        // 直接载入PHP模板
        empty($_content)?include $templateFile:eval('?>'.$_content);
    } else {
   
        // 视图解析标签
        $params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
        Hook::listen('view_parse', $params);
    }
    // 获取并清空缓存
    $content = ob_get_clean();
    // 内容过滤标签
    Hook::listen('view_filter', $content);
    // 输出模板文件
    return $content;
}

关键地方在这,我们之前 index 里的内容被存入了缓存文件php文件中,连带着我们输入的可控的php代码也在其中,然后包含了该文件,所以造成了命令执行。

public function load($_filename,$vars=null){
   
    if(!is_null($vars)){
   
        extract($vars, EXTR_OVERWRITE);
    }
    include $_filename;
}

sql注入

/Application/Home/Controller/IndexController.class.php 添加一段SQL查询代码。http://localhost/tp323/index.php/Home/Index/sql?id=1 查询入口。

public function sql()
{
   
    $id = I('GET.id');
    $user = M('user');
    $data = $user->find($id);
    var_dump($data);
}

传入 id=1 and updatexml(1,concat(0x7e,user(),0x7e),1)–+ ,跟进调试。进入 find() 函数,先进行一段判断,传入的参数是否是数字或者字符串,满足条件的话 $options[‘where’][‘id’]=input。

if(is_numeric($options) || is_string($options)) {
   
    $where[$this->getPk()]  =   $options;
    $options                =   array();
    $options['where']       =   $where;
}

随后进行一个判断 if (is_array(KaTeX parse error: Expected 'EOF', got '&' at position 10: options) &̲& (count(options) > 0) && is_array($pk)),getPk()函数是查找mysql主键的函数,显然 $pk 值是 id,不满足条件

$pk  =  $this->getPk(); // $pk='id'
if (is_array($options) && (count($options) > 0) && is_array($pk)) {
   
    //
}

随后执行 $options = t h i s − > p a r s e O p t i o n s ( this->_parseOptions( this>parseOptions(options); ,

protected function _parseOptions($options=array())
{
   
    if (is_array($options)) {
   
        $options =  array_merge($this->options, $options);
    }

    if (!isset($options['table'])) {
   
        // 自动获取表名
        $options['table']   =   $this->getTableName();
        $fields             =   $this->fields;
    } else {
   
        // 指定数据表 则重新获取字段列表 但不支持类型检测
        $fields             =   $this->getDbFields();
    }

    // 数据表别名
    if (!empty($options['alias'])) {
   
        $options['table']  .=   ' '.$options['alias'];
    }
    // 记录操作的模型名称
    $options['model']       =   $this->name;

    // 字段类型验证
    if (isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) {
   
        // 对数组查询条件进行字段类型检查
        foreach ($options['where'] as $key=>$val) {
   
            $key            =   trim($key);
            if (in_array($key, $fields, true)) {
   
                if (is_scalar($val)) {
   
                    $this->_parseType($options['where'], $key);
                }
            } elseif (!is_numeric($key) && '_' != substr($key, 0, 1) && false === strpos($key, '.') && false === strpos($key, '(') && false === strpos($key, '|') && false === strpos($key, '&')) {
   
                if (!empty($this->options['strict'])) {
   
                    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值