安全漏洞扫描,风险原因分析及解决方案

1 会话标识未更新 
1.1 原因 
在用户进入登录页面,但还未登录时,就已经产生了一个session,用户输入信息,登录以后,session的id不会改变,也就是说还是以前的那个session(事实上session也确实不会改变,因为没有建立新session,原来的session也没有被销毁)。 
很多人只是让会话invalidate没有用(request.getSession().invalidate();),是因为invalidate方法不是真正的将session销毁,只是将session中的内容清空,所以当invalidate以后再新建session,新建的session其实不是新的,是将之前的session重新启用了。于是session的id不变就不奇怪了。只有cookie失效掉,才能换成新的session id 
1.2 解决 
在登录页面上加上一段代码:

request.getSession().invalidate() ;         //清空session 

if (request.getCookies()!=null) {
   Cookie cookie = request.getCookies()[0];     // 获取cookie
   cookie.setMaxAge(0);                    // 让cookie过期
} 

注:会话失效后,请不要在代码前面使用SESSION保存数据。 
2 SQL注入 
2.1 原因 
1. 没有正确过滤转义字符  
在用户的输入没有为转义字符过滤时,就会发生这种形式的注入式攻击,它会被传递给一个SQL语句。这样就会导致应用程序的终端用户对数据库上的语句实施操纵。比方说,下面的这行代码就会演示这种漏洞:

statement := "SELECT * FROM users WHERE name = ‘" + userName + "‘; " 

将用户名变量(即username)设置为:a‘ or ‘t‘=‘t,此时原始语句发生了变化.

2. 用户输入错误的数据类型 
如果一个用户提供的字段并非一个强类型,或者没有实施类型强制,就会发生这种形式的攻击。当在一个SQL语句中使用一个数字字段时,如果程序员没有检查用户输入的合法性(是否为数字型)就会发生这种攻击。例如: 
statement := "SELECT * FROM data WHERE id = " + a_variable + "; " 
从这个语句可以看出,作者希望a_variable是一个与“id”字段有关的数字。不过,如果终端用户选择一个字符串,就绕过了对转义字符的需要。例如,将a_variable设置为:1; DROP TABLE users,它会将“users”表从数据库中删除,SQL语句变成:

SELECT * FROM DATA WHERE id = 1; DROP TABLE users; 

3. 数据库服务器中的漏洞 
有时,数据库服务器软件中也存在着漏洞,如MYSQL服务器中mysql_real_escape_string()函数漏洞。这种漏洞允许一个攻击者根据错误的统一字符编码执行一次成功的SQL注入式攻击。 
4. 盲目SQL注入式攻击 
当一个Web应用程序易于遭受攻击而其结果对攻击者却不见时,就会发生所谓的盲目SQL注入式攻击。有漏洞的网页可能并不会显示数据,而是根据注入到合法语句中的逻辑语句的结果显示不同的内容。这种攻击相当耗时,因为必须为每一个获得的字节而精心构造一个新的语句。但是一旦漏洞的位置和目标信息的位置被确立以后,一种称为Absinthe的工具就可以使这种攻击自动化。 
5. 条件响应 
注意,有一种SQL注入迫使数据库在一个普通的应用程序屏幕上计算一个逻辑语句的值:

SELECT booktitle FROM booklist WHERE bookId = ‘OOk14cd‘ AND 1=1 

这会导致一个标准的面面,而语句 
SELECT booktitle FROM booklist WHERE bookId = ‘OOk14cd‘ AND 1=2 
在页面易于受到SQL注入式攻击时,它有可能给出一个不同的结果。如此这般的一次注入将会证明盲目的SQL注入是可能的,它会使攻击者根据另外一个表中的某字段内容设计可以评判真伪的语句。 
6. 条件性差错 
如果WHERE语句为真,这种类型的盲目SQL注入会迫使数据库评判一个引起错误的语句,从而导致一个SQL错误。

例如:

SELECT 1/0 FROM users WHERE username=‘Ralph‘

