您的位置:首页 > 其它

PERL 5.8的反序列化

2016-02-17 10:08 211 查看
0x00 文章简单翻译

在做渗透测试的时候,我发现有个应用程序包含了form表单,其中有一个经过base64编码的hidden属性的参数名叫"state",包含了一些字符串和二进制数据。

?
我打开了burpsuite的Intruder,做"Character frobber" fuzzing测试。通过返回的结果,我发现了一些有趣的东西。如图1:



页面返回的结果里暴露了目标使用Perl和Storable 2.7,经过Google搜索,我知道Storable是Perl的一个模块,是用来做数据序列化的。查看Storable的官方文档我们可以看到有个很大的安全提示:

Some features of Storable can lead to security vulnerabilities if you accept Storable documents from untrusted sources. Most obviously, the optional (off by default) CODE reference serialization feature allows transfer of code to the deserializing process.
Furthermore, any serialized object will cause Storable to helpfully load the module corresponding to the class of the object in the deserializing module. For manipulated module names, this can load almost arbitrary code. Finally, the deserialized object's
destructors will be invoked when the objects get destroyed in the deserializing process. Maliciously crafted Storable documents may put such objects in the value of a hash key that is overridden by another key/value pair in the same hash, thus causing immediate
destructor execution.

有关这个安全问题,youtube上有个叫“ Weaponizing Perl Serialization Flaws with MetaSploit”的视频,作者还把相关代码放在了github(https://github.com/lightsey/cve-2015-1592),有了前人的经验,我想再应用到我的渗透项目里,应该不是太难:),但是经过一些测试后,我发现我不能按照前人的经验来应付我现在的渗透场景,Storable默认使用跨平台的nfreeze()函数来做序列化。例子代码如下:

?
当运行这段代码的时候,报错如下:

?
通过报错信息,我认为通过控制"foorbar"字符,尝试注入";",或许可以注入恶意的Perl代码来运行:D,为了验证我的想法,我通过https://metacpan.org/source/AMS/Storable-2.51/Storable.xs查看源码,结果却很失望。

?
通过在Storable.xs源码里搜索“No STORABLE_thaw defined for objects”报错信息,定位到了4388行的load_module(PERL_LOADMOD_NOIMPORT, newSVpv(classname, 0), Nullsv);这里仅仅调用了load_module(),并没有我想要的requrie功能,但是视频里不是这么说的,我又查看了2.15版本的Storable.xs源码https://metacpan.org/source/AMS/Storable-2.15/Storable.xs,经过源码对比,发现2.15版的Storable第4297行,多了
perl_eval_sv(psv, G_DISCARD);

?
可以看到,object名(package名后面的字符)直接传入了perl_eval_sv()函数。Perl >=5.10以后会使用新的载入机制,所以不受该漏洞影响,而我的目标运行在Perl 5.8,5.8版的Perl在许多老的Linux发行版本(像 RHEL/CentOS 5)是默认安装的,是受此漏洞影响的。这里我只要把我的payload放到object名后面就可以了,我可以载入"POSIX"模块,然后通过eval()来运行系统命令。但是这里需要注意的object名的长度是252字节,但也足够我们写payload了。假设我想通过dns来获取返回信息,payload可以这样构造:

?
payload可以构造的很短,比如通过User-Agent来获取命令,然后放入POSIX模块的eval()执行

?
这里还有一个技巧:如果目标的CGI是不显错的,我可以通过CGI:Carp的fatalsToBrowser来把正常输出和报错信息都吐给浏览器,来实现一个简单的webshell。

我这里提供了http://www.agarri.fr/docs/victim和http://www.agarri.fr/docs/PoC_thaw_perl58.pl用来做测试练习。

0x01 本地实际测试

我的测试代码如下:

?
如果只是本地测试,可以使用perlbrew来切换perl5.8.9和kali 1.10自带的perl 5.14.2,测试结果如图2所示:



可以看到perl 5.8.9是受漏洞影响的,而perl 5.14.2没有受影响。

接下来在测试下perl cgi,代码就用作者提供的http://www.agarri.fr/docs/victim,作者提供的POC需要稍微改改,要不然获取不到命令执行结果,测试结果如图3所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: