网络安全已经成为互联网最热门的话题之一,与现实相对应的,网络安全的部属、实现也就成为一个企业特别关心的问题。所以,现在我们可以很容易的看到各个企业在设计自己网络、构建企业网站的时候,对于网络安全的投入还是比较大方的,特别是一些敏感信息比较多的网站,比如银行、证券等企业,对于网络安全更是不遗余力,市场上各种宣传、广告,也都大力推广各种安全产品,比如防火墙、入侵检测、企业防病毒等一系列的产品。但是,是不是使用了这些产品,网络特别是网站就真的安全了?不一定,即使这些安全设备最高档、设置也很合理,网站还是有被攻击甚至完全被控制的可能。我们知道,现在的网站特别是稍微大一点的网站,一般都采用ASP、PHP或者JSP等脚本语言来连接数据库,取得数据库里面的数据生成动态网页,这样,当一个网站完全建立的以后,程序就会很多,特别是网页设计的特殊性,服务器与用户的交互程序特别多,所以,如果程序员不是很有经验或者没有强烈的安全意识,程序的漏洞就会很多,给网站带来不可估量的安全隐患。这些程序漏洞,一定程度上,可能比网站服务器的漏洞更加严重,因为这些漏洞防火墙或者入侵检测系统根本无法防止。
一、编程漏洞的形成
编程漏洞怎么形成的呢?我们需要对网页编程有比较全面的认识才可以理解。首先,我们来看看网页编程的特点。
1、网页编程交互性强
之所以采用各种语言来设计网站而不直接采用HTML,目的就是为了更好的管理网站资源,增加网站与浏览者之间的交互。所以,在网站设计的时候,一些常见的交互编程是少不了的,比如留言版、BBS论坛,聊天室等,这些程序最大的共同点就是用户输入很多资料,通过这些资料与其他浏览者交流或者与网站管理者交流。而交互的特点,正式漏洞形成的一大原因,因为用户输入信息是不可预测的,如果程序没有考虑到或者考虑不全面一些安全问题,用户输入就有可能成为攻击事件,不管有意还是无意。
2、网页编程字符处理特别多
上面我们谈到,交互其实就是信息的流通。所以,这些信息的处理就是大问题,怎样严格控制用户输入信息的内容、信息格式、信息长度都是编程需要考虑的问题。
3、网页编程涉及安全最里层
我们知道,网页编程直接和服务器打交道,这些程序都是直接和网站目录、网站数据库设置网站设置、系统设置相关,通过这些程序,可以访问网站目录、设置等几乎所有服务器内容。仔细想,这些程序其实都是很有潜在安全问题的,因为它们太敏感了。所以,如果程序设计有漏洞,几乎就等于网站有漏洞,甚至完全开放。
4、网页编程整体人员基础较差
网页编程人员的技术素质,这个问题其实我们可能比较少关注。在部分传统程序员眼中,网页程序设计其实不能称为程序员,他们认为网页程序设计,只需要美工好就可以了,完全没有技巧可言,不叫真正的编程。之所以形成这种观点,有几个原因。一是网页编程相对比较简单,变化较少,基本上,网页编程可以很简单的概括出几个类型:留言版、论坛、聊天室、邮件列表、新闻发布、软件下载等,而这些类型的编程,大部分都有模式可循,和传统编程相比,的确比较简单,任意掌握;二是网页编程人员大部分半路出家,专业的程序员相对较少,编程的系统训练较少,可能编程的基础也比较弱,所以,编程方面可以还是有一些缺陷的;三是部分网站直接下载网上免费程序来建立网站,这些程序的健壮性、安全性都没有严格考虑,如果网站采用者不自己修改这些程序而直接照搬得话,很可能存在严重安全问题。
二、编程漏洞的类型
网页编程相对比较简单,漏洞的形成实例虽然很多,但是,都有一些内在地共同点可以寻找,以此归纳出一些共同的特点,供我们参考。
1、用户输入验证不全面
在网站编程而言,有一个规则可能我们需要牢记,那就是对于用户和用户的输入,都必须抱怀疑态度,不能完全信任。所以,对于用户的输入,不能简单的直接采用,而必须经过严格验证,确定用户的输入是否符合输入规则才可以现实、录入数据库。总结用户输入验证,应该包括以下几个方面。
(1)输入信息长度验证
这一点可能我们比较少注意,因为我们往往认为一般用户不会故意将输入过分拉长,稍微有一些用户可能捣乱,但是,在这一点上可能没有危害。其实,只要我们仔细考虑,如果不进行输入验证,可能的危害会相当大,为什么?如果用户输入的信息达到几个兆,而我们的程序又没有验证长度的话,想想的危害就有:a、程序验证出错;b、变量占用大量内存,出现内存溢出,至使服务器服务停止甚至关机。这样的危害多大?
(2)输入信息敏感字符检查
这一点平时在设计程序的时候我们可能都有注意,主要关注的是一些javascript的敏感字符,比如在设计留言版的时候,我们会将“<”等符号的信息去除,以免用户留下页面炸弹。但是,是否这些就已经足够了呢?还远远不够。我们还有很多没有注意到,以下几个方面我们需要特别注意。
a、留言版内容信息的过滤
这一点上面已经提到,平时也使用较多。
b、用户名信息的过滤
这一点其实我们常常验证,但是,用户名的验证我们往往只是验证长度,没有验证JavaScript或者HTML的标记,这样就容易形成漏洞。比如用户在用户名填入“<h1>黑</h1>”,一般的用户名验证都可以通过,但是,显示在网页中却是很不美观的。这个输入没有破坏,但是,如果用户名验证不严,没有长度限制,后果怎样呢?这样的漏洞在网上很多!
c、Email信息的验证
Email信息我们往往也只验证是否含有“@”符号,其他没有限制,容易形成两个漏洞:一是输入信息过长的内存溢出漏洞;二是含有JavaScrript等字符信息,造成显示用户Email的时候形成页面炸弹等。
d、搜索信息的验证
搜索信息也要验证吗?当然要验证!尽管搜索信息不会直接保存到网站服务器,但是,搜索信息确与数据库或者服务器所有文件密切相关,如果搜索信息有问题,很容易就会暴露一些本来不应该暴露的数据库信息或者文件信息。而且,如果用户对程序比较了解,那么这种情况就更加需要注意,用户可能会利用对于程序的了解,来设计一些很特别的搜索信息,而这些搜索信息其实是会检索其他不应该检索的数据库表的,必然,用户账号密码表等。因此,那些从网上下载回来的程序,一般不适宜于直接使用,因为它们的原代码都可以被所有人知道,安全性当然不是很好。在这种情况下,我们一般验证一些常见的用于数据库操作的语句,必然搜索信息是否含有“Select”等,这样来限制用户输入,避免信息的泄露。
2、页面行为方式缺乏逻辑
可能这一点看起来很不好理解,页面行为方式是什么呢?我们现在举例说明。在一般的网站中,注册新用户的时候,一般会首先要求用户输入自己需要注册的账号信息,以此来验证该账号是否已经存在,确保用户的单一性。这样的要求,网站编程者的考虑很好,必然新浪注册新用户的时候,就是这样要求的。然而,如果编程不谨慎,却容易造成一个很大的漏洞,致使用户信息流失、出错等情况的发生。这种情况怎样产生的呢?其实很简单,这些页面在编程的时候,认为如果用户的注册信息通过了刚才我们提到的“检测时候存在该账号”,那么,程序就认为这个账号一定不存在,可以注册,在真正的注册页面中,直接使用“Insert Into”语句将注册信息插入用户数据库就可以了。仔细看看这样的注册过程,我们发现有一个大的漏洞,那就是,将注册信息插入数据库之前,并没有再一次检查这个用户是否存在,而是很简单的信任前一个检测页面传来的账号信息。我们知道,HTML文件是可以阅读源代码并且也可以直接保存的,如果用户将注册通过的页面保存并且将上面的账号信息修改为一个已经存在的账号,由于程序认为该账号已经通过检测,于是,直接将该账号插入数据库,结果,原来拥有该账号的用户就被删除或者信息被修改了。而如果这个账号刚好是一个管理员账号,结果会怎样呢?
可能我们认为以上的情况很简单,的确简单,但是这种方式编程的程序员却很多,随便在网上找,我们可以找到很多这种方式编程的源代码和已经采用的程序。
以上就是就是页面行为方式缺乏逻辑的典型举例,还有没有其他的举例呢?我们大家都很熟悉的一个例子。在电子商务初期,一些电子商务网站的程序很多存在这样的漏洞,用户可以随意定义自己购买商品的价格!其实也就是这个原因造成的。
3、编程方式不成熟
很多时候,我们可能根本没有意识到一些漏洞的产生,这时候,不是我们没有注意安全问题,而是我们缺少经验。这种情况,我们就需要多了解一些网络攻击者的进攻方式,以此来修改程序,加固网络、程序安全。我们已经知道的一些漏洞就是这种情况产生的。在一些账号密码验证中,有万能密码的存在就是这样产生的,在下面的举例中我们会详细介绍。
4、没有基于内容的检测
上面第一条我们提到检测的漏洞,这里,我们专门提出基于内容的检测。前面多是技术上的考虑,这里,确实基于国家法律法规的考虑。一个网站的设计完成,除了技术的完善以外,还需要这个网站在国家法律法规内发布信息,不能随意让自己的网站成为一些别用心的人发布不法信息的平台。所以 ,我们有必要对所有用户输入而且有可能显示给其他用户的信息进行内容检测,一般有几类:
(1)粗话的检测,一般我们检测一些常见的粗话;
(2)敏感词汇的检测,必然“法轮”“明慧”等这些词;
(3)关系政治的词汇,最好全部过滤,比如“共产党”等;
(4)国家领导人的姓名,最好过滤;
当然,以上的一些规则,不一定全部要这样,可以根据自己留言、或者论坛的性质来决定那些需要严格过滤。
三、攻击实例
以下的实例,可能网络上有些网站刚好存在这些问题,希望存在问题的网站能够及时修改程序改正,读者也不要利用这些漏洞做不符合国家法律法规的事情。
1、万能密码
这个漏洞,一些读者可能已经知道,但是,由于网络上依然很多网站存在这些漏洞,我们还是有必要详细、全面的了解这个漏洞的形成原因和严重后果。首先,我们来看看漏洞的产生。这个漏洞是因为在程序验证账号密码的时候程序不严谨造成的。我们在程序设计的时候,常常将账号、密码放在一个叫“User”的数据表中,设置“username”和“password”两个字段,当验证的时候,检查用户的输入是否存在于这个数据表,如果存在,证明这个用户合法;不存在,证明用户不合法。漏洞的出现,就是这个验证代码的编写不严谨造成的,我们来看原代码。
‘连接数据库
Set Conn=Server.CreateObject("ADODB.Connection")
Connstr="DBQ="+server.mappath("db\news.mdb")+";DefaultDir=;DRIVER={Microsoft Access
Driver (*.mdb)};DriverId=25;FIL=MS Access;ImplicitCommitSync=Yes;MaxBufferSize=512;
MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Threads=3;UserCommitSync=Yes;"
‘打开数据库连接
Conn.Open connstr
‘数据库选择语句
mysql="select * from user where userid=’”&txtuserid&”’ and pwd=‘”&txtpwd&” "
set rs=server.createobject("adodb.recordset")
rs.open mysql,conn,1,1
if not (rs.eof) then
rs.close
conn.close
response.redirect"ok_login.asp"
end if
在以上的代码中,我们看mysql的定义,这里的txtuserid和txtpwd都是直接来自用户的输入,如果用户构造特殊的用户名或者密码,就可以直接让这里的Select条件为“真”,完全不必理会是否有合法账号密码。我们这里不直接给出万能密码,希望有经验的读者仔细分析select语句,找出可能的漏洞。
以上漏洞的修改其实很多方法,我们这里提出几种比较完善的方法参考。首先,我们可以对用户输入的账号、密码进行严格检查,除了二十六个字母和十个数字,其他任何字符都是非法的,也就是过滤那些非法的字符,确保用户输入合法。注意,这个过滤要针对用户名和密码两个进行;二是修改以上的select语句或者下面的if语句,从程序设计角度堵塞漏洞的产生;三是检验用户的输入信息长度,限制输入信息在8个字母内,这样,也能防止漏洞的产生,不过,这个方法不是很好,最好利用第一种方法。
2、取得别人账号
这个漏洞原因已经在上面分析了,我们现在来看实例。首先,我们进入一个注册页面(图1)并且随意输入一个账号,发现出现账号已经存在的信息(图2):
这样,我们知道这个账号已经存在,怎样取得这个账号的使用权呢?我们使用另外一个账号注册,如果这个账号不存在,会出现以下的页面(图3)
以上页面,就是正常的注册页面,我们可以发现在“用户名称”后面,发现了需要注册的“kkkkkkkkk”账号,再看看这个页面的源代码,查找这个账号,看这个账号出现在哪些地方,我们只看关键的代码:
<FORM name="form2" action="../member/register1.jsp" method=post onsubmit="javascript:return TestField1()">
<div align="center">
<input type="hidden" name="Step" value="2">
<input type="hidden" name="recName" value=kkkkkkkkk>
<table width="500" border="0" cellspacing="0" cellpadding="2">
<tr bgcolor="#000000">
<td>
<div align="center"><b><font color="#FFFFFF">普通会员注册</font></b></div>
</td>
</tr>
</table>
在上面的代码中,我们发现有两个hidden类型的表单项,第一个是“Step”,第二个是“recName”,从名字我们知道,第一个是注册的步骤,对我们没有意义;第二个是注册的用户名,为什么要使用“hidden”类型表单保存呢?就是为了在以下的正式注册中直接使用这个作为用户名。发现什么没有?我们可以将这里的注册名修改为我们刚才试验时候使用的注册名“andy”,然后保存为一个HTML文件,再一次打开,填写必要信息提交,结果,我们已经取得该账号的“合法”使用权。在这里需要注意的一点是,在以下语句中:
<FORM name="form2" action="../member/register1.jsp" method=post onsubmit="javascript:return TestField1()">
如果我们直接保存页面到本机,提交的时候会出错的,因为本机不存在member/register1.jsp文件,我们必须将这里该为正确的网址,也就是在前面加上该网站的网址才可以提交。另外,并不是所有使用这种分步验证方式注册的网站都存在这个漏洞。
3、绕过验证的“页面炸弹”
即使页面有严格的验证,有时候,我们还是可以绕过这些验证来提交一些不合法的信息,最简单的就是采用JavaScript方式验证的程序,因为JavaScript的特殊性,我们可以将提交信息的页面保存到本地计算机,然后将这些JavaScript程序删除,再提交攻击信息,这样,轻松的,我们就可以绕过页面信息验证了。
四、总结
以上我们介绍了网页编程中容易出现的一些漏洞,这些漏洞,其实并不只是在网页编程中出现,在其他的编程中,也有一定的参考价值。从以上的介绍中可以知道,安全的概念其实贯穿在整个网页设计过程中,随时我们都要考虑到安全的问题,这样,我们的网站才会多一些安全性;同样的,作为网络攻击者,如果随时注意一些编程漏洞,很容易,网站的漏洞就可以找出来。