显然,如果用户Ralph存在的话,被零除将导致错误。 
7. 时间延误 
时间延误是一种盲目的SQL注入,根据所注入的逻辑,它可以导致SQL引擎执行一个长队列或者是一个时间延误语句。攻击者可以衡量页面加载的时间,从而决定所注入的语句是否为真。 
2.2 解决 
1. 用预编译处理语言 
要防御SQL注入,用户的输入就绝对不能直接被嵌入到SQL语句中。恰恰相反,用户的输入必须进行过滤,或者使用参数化的语句。参数化的语句使用参数而不是将用户输入嵌入到语句中。在多数情况中,SQL语句就得以修正。然后,用户输入就被限于一个参数。下面是一个使用Java和JDBC API例子:

PreparedStatement prep = conn.prepareStatement("SELECT * FROM USERS WHERE PASSWORD=?"); 

prep.setString(1, pwd); 

总体上讲,有两种方法可以保证应用程序不易受到SQL注入的攻击,一是使用代码复查,二是强迫使用参数化语句的。强迫使用参数化的语句意味着嵌入用户输入的SQL语句在运行时将被拒绝。 
2. 轨范出错处理 
防范SQL注入,还要避免出现一些详细的错误消息,因为黑客们可以利用这些消息。要使用一种标准的输入确认机制来验证所有的输入数据的长度、类型、语句、企业规则等。 
3. 使用专业的漏洞扫描工具 
但防御SQL注入攻击也是不够的。攻击者们目前正在自动搜索攻击目标并实施攻击。其技术甚至可以轻易地被应用于其它的Web架构中的漏洞。企业应当投资于一些专业的漏洞扫描工具,如大名鼎鼎的Acunetix的Web漏洞扫描程序等。一个完善的漏洞扫描程序不同于网络扫描程序,它专门查找网站上的SQL注入式漏洞。最新的漏洞扫描程序可以查找最新发现的漏洞。

3 XSS跨站脚本编制 
3.1 原因 
它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用,所以许多人常忽略其危害性。 
3.2 解决 
在防止这类问题时,输入内容的转义效果远比内容过滤要好。 
具体实施可以增加一个request的转码过滤器。代码:

package com.apusic.portal.sso;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;
import java.util.*;
/**
* Servlet Filter implementation class SqlEscapeFilter
*/
public class SqlEscapeFilter implements Filter {
    /**
     * Default constructor.
     */
    public SqlEscapeFilter() {
        // TODO Auto-generated constructor stub
    }
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }
    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here
        HttpServletRequest hreq = (HttpServletRequest)request;
        Map map = hreq.getParameterMap();
        Iterator itr = map.keySet().iterator();
        while( itr.hasNext() )
        {
            String key = itr.next().toString();
            String [] values = hreq.getParameterValues(key);
            if( values != null )
            {
                for( int i = 0; i < values.length; i++ )
                {
                    values[i] = cleanXSS(values[i]);
                }
            }
            hreq.setAttribute(key, values);
        }
        // pass the request along the filter chain
        chain.doFilter(request, response);
    }
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }
    private String cleanXSS(String value)
    {
        value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
        value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", ")");
        value = value.replaceAll("‘", "& #39;");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\‘][\\s]*javascript:(.*)[\\\"\\\‘]", "\"\"");
        value = value.replaceAll("script", "");
        return value;
    }
} 

配置应用中的web.xml 
Web.xml:

<filter>
     <display-name>SqlEscapeFilter</display-name>
     <filter-name>SqlEscapeFilter</filter-name>
     <filter-class>com.apusic.portal.sso.SqlEscapeFilter</filter-class>
</filter>
<filter-mapping>
     <filter-name>SqlEscapeFilter</filter-name>
     <url-pattern>*.jsp</url-pattern>
</filter-mapping> 

4 XSRF跨站请求伪造 
4.1 原因 
CSRF利用方式比较类似XSS(跨站脚本 Cross Site Scripting) ,不过不同的是CSRF是构造一个提交来让其他人访问后,利用站点对这些人的信任来进行一些所期望的操作. 
比如:A和B在同一个有XSS漏洞的站点C,B登录过D站点,并且有这个D站点的Cookies,这时候如果A构造一个CSRF,内容为给 A在D站点的账户转移一些虚拟币,如果这时候在C站点浏览的B用户打开了A构造的含有CSRF的页面,这时候B的D站点用户会因为对B用户的信任而进行给 A转账的操作. 
4.2 解决 
此类攻击的情景相对的比较复杂,具体解决可以参考以下5点: 
第一:限制验证cookie的到期时间。这些cookie的合法时间越短,黑客利用你的Web应用程序的机会就越小。不过,这个时间越短,用户就越不方便。因此,你需要在安全性和方便性之间进行平衡。 
第二:执行重要业务之前,要求用户提交额外的信息。要求用户在进行重要业务前输入口令,这可以防止黑客发动CSRF攻击(只要浏览器中没有包含口令),因为这种重要信息无法预测或轻易获得。 
第三:使用秘密的无法预测的验证符号。当保存在用户浏览器中的cookie仅由一次会话确认时,CSRF攻击才会有效。所以在每次HTTP请求(当然攻击者无法提前知道)中都有附加的特定会话的信息,这样就可以挫败CSRF攻击。不过,如果这种应用程序存在跨站脚本漏洞,黑客就有可能访问这种验证符号。 
第四:使用定制的HTTP报头。如果执行交易的所有请求都使用XMLHttpRequest并附加一个定制的HTTP报头,同时拒绝缺少定制报头的任何请求,就可以用XMLHttpRequest API来防御CSRF攻击。由于浏览器通常仅准许站点将定制的HTTP报头发送给相同站点,从而了防止由CSRF攻击的源站点所发起的交易。 
第五:检查访问源的报头。在浏览者发送HTTP请求时,它通常会包含源自访问源报头的URL。理论上讲,你可以使用这些信息来阻止源自其它任何站点(而不是来自Web应用程序自身)的请求。

综合公司以往平台报出此类漏洞产出的原因,基本上都可以通过以下简单做法加以解决: 
在请求后面加上一次性令牌。如验证码,手机短信验证,或者sessionID等。 
5 登录错误消息凭证枚举(不充分帐户封锁) 
5.1 原因 
当试图利用不正确的凭证来登录时,当用户输入无效的用户名和无效的密码时,应用程序会分别生成不同的错误消息。通过利用该行为攻击者可以通过反复试验,加暴力破解来发现应用程序的有效用户名、再继续尝试发现相关联的密码。 
5.2 解决 
不论用户名或密码出现问题都提示同样的错误,且同时加上登陆失败次数达到规定次数,则执行帐户锁定功能。 
6 HTML注释敏感信息泄露 
6.1 原因 
页面源代码不正确的注释方式。 
6.2 解决 
将html中有关密码之类的敏感注释去掉或者用<%-- -%>隐式注释。 
7 应用程序错误 
7.1 原因 
未执行验证,可能输入参数数据类型不匹配。 
7.2 解决 
实行严格的数据类型验证。 
8 已解密的登录请求 
8.1 原因 
AppScan 的推理是“AppScan 识别了不是通过SSL 发送的密码参数。 
8.2 解决 
第一:采用基于SSL的HTTPS传输协议 
第二:对敏感信息加密并绕过扫描(只要不是采用SSL安全认证即使加密了但是AppScan还是会扫描出来)

 <input type="text" id="password1"  style="width:195px; height:25px; line-height:25px;border: solid 1px #89B4D6;color:#999" value="10086密码" onfocus="javascript:clearPass();"  onkeyup="this.value=this.value.replace(/./g,‘*‘);" onkeypress="javascript:hiddenPass()"/>
     <input id="password" type="hidden" name="password"  class="inputs_dl" value="" />
将type为password的改为text,然后用JS做一个假的密码输入框,AppScan会扫描type为password的控件。
   function hiddenPass(){
        var pass = document.getElementById("password1");
    var j_pass = document.getElementById("password");
      if(event.keyCode==13){
      check();
      }
       var keycode=event.keyCode;
        var keychar=String.fromCharCode(keycode);
      j_pass.value=j_pass.value+keychar;
      j_pass.value=j_pass.value.substring(0,pass.length);
  } 

   function clearPass(){
       $("#password1").val("");
       $("#password").val("");
  } 

