URL存在跨站漏洞http host头攻击漏洞解决方案

更新日期: 2019-03-26阅读: 2.6k标签: 漏洞

最近项目部署的时候客户使用的绿盟扫描出一些漏洞,老大让我处理,经过看大神的博客等方式,分享一些简单的解决方法。


一 跨网站脚本

跨网站脚本(Cross-site scripting,通常简称为XSS或跨站脚本或跨站脚本攻击)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了html以及用户端脚本语言。 

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java, VBScript, ActiveX, Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。 防止XSS攻击简单的预防就是对Request请求中的一些参数去掉一些比较敏感的脚本命令。


二 解决方案

方式一:【使用Nginx的修复方案】

server {
   listen 8888 default;
   server_name _;
   location / {
        return 403;
   }
}

添加一个默认 server,当 host 头被修改匹配不到 server 时会跳到该默认 server,该默认 server 直接返回 403 错误。

重启 nginx 即可。

除了这种做法,也可以在目标 server 添加检测规则。比如下面的 if 判断配置。

server {
  server_name  192.168.0.171;
  listen       8888;
  if ($http_Host !~*^192.168.0.171:8888$){
    return 403;
  }
  include /etc/nginx/default.d/*.conf;
  location / {
    root /www/dvwa;
    index index.php index.html index.htm;
  }
}


方式二:【基于tocmat的修复方案】

经测试,最低支持Tomcat6.0.x以上版本的修复。

打开tomcat的conf目录中的server.xml文件,将Host节点做如下配置:

<Host name="www.baidu.com" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false"><!--本机对外域名-->
<Alias>172.19.43.28</Alias><!--本机所支持的所有IP-->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt" resolveHosts="false"
pattern="%a %A %b %B %h %H %l %m %p %s %S %t %u %U %v %D %T" />

说白了,这个漏洞是因为你使用了 Host 而没验证它。

String path = request.getContextPath();
String basePath = request.getScheme() + "://"
  + request.getServerName()
  + ":" + request.getServerPort()
  + path + "/";

方式三:【基于Filter的修复方案】

在工程的web.xml中配置下面代码中的拦截器,注意该拦截器一定要放在第一个执行。

最低支持Tomcat7.0.x以上版本的修复

1、首先配置web.xml,添加如下配置信息:

<!-- xSS跨站漏洞filter --> 
  <filter>
    <filter-name>xSSFilter</filter-name>
    <filter-class>com.founder.mrp.web.filter.XSSFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>xSSFilter</filter-name>
    <url-pattern>/*</url-pattern>
 </filter-mapping>

2、编写过滤器:

package com.founder.mrp.web.filter;

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.HttpServletRequest;

public class XSSFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //自定义request包装类,并把它传入过滤器链
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest)request);
        chain.doFilter(xssRequest , response);

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
    }

}

3、包装类

主要是覆盖实现了getParameter,getParameterValues,getHeader这几个方法,然后对获取的value值进行XSS处理。

package com.founder.mrp.web.filter;

import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
HttpServletRequest orgRequest = null;
    
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        orgRequest = request;
    }
 
    /**
     * 覆盖getParameter方法,将参数名和参数值都做xss & sql过滤。<br/>
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(xssEncode(name));
        if (value != null) {
            value = xssEncode(value);
        }
        return value;
    }
    
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(xssEncode(name));
         if(values != null && values.length > 0){
             for(int i =0; i< values.length ;i++){
                 values[i] = xssEncode(values[i]);
             }
         }
        return values;
    }

    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss & sql过滤。<br/>
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
     * getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name) {
 
        String value = super.getHeader(xssEncode(name));
        if (value != null) {
            value = xssEncode(value);
        }
        return value;
    }
 
    /**
     * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符
     * 
     * @param s
     * @return
     */
    private static String xssEncode(String s) {
        if (s == null || s.isEmpty()) {
            return s;
        }else{
            s = stripXSSAndSql(s);
        }
        StringBuilder sb = new StringBuilder(s.length());
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
            case ‘<‘:
                sb.append("<");
                break;
            case ‘>‘:
                sb.append(">");
                break;            
            case ‘(‘:
                sb.append("(");
                break;
            case ‘)‘:
                sb.append(")");
                break;
            case ‘&‘:
                sb.append("&");
                break;
            case ‘|‘:  
                sb.append("|");
                break;
            case ‘+‘:
                sb.append("+");
                break;
            case ‘%‘:
                sb.append("%");
                break;
            case ‘@‘:  
                sb.append("@");
                break;    
            case ‘$‘:
                sb.append("$");
                break;
            case ‘#‘:
                sb.append("#");
                break;    
            case ‘\‘‘:
                sb.append("'");// 转义单引号
                break;
            case ‘\"‘:
                sb.append(""");// 转义双引号
                break;
            case ‘\\‘:
                sb.append("\");//全角斜线
                break;
            default:
                sb.append(c);
                break;
            }
        }
        return sb.toString();
    }
 
    /**
     * 获取最原始的request
     * 
     * @return
     */
    public HttpServletRequest getOrgRequest() {
        return orgRequest;
    }
 
    /**
     * 获取最原始的request的静态方法
     * 
     * @return
     */
    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
        if (req instanceof XssHttpServletRequestWrapper) {
            return ((XssHttpServletRequestWrapper) req).getOrgRequest();
        }
 
        return req;
    }
 
    /**
     * 
     * 防止xss跨脚本攻击(替换,根据实际情况调整)
     */
 
    public static String stripXSSAndSql(String value) {
        if (value != null) {
            // NOTE: It‘s highly recommended to use the ESapi library and
            // uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            value = value.replaceAll("", "");
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile("<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a src="..." type of e-xpression
            scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\‘](.*?)[\\\"|\\\‘]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome </script> tag
            scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid eval(...) expressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid e-xpression(...) expressions
            scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid javascript:... expressions
            scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid vbscript:... expressions
            scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid onload= expressions
            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<iframe>(.*?)</iframe>",Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("</iframe>",Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("<iframe(.*?)>",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
        }
        return value;
    }

}

由于尝试较多,也比较混乱,也不确定哪个适用各位的情况,只能多查多参考。

链接: https://fly63.com/article/detial/2565

PHP中双引号引起的命令执行漏洞

在PHP语言中,单引号和双引号都可以表示一个字符串,但是对于双引号来说,可能会对引号内的内容进行二次解释,这就可能会出现安全问题。在双引号中倘若有${}出现,那么{}内的内容将被当做代码块来执行。可以看到成功执行了phpinfo()

62 岁程序员锒铛入狱,因植入漏洞重复获取修理费用

一位西门子公司的合同工十年前在给西门子写的电子表格中植入了逻辑炸弹,它会在特定日期之后导致电子表格崩溃,于是西门子就必须再次雇佣该名合同工进行修复,每次都需要重新支付修复费用,持续时间近 3 年。最近他被抓包了

web安全漏洞之目录遍历

第一次接触到目录遍历漏洞还是在 ThinkJS 2 的时候。代码如下图,目的是当用户访问的 URL 是静态资源的时候返回静态资源的地址。其中 pathname 就是用户访问的 URL 中的路径,我们发现代码中只是简单的解码之后

如何在软件开发中避免出现漏洞

随着数据泄露事件的频繁发生,创建和维护安全的软件产品对于每一个组织来说,都变得越来越重要了。尽管并非所有的攻击都可以被预期或防范,但是我们至少可以通过消减软件的漏洞,来避免攻击的暴露面。

十大常见web漏洞

SQL注入攻击(SQL Injection),简称注入攻击、SQL注入,被广泛用于非法获取网站控制权,是发生在应用程序的数据库层上的安全漏洞。在设计程序,忽略了对输入字符串中夹带的SQL指令的检查

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!