上一篇文章中介绍了GBK字符集下的安全问题,并举了SQL注入的例子。这个安全问题同样存在于前端,我们可以使用同样的方式把代码注入到JavaScript中制造出XSS攻击。所以在程序出现乱码时就要小心了,会出现乱码的程序都可能存在安全隐患。
比如我们有个这样的程序
<?
header('Content-Type: text/html; charset=gbk');
$log=addslashes($_GET['log']);
$log=str_replace('/','\\/',$log);
$log=preg_replace('/\r\n|[\r\n]/','\\n',$log);
?>
<script>
console.log("<?=$log?>");
</script>
这个程序转义了很多字符,但是我们依然可以通过GBK的方式绕过一个反斜杠来注入代码,从而实现XSS。 ?log=%81");alert(String.fromCharCode(0x6B21,0x78B3,0x9178,0x94B4));<!--
虽然斜杠被转义使我们无法使用JavaScript注释去屏蔽后面的东西,但是JavaScript中的HTML注释一样可以起到单行注释的效果。这里在内容部分只是用alert弹出一个字符串,实际情况可能会用上eval去执行一个字符串中的代码。而字符串是用formCharCode从Unicode直接解析的,不需要用到引号。
非法字如果允许存在页面上,他们就会呈现出乱码。当一个网页出现乱码是就意味着服务器很有可能没过滤非法字符,很有可能存在各种漏洞。当年百度贴吧的程序就是如此,以至于XSS横行。如今它对字符的过滤已经非常严格了,甚至连繁体字都要被转换成简体字。这些大网站是被攻击到怕了才修复的,对于一些小网站,这种漏洞还是很普遍的。
如何避免呢?很简单,不要用服务器程序动态生成客户端程序就行!这么做本来就不符合科学发展观!需要数据的话你可以生成专门的标记(例如META、SCRIPT)来储存,htmlspecialchars函数是安全的。或者直接用Ajax或其它通信方式获取。总之服务器程序动态生成客户端程序的做法就不该在正规项目中出现!