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