网络安全 频道

字符引发的信息安全问题

说到字符,很多用户也许会不以为然:小小的字符,不过是个非常基础的人机交互表达形式,它能产生什么威胁?但是,威胁偏偏就来自最原始的方面,并且这种威胁往往是最危险的,也是最难以防范的。


正如世界上有各种表达形式和书写格式不同的语言一样,在计算机的世界里同样存在类似的问题:在计算机发展初期,不同的计算机系统对字符的处理方式不同,这导致了各个系统之间不能互相交流。为了解决这个问题,人们制订了多种标准以便不同系统之间也能正确进行字符交互,这就是字符编码的由来。

由于字符可以通过多种途径进行表达,所以它们的编码也多种多样,常见的英文字符编码有ASCII、ANSI、Unicode、UTF、ISO等,对于非英文字符,常见的字符编码有GBK、BIG5、JIS等。可能有的读者已经开始不耐烦了:说了半天“编码”,到底什么才是编码?!

这里,我们用一个小例子帮助大家理解什么是“编码”。我们可以这样理解:一杯水无论放进什么形状的杯子里都还是水,而不会变成老虎之类的,这个道理很简单,对不对?那么同样的法则也适用于字符。对一个字符来说,无论系统内部怎么处理,只要最终显示出来的是原来的字符,那就没错。例如“小”字,Unicode编码把它作为“%D0%A1”存放,而ASCII编码里,它可以用“-12127”来表示,但是无论它怎么变,只要还能还原回“小”字,系统的处理工作就不会出问题(图1)。



多种编码的产生本来是为了解决字符信息的交互问题,然而正是这些多种多样的编码导致了让人意想不到的后果。字符,这个不起眼的小东西在编码的世界里举起了“大刀”,这使得上面提到的“水变成老虎”成为可能。


字符威胁实录

在接触计算机不久的时候你听说了一个词“ASCII”;到了Windows 2000开始流行的时候,你知道“Unicode”帮你解决了不少乱码问题;当你成为计算机高手以后,你常常会跟“SQL”玩个不亦乐乎,可是你知道吗?在这些你所熟知的字符或编码背后,隐藏着什么样的危险吗?你知道这样的危险就在你身边吗?


控制符:想说爱你不容易

ASCII全称American Standard Code for Information Interchange(美国信息互换标准代码),是最基础的字符表达方式,它能完整表示26个英文字母、10个数字以及通用的格式符号等。ASCII又分为控制字符和可显示字符(也称为“Printable”,即可打印字符),通常情况下,控制字符只能由特殊按键和系统自己产生,而且这些字符中的大部分是我们看不见的。但是你千万不要以为看不见即不存在,恰恰相反,它们时刻存在!例如,在你保存一个文本的时候,系统就会自动在文件结尾添加一个你看不见的结束符号,这个符号的作用就是用来告诉处理程序,读取到这里的时候:停!专业说法可以称之为文件结束符。

不幸的是,上面提到,ASCII控制编码并非只有系统自身可以产生,用户也可以通过特殊的输入方式成功地输出一个键盘上打不出来的特殊字符,这就可能会造成极其严重的后果。老一辈的论坛管理员也许还记得国内那次恐怖论坛攻击事件:很多论坛的帖子在一夜之间全部丢失!可是论坛却没有被入侵过的痕迹,服务器也完好无损,难道见鬼了?!后来,有人仔细查看了论坛日志文件,原来是入侵者用一个特殊符号发了一个帖子,这个符号让处理程序读取文件时误认为文件到这里就结束了,而控制符号是不会显示出来的,所以论坛程序只能认为这“惟一”的帖子格式不对,于是论坛停止了文件读取,在我们看来,即很多论坛帖子被删除了。但是事情仅仅是这样就结束了吗?入侵者只是发了一个控制符号导致了论坛读取错误,然而数据还是在的,只要去掉这个字符就可以恢复了。有人会笑了:小儿科的把戏!不过,别急着下结论,如果那么轻易就结束游戏,管理员就不会哭了:由于这个控制符号的存在,一旦有人写入新的数据,那么在这个帖子后面的所有数据将被清空!因为系统认为文件到这里已经结束了,那么后面的数据将会怎么样?结局只有一个:被全部清空!这时候,破坏论坛的就不再是入侵者了,而是那些热心过头急着发帖问“啊!论坛被黑了!”的成员们了,这个游戏好玩吗?一个字符,歼灭论坛(图2)。



