Perl数据类型安全研究【翻译】

0x00 背景


enter image description here

前几天有个人在某大会上讲了一个在perl中存在了20年的问题。作为一个只会perl不会python的人,真的很心痛。看完视频后感觉被黑的吃不下东西。

这俨然就是一场对perl的吐槽批斗大会,整个演讲充满了sucks、fuck等和谐词汇,也能看出演讲者是多么的义愤填膺,场下一次次的鼓掌和附,嗯,让我想起了郭德纲。

0x01 问题


enter image description here

言归正传,这个在perl中存在了20年的问题到底是啥呢?抛去perl的语法的槽点,真正的问题在data types上,对的,就是数据类型。

Perl对数据类型的处理真是有点匪夷所思了。

我们先了解一下perl中的变量有哪几种。

perl中的变量

perl的数据类型分为三类:标量$,数组@,哈希%。

具体定义在这里不多说,我们来看几个例子:

enter image description here

不管是标量、数组还是哈希(字典),定义跟其他语言没什么区别。

enter image description here

我们来看看几个特殊的情况,下面每个预期值为正常人类理解应该得到的结果。

#!perl
@array =(1, 2, 'a', 'b', 'c');
print $array[0];

预期值 1

enter image description here

实际值 1

#!perl
$scalar = (1, 2, 'a', 'b', 'c'); 
print $scalar;

预期值 1

enter image description here

实际值 c 我擦泪,为毛会是c!太不科学了,继续往下看。

#!perl
@list = (1, 2, 'a', 'b', 'c'); 
print scalar @list;

预期值 1

enter image description here

实际值 5 呵呵,他把数组的长度输出了。

再看看这个哈希的例子

#!perl
%hash = (1, 2, 'a', 'b', 'c'); 
print $hash{'a'};

预期值 木有

enter image description here

实际值 b 为毛把b给输出了,谁能告诉我这头草泥马是怎么处理的。

0x02 漏洞


这些问题会产生什么漏洞呢?

一起看看在web中php跟perl处理的对比。

enter image description here

enter image description here

这么看来是木有任何问题的,那么使用复参的时候呢?

enter image description here

php很好的处理了传入的数据,而perl的做法就是草泥马在奔腾%>_<%他是直接可以传入数组的。

再深入一下,看看当数组和哈希结合的时候的情况。

#!perl
@list = ('f', 'lol', 'wat');
$hash = {'a' => 'b',
         'c' => 'd', 
         'e' => @list
};
print $hash;

预期值

#!perl
{
'a' => 'b',
    
'c' => 'd',
    
'e' => ['f','lol','wat'] 
} 

enter image description here

神马情况,数组中的“,”变成了“=>”又给赋值了?e=>f、lol=>wat,what the f*cuk!

enter image description here

这是多大的一个坑啊!看Bugzilla是怎么掉进去的。

http://zone.wooyun.org/content/15628

关于数据类型的这些问题我不想再说了,有些恶心。

0x03 GPC的问题


enter image description here

enter image description here

屌屌的棒棒的,对吧,可是……

enter image description here

我了个*,一个都不给转义了,就这么罢工了,可以顺顺畅畅的注入了好么。

enter image description here

我想静静。

0x04 来源


Pdf:

http://events.ccc.de/congress/2014/Fahrplan/system/attachments/2542/original/the-perl-jam-netanel-rubin-31c3.pdf

视频地址:

http://media.ccc.de/browse/congress/2014/31c3_-6243-en-saal_1-201412292200-the_perl_jam_exploiting_a_20_year-old_vulnerability-_netanel_rubin.html#video

©乌云知识库版权所有 未经许可 禁止转载


30
Crise 2016-02-02 18:24:00

这些容易出错的地方 明眼人的预期就是和实际的值相同,perl对上下文环境敏感 根据你所吐槽的这些内容在perl实际应用中根本就不存在
%hash = (1, 2, 'a', 'b', 'c'); #比如说这个 预期的值就是b阿,hash是成对出现的 也就是说相当于 %hash = (1=>2,
'a'=>'b',
'c' =>''

);
print $hash{'a'};
预期值 也就是b啦,这是根本没用过perl的人在台上竭力吐槽么?

30
cnhacktnt 2015-04-09 08:27:25

敢黑我大 Perl

『演讲者是多么的义愤填膺,场下一次次的鼓掌和附』

演讲者是个逗比吧, 二货处处有,国外也很多。

30
helen 2015-02-28 14:00:51

那个带Load URL的工具是什么

30
px1624 2015-01-09 15:58:41

这图是骆驼还是草泥马?

30
乌帽子 2015-01-09 11:51:30

各种奇葩的配图啊

30
Jea 2015-01-08 12:51:33

Perl是很灵活的语言,但太灵活了,导致一些使用者不知其然,不知其所以然!如同大家所知道的,让你去照顾另一个人用Perl创造的生命!理解不了结果就是使用出错,不知道Larry Wall会不会理他

30
gainover 2015-01-08 11:50:49

原pdf里几个例子还确实蛮经典的

30
Perler 2015-01-07 17:26:35

不是 bind,是 execute 。估计你这是头脑中和起端口的概念混了。。。

30
kkk 2015-01-07 11:19:11

