本篇文章给大家分享的是有关如何深入分析Citrix ADC远程代码执行RCE漏洞CVE-2019-19781,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
2019年年底,Citrix ADC和Citrix Gateway被曝出存在远程代码执行的高危漏洞CVE-2019-19781,该漏洞最吸引人的地方在于,未授权的攻击者可以利用它入侵控制Citrix设备,并实现进一步的内网资源访问获取。漏洞由安全团队Positive Technologies 和 Paddy Power Betfair发现上报,但在漏洞公告中却未给出过多的漏洞利用方式,因此,这是值得来深入研究的地方。
漏洞分析
虽然在Citrix官方的漏洞公告中未透露出漏洞利用细节,但从其中的漏洞缓解措施中,却侧面揭露了该漏洞的相关类型:
从上述缓解措施信息中,我们判断漏洞可能存在的路径为/vpns/,且有可能是一个目录遍历漏洞。有了这些线索,我们开始在httpd.conf文件中去寻找路径/vpns的定义方法,之后发现NetScaler::Portal::Handler Perl Module (Handler.pm)模块在/vpn/portal/scripts/目录下负责生成了一些方法定义。
/vpn/portal/scripts/下包含了一些脚本文件,由于前期我们判断漏洞起因是目录遍历,因此我们把分析重点放到了那些具备文件写操作的代码路径上。之后,我们在perl模块中的UsersPrefs脚本中发现了以下代码:
sub csd {my $self = shift;my $skip_read = shift || "";# Santity Checkmy $cgi = new CGI;print "Content-type: text/html/n/n";// Username variable initialized by the NSC_USER HTTP Headermy $username = Encode::decode('utf8', $ENV{'HTTP_NSC_USER'}) || errorpage("Missing NSC_USER header.”); <- MARK THIS$self->{username} = $username;...$self->{session} = %session;// Constructing the path from the username.$self->{filename} = NetScaler::Portal::Config::c->{bookmark_dir} . Encode::encode('utf8', $username) . '.xml’;if($skip_read eq 1) {return;}
简言之,上述代码用于从用户相关的NSC_USER HTTP头中构建一条路径,但是在过程中却缺乏任何安全校验措施,结果导致可用任意调用csd方法的脚本去触发目录遍历漏洞。经分析发现,/vpn/portal/scripts/下的所有脚本都会调用csd方法函数,但其中一个脚本文件newbm.pl比较特别:
my $cgi = new CGI;print "Content-type: text/html/n/n";my $user = NetScaler::Portal::UserPrefs->new();my $doc = $user->csd();...my $newurl = Encode::decode('utf8', $cgi->param('url'));my $newtitle = Encode::decode('utf8', $cgi->param('title'));my $newdesc = Encode::decode('utf8', $cgi->param('desc'));my $UI_inuse = Encode::decode('utf8', $cgi->param('UI_inuse'));...my $newBM = { url => $newurl,title => $newtitle,descr => $newdesc,UI_inuse => $UI_inuse,};...
newbm.pl会首先创建一个包含各种参数信息的数组,之后,又会调用filewrite方法把数组中的信息写入到一个XML文件中:
if ($newBM->{url} =~ /^//){push @{$doc->{filesystems}->{filesystem}}, $newBM;} else { # bookmarkpush @{$doc->{bookmarks}->{bookmark}}, $newBM;}// Writing XML file to disk$user->filewrite($doc);
按理来说,我们可以通过构造一些写入命令去控制文件路径或XML中内容,但是,在这里一切都不管用。之后,我们看了安全研究者Craig Yong写的《关于CVE-2019-19781你需要知道的》,其中特别提到了可用Perl Template Toolkit模板工具实现漏洞利用。
深入研究后,我们发现可以在XML文件中插入一些特定的指令,如果这些指令被模板引擎解析,就能触发命令执行。以下就是模板引擎解析test.xml后发生命令执行的一个例子:
综上所述,现在我们有了Perl Template Toolkit这种插入指令的文件写操作方法,但还需要一种方法让某个脚本去强制模板发生解析操作。之后,我们在模板的引用代码中发现Handler.pm可以被用来实现模板解析:
其中的变量 $tmplfile是从HTTP Request Path中构建的,而且之后为了处理这个$tmplfile变量文件,还会生成一个新的模板。现在,将我们之前创建的test.xml测试文件放到模板目录下,触发模板解析行为看看:
总结来看,为了成功漏洞利用需要进行以下步骤:
1、通过模板机制发现执行Perl代码的方式(需要绕过);
2、利用目录遍历方式,在模板目录下放入一个经过构造的XML文件;
3、浏览放入的XML文件,触发模板解析,实现XML中的代码执行。
重点在于最后一步的任意代码执行,在原本默认的Citrix配置中,是不能实现代码执行的,只有经过一个特性配置才能实现Perl代码执行。先前考虑到受漏洞影响的Citrix设备数量,且已有多个团队已经把该漏洞武器化,因此我们没有提供针对该漏洞的利用代码,但后续随着漏洞的披露以及多个安全研究者的exploit公开,我们也选择了公布具体的漏洞利用方法。
第一种方法:模板注入可导致的远程代码执行
这里有两种方法可以实现代码执行,第一种也就是目前大多数公开exploit中使用的BLOCK模板注入方法。我们通过在Perl Template Toolkit的GitHub中,发现了这个被其他用户提交的bug,而正是这个bug可被在此进行利用:
bug问题中介绍执行任意perl代码的方法,目前看似所有公开的exploit中都使用了这种方法,实现了上述漏洞中的任意命令执行,我们再来深入看看这种利用方法在漏洞中的具体实现。
根据Perl Template Toolkit的文档描述可知,模板变量是一个特殊变量,且在调用处理过程中会包含一个指向主模板的对象引用,这里的对象类型可以通过print方法打印显示,为Template::Document:
有了这个对象引用之后,就可以用受控参数去调用方法。通过研究其中的类class代码,我们发现可以综合上述特性成功去调用new方法:
# new(/%document)## Creates a new self-contained Template::Document object which# encapsulates a compiled Perl sub-routine, $block, any additional# BLOCKs defined within the document ($defblocks, also Perl sub-routines)# and additional $metadata about the document.#------------------------------------------------------------------------sub new {my ($class, $doc) = @_;my ($block, $defblocks, $variables, $metadata) = @$doc{ qw( BLOCK DEFBLOCKS VARIABLES METADATA ) };$defblocks ||= { };$metadata ||= { };# evaluate Perl code in $block to create sub-routine reference if necessaryunless (ref $block) {local $SIG{__WARN__} = /&catch_warnings;$COMPERR = '';# DON'T LOOK NOW! - blindly untainting can make you go blind!$block = each %{ { $block => undef } } if ${^TAINT}; #untaint$block = eval $block;return $class->error($@)unless defined $block;}
该new方法可以获取BLOCK模板中的参数并调用eval方法,由此实现任意的perl代码执行。此外,我们还发现用另一个方法component ,也可以实现同样的攻击效果。
第二种方法:DATAFILE插件中的命令注入
在对源代码的方法调用安全分析中,我们发现了DATAFILE插件中的以下代码:
sub new {my ($class, $context, $filename, $params) = @_;my ($delim, $line, @fields, @data, @results);my $self = [ ];local *FD;local $/ = "/n";$params ||= { };$delim = $params->{'delim'} || ':';$delim = quotemeta($delim);return $class->fail("No filename specified")unless $filename;open(FD, $filename)|| return $class->fail("$filename: $!");# first line of file should contain field definitionswhile (! $line || $line =~ /^#/) {$line = <FD>;chomp $line;$line =~ s//r$//;}sub new {my ($class, $context, $filename, $params) = @_;my ($delim, $line, @fields, @data, @results);my $self = [ ];local *FD;local $/ = "/n";$params ||= { };$delim = $params->{'delim'} || ':';$delim = quotemeta($delim);return $class->fail("No filename specified")unless $filename;open(FD, $filename)|| return $class->fail("$filename: $!");# first line of file should contain field definitionswhile (! $line || $line =~ /^#/) {$line = <FD>;chomp $line;$line =~ s//r$//;}
如果你具备perl代码审计经验,就会了解使用上述只有两个参数的open函数来打开文件进行操作是不安全的。如果加上管道命令 | 后,open函数将会把它的其余部分解释为命令调用,加之由于我们可以控制文件名变量$filename,所以可以用这种方法来实现命令执行。
通过构造一个模板文件,在调用了 DATAFILE 插件后,就可导致任意命令执行,如下:
可以看到构造文件中的命令成功创建了预想的/tmp/COMMAND_INJECTION/目录:
该漏洞被相继发现披露后出现了各种exploit,但如Craig Yong在文章中说到的“需要注意的是,某些Payload会导致Citrix NetScaler过度记录错误,直到它填满/var分区”。大家可点此获取Exploit漏洞利用代码。
漏洞修复
目前,Citrix公布了详细的漏洞缓解措施,其中包含了具体的执行步骤,我们建议Citrix ADC用户及时参照该项措施进行修复。
此外,在针对设备发起的外界POST请求中,如果其中涉及到“/vpns/” and “/../”样式的字符串,且之后跟着一个对xml文件的GET请求,那么就可以直接把它判断为漏洞利用的攻击行为了。
以上就是如何深入分析Citrix ADC远程代码执行RCE漏洞CVE-2019-19781,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/221493.html