A Journey into Synology NAS 系列四: HTTP请求流程和案例分析
前言
前面两篇文章从局域网的角度出发,对群晖NAS设备上开放的部分服务进行了分析。而在大部分情况下,群晖NAS设备是用于远程访问的场景中,即唯一的入口是通过5000/http(5001/https)进行访问(暂不考虑使用QuickConnect或其他代理的情形)。因此,本篇文章将主要对HTTP请求流程和处理机制进行分析,并分享在部分套件中发现的几个安全问题。
HTTP请求处理流程
在正常登录过程中抓取的部分请求如下,可以看到请求url包含query.cgi、login.cgi和entry.cgi等。根据群晖的开发者手册可知,与设备进行交互的大概流程如下:
- 通过
query.cgi获取API相关的信息; - 通过
login.cgi和encryption.cgi进行认证,获取session id; - 通过
entry.cgi发送请求、解析响应; - 完成交互后登出。

某个具体的请求示例如下,可以看到有点类似于JSON-RPC。对于大部分请求,其url均为"/webapi/entry.cgi"。在POST data部分,api参数表示要请求的API名称,method表示要请求的API中的方法,version表示要请求的API版本。

针对API请求,群晖在后端采用json元数据文件SYNO.***.***.lib来定义与API相关的信息,示例如下。
1 | { |
根据上述信息,可以知道如何构造一个具体的请求来触发后端的某个处理程序。
整体的HTTP请求处理流程大概如下。首先,请求通过5000端口发送给设备,基于请求的url,nginx服务会将该请求分发给不同的cgi,如query.cgi、login.cgi和entry.cgi,其中,entry.cgi是大部分POST请求的端点。这些cgi会与另外两个服务synocgid和synoscgi进行通信,其中synocgid负责处理与session相关的事务,而synoscgi则负责分发具体的请求到最终的处理程序。

安全问题
在理解了HTTP请求流程和处理机制后,便可以对群晖NAS设备的功能模块进行分析。在群晖NAS设备上,主要包含两大攻击面:DSM操作系统本身和群晖提供的大量套件。下面结合具体的实例进行分析。
Diagnosis Tool
前面提到过,Diagnosis Tool是群晖提供的一个工具套件,支持抓包、调试等功能。该工具的界面和具体的抓包请求示例如下。

该请求由packet_capture.cgi程序进行处理,部分示例代码如下。在handle_action_start()中,获取请求中的参数后将其以json字符串的形式传给tcpdump_wrapper程序。
1 | __int64 __fastcall handle_action_start(__int64 a1, __int64 a2, const char *a3, const char *a4) |
在tcpdump_wrapper中,调用sub_401F10()解析得到output_dir、expression和interface参数,并传入RunTcpDump(),其最终调用execve()执行命令tcpdump -i <interface> -w <file> -C 10 -s 0 filter_expression。
1 | __int64 __fastcall main(signed int a1, char **a2, char **a3) |
调用execve()来执行命令,相对比较安全,避免了命令注入的问题,但其中的filter_expression参数是可控的。通过查看tcpdump命令的帮助文档,发现-z选项与-C或-G选项组合也可达到命令执行的目的。

针对tcpdump -i <interface> -w <file> -C 10 -s 0 filter_expression,其中已包含-C选项,因此通过伪造filter_expression参数为-z<path to your shell script>,即通过注入命令选项,可实现命令执行的效果。
DS File
DS File是群晖提供的一个移动应用程序,便于从移动设备上访问和管理DiskStation上的文件,使用该应用访问DiskStation的流程与通过web的流程类似。当尝试登录到DiskStation时,认证过程采用基于PKI的加密机制。而在某些情形下如目标IP输入错误,或者网络临时不可用,正常的请求会失败,DS File会发送额外的请求。

通过查看对应的第3个请求发现,在请求头中包含经过Base64编码后的Authorization信息,相当于明文。

因此,在一个不安全的网络环境中,当尝试通过DS File应用访问DiskStation时,通过简单地丢弃或重定向对应的请求,”中间人’’可窃取用户的明文账号信息。
Synology Calendar
该套件是一个基于Web的应用程序,用于管理日常的事件和任务,其支持在事件中添加附件和分享日程等功能。其中,添加附件的功能支持从本地上传和从 NAS中上传两种方式。普通用户创建事件并添加附件的示例如下,同时给出了与附件链接相关的部分前端代码。

可以看到,上传文件的名称被拼接到href链接中。如果伪造一个文件名,能否控制对应的href链接呢?经过测试发现,由于未对文件名进行校验,通过伪造一个合适的文件名,可以更改对应的href链接,同时让显示的文件名称看起来正常。

此外,借助日程分享功能,还可以将该事件分享到管理员组中。当管理员组中的某个人查看该事件并点击对应的附件之后,该请求就会被执行。因此,利用该漏洞,一个普通权限的用户可以以”管理员”的权限执行”任意”请求,比如将其添加到管理员组中。
Media Server
Media Server套件提供与多媒体相关的服务,允许在NAS上通过DLNA/UPnP播放多媒体内容。在安装该套件后,会启动一些自定义的服务,如下。

通过简单的分析,发现dms中存在一些可供访问的url,且无需认证。

第1个比较有意思的api是videotranscoding.cgi,对应的请求url格式为http://%s:%d/transcoder/videotranscoding.cgi/%s/id=%d%s,处理该请求的部分代码如下。可以看到,如果url中包含字符串id=和字符?,就将id=和?之间的内容拷贝到dest缓冲区中。由于没有考虑两者出现的先后顺序,如果请求url为http://%s:%d/transcoder/videotranscoding.cgi/VideoStation?id=1,在调用strncpy()时就会出现整数下溢问题。
1 | __int64 sub_406E80(__int64 a1) |
假设请求url的格式和程序预期的一致,函数sub_403F50()将会在后续被调用,其第3个参数对应前面拷贝的请求url中id=和?之间的内容。在sub_403F50()中,对参数a2进行简单校验后,参数a3会被当做id后面的参数进行格式化。由于未对参数a3进行适当校验,且参数a3外部可控,因此会存在SQL注入的问题。
1 | __int64 sub_403F50(__int64 a1, std::string *a2, _QWORD *a3, std::string *a4) |
另外1个类似的api为jpegtnscaler.cgi,对应的请求url格式为http://%s:%d/transcoder/jpegtnscaler.cgi/%s/%d.%s,处理该请求的部分代码如下。可以看到,在调用strncpy()前未对其长度参数进行校验,通过构造请求如http://%s:%d/transcoder/jpegtnscaler.cgi/<a*0x450>/1,可造成缓冲区溢出。
1 | __int64 main(__int64 a1, char **a2, char **a3) |
Audio Station
Audio Station套件提供收听广播节目、管理音乐库、建立个人播放清单等功能,并支持随时随地与朋友分享。安装该套件后,在其安装路径下会存在一些自定义的cgi程序,如media_server.cgi、web_player.cgi、audiotransfer.cgi等。在使用该套件的同时进行抓包,部分请求示例如下。

在前面提到的HTTP请求处理流程中,execl_cgi()负责处理自定义的cgi请求。更重要的是,在某些情形下,认证的处理由自定义的cgi程序负责。

通过分析,最有意思的api为audiotransfer.cgi,对应的请求url格式为http://%s:%d/webman/3rdparty/AudioStation/webUI/audiotransfer.cgi/%s.%s,处理该请求的部分代码如下。可以看到,在main()函数开始处调用sub_402730()。在函数sub_402730()中,先获取请求url路径最后面的内容,然后将其传给MediaIDDecryption()。在MediaIDDecryption()中,先计算参数a1的长度,在拷贝前6个字节后,调用snprintf()。由于调用snprintf()时,其size参数和后面的字符串内容可控,存在缓冲区溢出问题。更重要的是,这个过程中没有对认证进行处理,即无需认证,因此通过构造并发送特定的请求,远程未认证的用户可触发该缓冲区溢出漏洞。
1 | __int64 main(__int64 a1, char **a2, char **a3) |
关于漏洞利用,知道创宇的@fenix师傅基于DSM 5.2-5592和Audio Station 5.4-2860进行了分析和测试,其中相关的条件包括x86架构、NX保护、ASLR为半随机,感兴趣的可以去看看。这里补充几点:
针对
x86架构,基于DSM 6.x,ASLR为全随机,通过寻找合适的gadgets,可实现稳定利用,无需堆喷或爆破;在
DSM 6.x上,获取到shell后,还需要进行提权操作;针对
x64架构,由于存在地址高位截断的问题,暂时未找到合适的思路进行利用。如果师傅们有合适的思路,欢迎交流 :)
One More Thing
上面只是列举了几个典型的套件,以及在其中发现的部分问题。实际上,群晖的DSM系统中有非常多的功能,以及大量的套件可供分析。群晖官方会不定期发布其产品的安全公告,结合群晖的镜像仓库,可以很方便地去做补丁分析和漏洞挖掘。
小结
针对群晖NAS的远程使用场景,本文重点对web接口上请求的流程和处理机制进行了分析。同时,结合几个典型的套件,基于上述流程,分享了在其中发现的部分安全问题。
本文是该系列的最后一篇,希望对群晖NAS设备感兴趣的同学有所收获。
相关链接
- Synology-SA-20:07 Synology Calendar
- Synology-SA-21:21 Audio Station
- 聊聊 Synology NAS Audio Station 套件未授权 RCE 调试及 EXP 构造
- 群晖产品安全公告
- 群晖镜像仓库
本文首发于安全客,文章链接:https://www.anquanke.com/post/id/266297