是不是开始有点畏惧字符了?不敢再小觑它了吧?更可怕的事情还在后面。


Unicode:管理员的噩梦

许多人对Unicode的认识是从著名的“IIS Unicode”二次编码漏洞开始的。但是具体什么是Unicode,这就不是所有人都知道的了。Unicode常常被翻译为“万国码”或者“唯独码”,后者也许是来自Unicode发明者的宗旨:“推进多文种的统一编码”。Unicode同现在流行的代码页最显著不同点在于:Unicode是两字节的全编码,对于ASCII字符它也使用两字节表示。普通代码页是通过高字节的取值范围来确定字符是ASCII码,还是汉字的高字节。如果发生数据损坏,当整篇文字某处内容被破坏,则会引起其后汉字的混乱。Unicode则一律使用两个字节表示一个字符,最明显的好处是它简化了汉字的处理过程。

Unicode编码标准的出现让各种系统之间的交流变得简单,然而正如爱情是把双刃剑那样,Unicode也会伤人的。

问题出在Unicode对字符的解码上,它的算法让一个字符可以通过多种编码格式产生,于是入侵者可以采用“旁门左道”产生一个非标准编码的路径符号。例如“%c1%1c”,通过Unicode解码公式解析出来的字串为:%c1%1c->(0xc1-0xc0)*0x40+0x1c=0x5c=“/”。我们知道,IIS在打开文件时,如果该文件名包含Unicode字符,它会对其进行解码,如果用户提供一些特殊的编码,将可能导致IIS错误地打开或者执行Web根目录以外的文件。在这里,IIS并不知道这个是路径符,就直接发出了处理请求。于是,入侵者攻击者利用这个漏洞绕过了IIS的路径检查,进入了系统(图3),这就是著名的“IIS Unicode”二次编码漏洞攻击原理。



论坛:天生和字符有仇

如果有人专门去阅读一些论坛的文件内容,会发现它们里面都会有一些代码专门用来处理字符,这部分代码的工作叫做“字符过滤”。为什么呢?因为有太多字符都能对论坛造成伤害,这些字符不一定需要特殊编码,甚至我们正常敲出的文字里都有可能包含被论坛作者定义为“危险”的字符。究其原因,就是因为论坛程序的特殊性,因为它们工作在服务器和外界的接口处,而且自身也是由纯字符组成的,但是一些看似正常的字符会“不小心”改变了它们的逻辑,这是连论坛作者自己可能都没想到的。例如,一些论坛的功能设置部分会涉及文件读写,因此有必要加上权限盘查。但是如果作者编写的权限检查代码忽略了某些特殊字符的输入,结果就会让入侵者成功地往系统中写入一个文件。LB5000论坛就曾经出现过一个重大漏洞:它的界面设置模块对用户权限的盘查不严谨,其中一个字符输入没有经过身份验证,而这个设置会产生一个可以让论坛程序执行的文件用于临时保存界面配置数据,于是入侵者通过以下格式写入一个简单的内容:setskin.cgi?membercode= ad&action=process&printme=use%20CGI%20qw(:standard)%3bopen(HBU,param('a'))%3bprint%20HBU%20param('b')%3b,这样就能完成对论坛的写操作。让我们简单地看看这段代码。这个代码产生了一个包含以下有用内容的leoskin.cgi文件:

use CGI qw(:standard);
open(HBU,param('a'));
print HBU param('b');

懂Perl语法的用户一眼就能看出来,这是一段简单的写入文件代码,入侵者只要用“leoskin.cgi?a=>[文件名]&b=[内容]”格式的语句就可以向论坛写入文件。

到这里也许有人还不明白:写个文件有什么了不起?别忘了,LB5000论坛是基于文件的,它的所有东西都是文件,包括管理员账号。既然我们能写文件,那么只要想办法写入一个管理员账号文件,这下了不起没有?利用这一点,入侵者还可以写入一个执行命令的文件——WebShell,进而控制整个服务器!

近期DVBBS论坛最热的一个漏洞就是UPFILE漏洞,这个漏洞为什么得以成功呢?是简单的字符起的作用!有谁不能用十六进制处理工具把里面那个关键的空格改为结束符而成功入侵这类论坛呢?!这又是一个“小”字符摧跨“大”堤坝的典型案例。


SQL:你的“针管”在哪里

说到字符就不能不提一下大名鼎鼎的SQL了,其实很多论坛过滤字符最大的原因也是因为SQL,这个不能称之为漏洞的“结构化查询语言”让“AND”、“OR”等最为简单的字符成了危险的代号。

由于ASP的特性,入侵者在一个连接数据库操作的URL里加入“ AND SQL语句”会让IIS执行这个URL里的SQL语句,于是服务器的噩梦又来了。通过SQL能做什么呢?最简单的是猜测密码(比如免费下载电影或者享用付费用户才拥有的服务),如果服务器的权限设置不好,入侵者能直接用SQL执行任何系统命令!包括清空整个数据库的全部资料(图4)!



奇怪的编码:格式化字符

如今,“溢出攻击”已经成为攻击的主要方式之一,广大用户或多或少都会听说过“Shell”这个名词,有兴趣的人可能还看过一些溢出程序的代码。很多人都会产生出这样的疑问:每个溢出程序代码里都会发现的那一串甚至几串用路径符和类似十六进制代码表示的字符串,那是什么?

要说明这个问题,必须先知道C语言对字符的处理方法。在C语言中,写一行代码向屏幕打印字符并不是简单地向屏幕输出字符串,能在屏幕显示的字符实际上是经过函数转换的“打印格式”字符,C语言提供了一种格式化字符,它允许程序员控制显示文本的样式,我们可以通过代替特殊的格式字符来显示值或数据。例如“printf("The value is %s",sVal)”,其中“%s”就是格式化字符,它自身不能用做显示,而是告诉系统,按照“字符串”的格式把sVal的值放进整个字符串,这就像一个蛋糕模子,它固定了一种样式,你做出的蛋糕就只能是这种样式了。

然而问题又来了,“格式化字符”的存在,让溢出攻击成了现实。攻击者用十六进制编码向内存写入攻击代码,并按照一定格式编排格式化字符,让系统执行到这些字符的时候不再按照原本的程序思路执行,而是扭转到攻击代码所在的内存位置,这就导致了“溢出”(Overflow)。程序就有可能执行到攻击者写入的命令,这像什么呢?就像一块过分膨胀的蛋糕,虽然你的模子是没有问题的,但是蛋糕烘烤的时候,它涨出了原有的空间,这样出来的蛋糕自然不会是你喜欢的样子。同样的情形发生在计算机内存里,就是一组指令涨出了它的“模子”,并且有一部分流入烤箱底部被烤糊了。例如,类似于“\x55\x8B\xEC\ x33\xFF\x57\xC6......”的攻击代码,它是一组用十六进制格式符隔开的指令,当它写入内存后,实际上是产生了一组可以让系统执行的“正常”代码,像是运行CMD.EXE,但是这组指令并没有指向它们的执行代码,所以通常情况下,它们即使被写入内存也只能是废物一堆(烤糊的蛋糕,你能吃吗?),如果要让它们起作用,怎么办呢?这时候就需要格式化字符的帮助了,通过执行一段特殊的包含格式化字符的代码,程序指向了包含攻击指令的内存位置,于是攻击指令生效了(图5)。



防御字符威胁

由于字符问题由系统内部产生,我们无法把它消灭,只能通过“后天”的修补来解决问题。最安全的方法就是在我们的程序里加入防护代码,并给系统打上补丁,这样才能尽量避免来自字符的攻击。

很多公司都有因为电脑被入侵而遭受严重经济损失的惨痛经历,不少普通用户也未能避免电脑被破坏的厄运,造成如此大损失的并不一定都是技术高超的入侵者所为,小小的字符串带给我们的损失已经太多。因此,如果你是数据库程序开发人员、如果你是系统级应用程序开发人员、如果你是高级计算机用户、如果你是论坛管理人员……请密切注意有关字符漏洞以及其他各类漏洞的最新消息及其补丁,及时在你的程序中写入防范最新字符漏洞攻击的安全检查代码并为你的系统安装最新的补丁会让你远离字符带来的危险。
0
相关文章