不可饶恕错误之输出未转义
技术与开发
编者语:金融危机的到来让许多程序员也受到影响,在这样的大环境下,程序员还有好的机遇吗?有!而且是非常大的机遇!当前移动平台的程序开发如火如荼,特别是在苹果、Google等推出了平台开发工具后,进入这一领域的程序员越来越多,有的是想赚一些外快,有的是想在移动平台上功成名就,成为马化腾第二。
机遇就在眼中,你整装待发了吗?在此之前,还有什么需要注意的?小编跟以前进入此领域的程序员们交流时,他们首先给出的是忠告,编程时要避免犯一些不必要的错误,留下安全漏洞,造成功亏一篑。那又有哪些错误是我们需要避免的呢?看了不可饶恕编程错误系列,你就可以正式“出征”了!
数动连线程序员许勇:其实手机编程容易犯的错误跟在PC平台上容易犯的错误有很多是相同的,因为有的编程语言是通用的,而且手机编程才上手时,很容易就会犯下平时在PC平台上不容易犯的错误。
这些错误会产生严重的后果,留下安全隐患。例如输出未转义错误,在需要网络通信的手机程序中存在的话,例如浏览器中,就可能弹出无数窗口,导致手机出现死机等症状。可以说,在手机编程中,如果犯下了输出未转义错误,是不可饶恕的。
未转义导致漏洞出现
什么是输出转义?它的意思是保持输出的信息原意不变。例如,数据库中存有网友输入的信息“</ br>”,如果该信息没有经过转义而直接输出到浏览器的话,它将会被解析成为HTML代码从而影响网页的布局。
但是我们并不想出现这样的后果,我们只想输出这个信息而不解析成HTML代码,这个时候就必须通过转义来完成本次输出,以保证本次输出的结果是“</ br>”的字符串。
下面,我们来看看恶意输入代码“<script>while(1=1){alert('OK!')}</script>”,如果没有进行输出转义,浏览器就会将这段信息当作JavaScript代码执行,弹出无数个对话框,导致访问者浏览困难。如果这样的错误出现在手机程序上,就会导致流量狂增,大大浪费手机话费。
典型未转义错误分析
原理容易懂,但是在编写具体代码时,还是容易出现未转义错误。下面我们来看两段典型的输出未转义的错误代码。
代码1:输出目标为浏览器
假如由我们来实现一个功能,网友输入用户名提交后,显示欢迎信息,其中关键代码如下:
<?php
$username=$_POST[username];
Echo 'HELLO!'.$username;
>
这段代码看上去没有问题,但是,在输出的时候却没有进行输出转义,这便会带来很多问题。假如在输入用户名的时候输入“<iframe src="http://www.xxx.com"><iframe>”这段代码,那么浏览器会把这段代码当作HTML代码处理,将网站www.xxx.com的内容嵌入我们的网站中,访问者访问我们网站的同时会访问到该网站,如果www.xxx.com是恶意网站,那么我们的网站便成为了传播恶意网站的介质。
那么我们如何来避免这种问题的发生呢?我们将需要输出的用户名进行输出转义就可以了,正确代码如下:
<?php
$username= htmlspecialchars($_POST[username]);
$username= htmlspecialchars($username);//保持输出信息的原意
Echo 'HELLO!'.$username;
>
函数htmlspecialchars会将一些特殊字符进行转义(如:&、<、>转义为&、<、&rt)这样输出的信息保持了原意,便不会造成输出错误了。
代码2:输出目标为数据库。
假如我们提交一个查询信息到数据库查询。其中关键代码如下:
<?php
$username=$_POST[username];
$sql = "SELECT * FROM `userinfo` WHERE username = '$username'";
$result = mysql_query($sql);
>
这段代码大家已经看出了问题,就是我们上期所讲到的SQL注入问题,造成SQL注入的问题就在于将信息输出到数据库的时候没有保持信息的原意。这里我们利用函数mysql_real_escape_string来避免这种情况的发生,保持信息的原意,正确代码如下:
<?php
$username=$_POST[username];
$username = mysql_real_escape_string($username);//保持输出信息的原意
$sql = "SELECT * FROM `userinfo` WHERE username = '$username'";
$result = mysql_query($sql);
>
函数mysql_real_escape_string可以将$username中的特殊字符转义,转义后的信息可以安全应用于数据库查询(mysql_real_escape_string() 并不转义 % 和 _)。
小编支招
怎样才能做到保持输出信息的原意不变呢?首先,我们在编程的时候,必须清楚地知道每一个向外部系统输出的目标(如:是输出到浏览器还是输出到数据库),然后根据所传输信息到不同的系统而采用不同的方法。
对于一些常见的输出目标(包括客户端、数据库和URL)的转义,编程语言中有内置函数可用(如PHP的htmlspecialchars、mysql_real_escape_string)。大家也可以写自己的算法,但一定要做到万无一失,要找到在外部系统中的特殊字符,以及它们的表示方式,将特殊字符一一转换为表示方式,以保证输出信息原意不变。