微博跑过来的,就知道肯定要被喷了。虽然不精通perl,但真的还是用过一段时间的,感觉灵活度很高。文主的基础有点令人堪忧啊

30
tanjiti 2015-01-07 10:28:34

我认为
@list = (1, 2, 'a', 'b', 'c');
print scalar @list;
等价于
$b = @list = (1, 2, 'a', 'b', 'c');
print $b;
所以说在
【在标量上下文环境中的列表赋值操作,会返回赋值操作符右边元素的个数】

flw有句话是赞同的,这是perl的特性,灵活但容易出错。

30
瞌睡龙 2015-01-07 10:20:53

这说的是,作者列举的perl特性可能很多perl程序员不会意识到会有什么问题,也可以看出Bugzilla都踩进去了一个坑,导致了一个很严重的漏洞,一个语言如果你研究的很透彻了会避免产生这种问题,但我觉得语言的本身应该降低理解门槛。至于DBI注入的问题,很多程序员的第一想法应该就是你本身做了防注入处理我可以安心使用了,再传参进去竟然就可以安心的闭合单引号进行注入,这个问题明显也是没有考虑周到。

30
s0mun5 2015-01-07 10:10:23

论一个程序员的自尊,哈哈,我只是翻译而已,大神们来骂我干嘛?

30
lxj616 2015-01-07 10:08:36

数据类型本身没有问题,但如果开发者对perl理解不够深入,就容易发生问题,文章说的并不是perl本身有逻辑错误,说的是容易被误用而导致漏洞的语言难点

30
c0lc 2015-01-07 09:52:33

这水平堪忧啊

30
winsyk 2015-01-07 09:42:08

-_- 居然把flw大神都引来了

30
就是 2015-01-07 09:28:06

看了前2个就笑喷了,还说只会perl,我看是只会perl的拼写吧
,只说明一下:
$scalar = (1, 2, 'a', 'b', 'c');

($s0mun5,$is,$sb) = ('s0mun5','is','sb');
sprintf('%s %s %s',$s0mun5,$is,$sb);
有异曲同工之妙

30
Perler 2015-01-07 00:19:11

不要说大骆驼,即使好好读遍小骆驼也不至于出来现眼。。。

30
flw 2015-01-07 00:11:49

亏这帖子还是发在【乌云】上呢!!!
用拼接字符串的方式生成 SQL 这就是一切 SQL 注入漏洞之源!!!

为什么不用 prepare 然后 bind 参数的方式?
不管是什么编程语言,你只要涉及到数据库操作,
你就记住,你不要拼凑 SQL 语句,而是留占位符,prepare,然后 bind,就不会有任何问题了!

30
flw 2015-01-07 00:09:20

你一开始写的完全不对自己意识到了就姑且不论了。
后来你纠正了一次还是不对:
你第二条提到的 print scalar @list 根本不是什么【在标量上下文环境中的列表赋值操作】,这里的列表赋值操作是妥妥的列表上下文,没有任何问题。在标量上下文的不是列表复制操作,而是【数组】,数组在标量上下文中返回它的元素个数(长度),没有任何问题 —— Perl 就是这么设计的。

30
flw 2015-01-07 00:06:31

楼主就你这水平也好意思说自己“只会 Perl”?
连基本的赋值语句都没搞明白就出来混了?

30
wostis 2015-01-07 00:00:54

无脑黑,基础都没学好就在这跟风黑,这就是只会perl的水平?

30
3xpl0it 2015-01-06 23:19:44

静看骆驼了

30
泳少 2015-01-06 23:11:46

valo别闹!!!

30
winsyk 2015-01-06 21:46:06

MM 说的是。

30
tanjiti 2015-01-06 19:36:07

纠正我说错的地方:
没有得到预期的值,是因为混淆了列表、数组、散列之间的区别

1.
$scalar = (1, 2, 'a', 'b', 'c');
print $scalar;

输出结果'c'的原因是
逗号操作符在标量上下文中会返回最右边的元素

2.
@list = (1, 2, 'a', 'b', 'c');
print scalar @list;

输出结果5的原因是
在标量上下文环境中的列表赋值操作,会返回赋值操作符右边元素的个数

3.
%hash = (1, 2, 'a', 'b', 'c');

print $hash{'a'};
输出结果b的原因是

列表赋值给散列时,会按key,value,key,value,key,value...的方式映射
%hash实际是
'1'=>2
'a'=>'b'
'c' 单了

30
tanjiti 2015-01-06 18:33:58

讨厌说perl坏话
我来解释一下
@list = (1, 2, 'a', 'b', 'c');
print scalar @list;
为什么会是c

上面的语句等价于
perl -e "print scalar(1,2,'a','b','c')"
而逗号操作符在标量上下文中会返回最右边的元素

p.s.文章还没看完,但讨厌说perl坏话,讨厌

30
Matt 2015-01-06 17:17:57

复参的问题 apache本身对复参只取后面的value.并不是php的问题。

30
shawshank 2015-01-06 17:17:48

我只想说草泥马和骆驼是两个物种...

30
Net 胡来 2015-01-06 16:09:07

静静是谁...

30
肉肉 2015-01-06 15:25:32

第一次看到这么可爱地阐述观点的文章,被萌哭

30
story 2015-01-06 15:15:23

为毛这么多草泥马

感谢知乎授权页面模版