然后传输密码的时候加个密:

password = base64encode(password); 

9 启用了不安全的HTTP方法 
9.1 原因 
除标准的GET与POST方法外,HTTP请求还使用其他各种方法。许多这类方法主要用于完成不常见与特殊的任务。如果低权限用户可以访问这些方法,他们就能够以此向应用程序实施有效攻击。以下是一些值得注意的方法:
PUT,向指定的目录上传附加文件; 
DELETE,删除指定的资源; 
COPY,将指定的资源复制到Destination消息头指定的位置; 
MOVE,将指定的资源移动到Destination消息头指定的位置; 
SEARCH,在一个目录路径中搜索资源。 
PROPFIND,获取与指定资源有关的信息,如作者、大小与内容类型。 
TRACE,在响应中返回服务器收到的原始请求。可以使用这种方法避开阻止跨站点脚本的防御 
9.2 解决 
如何禁止DELETE、PUT、OPTIONS、TRACE、HEAD等协议访问应用程序应用程序呢? 
解决方法 
第一步:修改应用程序的web.xml文件的协议

1.    <?xml version="1.0" encoding="UTF-8"?>
2.    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4.    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
5.    version="2.4"> 

第二步:在应用程序的web.xml中添加如下的代码即可

1.    <security-constraint>
2.    <web-resource-collection>
3.    <url-pattern>/*</url-pattern>
4.    <http-method>PUT</http-method>
5.    <http-method>DELETE</http-method>
6.    <http-method>HEAD</http-method>
7.    <http-method>OPTIONS</http-method>
8.    <http-method>TRACE</http-method>
9.    </web-resource-collection>
10.    <auth-constraint>
11.    </auth-constraint>
12.    </security-constraint>
13.    <login-config>
14.    <auth-method>BASIC</auth-method>
15.    </login-config> 

10 禁止页面缓存 
10.1 原因 
能够访问到缓存的脱机数据导致泄密。 
10.2 解决 
建议在web管理后台程序的过滤器里增加如下代码:

 response.setHeader("Cache-Control", "no-cache"); //只是请求或响应消息不缓存
  response.setHeader("Cache-Control", "no-store"); //在请求消息中发送将使得请求和响应消息都不使用缓存
response.setDateHeader("Expires", 0); //缓存距离过期的时间为0毫秒,即缓存立即过期
  response.setHeader("Pragma", "no-cache"); //页面不缓存 

11 数据库错误模式 
11.1 原因 
主要是一些数据连接错误信息,通过提交特殊构造的字符,程序会暴露一些数据库信息,也容易引起SQL注入攻击。 
现有平台发现的例子:

<html><head><title>Apache Tomcat/5.5.28 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p><p><b>exception</b> <pre>javax.servlet.ServletException: org.hibernate.HibernateException: java.sql.SQLException: ORA-12899: value too large for column &quot;QCSMS&quot;.&quot;T_SYS_LOGON_LOG&quot;.&quot;USER_CODE&quot; (actual: 24, maximum: 20) 
时间: 2024-10-18 14:48:57

安全漏洞扫描,风险原因分析及解决方案的相关文章

AppStore IPv6-only审核被拒原因分析及解决方案

AppStore IPv6-only审核被拒原因分析及解决方案 http://www.jianshu.com/p/8edfdfa20b29 自2016年6月1日起,苹果要求所有提交App Store的iOS应用必须支持IPv6-only环境,背景也是众所周知的,IPv4地址已基本分配完毕,同时IPv6比IPv4也更加高效,向IPv6过渡是大势所趋. 然而在对IPv6进行兼容适配过程中,很多开发者在本地环境测试通过,却在App Store审核时被拒,这种情况下可以首先排查是否由DNS解析失败引起,

Oracle包被锁定的原因分析及解决方案

http://blog.csdn.net/jojo52013145/article/details/7470812 在数据库的开发过程中,经常碰到包.存储过程.函数无法编译或编译时会导致PL/SQL 无法响应的问题.碰到这种问题,基本上都要重启数据库解决,严重浪费开发时间.本文将就产生这种现象的原因和解决方案做基本的介绍. 问题分析 从事数据库开发的都知道锁的概念,如:执行 Update Table xxx Where xxx 的时候就会产生锁.这种常见的锁在Oracle里面被称为DML锁.在O

window.open浏览器弹出新窗口被拦截—原因分析和解决方案

最近在做项目的时候碰到了使用window.open被浏览器拦截的情况,在本机实验没问题,到了服务器就被拦截了,火狐有拦截提示,360浏览器拦截提示都没有,虽然在自己的环境可以对页面进行放行,但是对用户来说,不能要求用户都来通过拦截.何况当出现拦截时,很多小白根本不知道发生了啥,不知道在哪里看被拦截的页面,百思不得其解,后来查了一下,各家浏览器支持的不一样. 另外,可以发现,当window.open为用户触发事件内部或者加载时,不会被拦截,一旦将弹出代码移动到ajax或者一段异步代码内部,马上就出

Beforeunload打点丢失原因分析及解决方案

淘宝的鱼相在 2012 年 8 月份发表了一篇文章,里面讲述了他们通过一个月的数据采集试验,得到的结果是:如果在浏览器的本页面刷新之前发送打点请求,各浏览器都有不同程度的点击丢失情况,具体点击丢失率统计大家请看下图(数据日期为 2012 年 7 月份): 从图中可以看出,chrome,safari 这类 webkit 内核的浏览器在本页刷新之前发送打点,导致的丢失最为严重,分别为 61%,76%,而 ie8 丢失的情况最少,为7%. (具体大家可以参看此文:http://ued.taobao.c

在Activity的onCreate方法中显示PopupWindow导致异常的原因分析及解决方案

一.前言 在某些情况下,我们需要一进入Activity就显示PopupWindow,比如常见的选择界面.但由于PopupWindow是依附于Activity的,如果Activity没有创建完成,Activity还没完全显示出来就显示PopupWindow的话,会出现异常现象. 二.问题复现 我在Activity的onCreate()方法中调用如下方法: public void show( ){ if( null != mPopupWindow ){ mPopupWindow.showAtLoca

Android ListView异步加载图片乱序问题,原因分析及解决方案

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android所有系统自带的控件当中,ListView这个控件算是用法比较复杂的了,关键是用法复杂也就算了,它还经常会出现一些稀奇古怪的问题,让人非常头疼.比如说在ListView中加载图片,如果是同步加载图片倒还好,但是一旦使用异步加载图片那么问题就来了,这个问题我相信很多Android开发者都曾经遇到过,就是异步加载图片会出现错位乱序的情况.遇到这个问题时,不

在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案

转:http://www.jianshu.com/p/89687f618837 原因分析   当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误,报的错误是case分支后面跟的参数必须是常数,换句话说出现这个问题的原因是Android library中生成的R.java中的资源ID不是常数: 打开library中的R.java,发现确实如此,每一个资源ID都没有被声明为final: 但是当你打开你的主工程,在onClick.onItemClick等各种

关于JVM内存溢出的原因分析及解决方案探讨

前言:JVM中除了程序计数器,其他的区域都有可能会发生内存溢出. 0.什么是内存溢出 当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出. 1.内存泄漏和内存溢出区别与联系 内存泄漏:系统分配的内存没有被回收. 内存溢出:分配的内存空间超过系统内存. 2.内存泄漏的原因分析   jvm由5大块组成:堆,栈,本地方法栈,程序计数器,方法区.栈它的主要记录方法的执行和对象的引用.堆则存在真正的引用的对象. 内存泄漏是由于使用不当,把一部分内存“

Connection reset原因分析和解决方案

在使用HttpClient调用后台resetful服务时,"Connection reset"是一个比较常见的问题,有同学跟我私信说被这个问题困扰很久了,今天就来分析下,希望能帮到大家.例如我们线上的网关日志就会抛该错误: 从日志中可以看到是Socket套接字在read数据时抛出了该错误. 导致"Connection reset"的原因是服务器端因为某种原因关闭了Connection,而客户端依然在读写数据,此时服务器会返回复位标志"RST",然