【LWei-开发】WEB开发常见漏洞攻击及修复方法

1、sql注入

解决方法:通过使用MyBits等框架避免;获取参数值得地方对特殊字符进行过滤;
2、XSS攻击

反射型解决方法:向文档输出动态内容时,应根据输出位置进行正确的编码或转义;

存储型解决方法:数据库存储前过滤特殊字符进行正确的编码或转义;

/*
* Xss特殊字符过滤类,正则表达式可根据具体业务需求调整。
*/
public class XssShieldUtil {
	private static List<Pattern> patterns = null;

	private static List<Object[]> getXssPatternList() {
		List<Object[]> ret = new ArrayList<Object[]>();
		ret.add(new Object[] { "<(no)?script[^>]*>.*?</(no)?script>", Pattern.CASE_INSENSITIVE });
		ret.add(new Object[] { "eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL });
		ret.add(new Object[] { "expression\\((.*?)\\)",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL });
		//ret.add(new Object[] { "(javascript:|vbscript:|view-source:)*", Pattern.CASE_INSENSITIVE });
		ret.add(new Object[] { "<(\"[^\"]*\"|\'[^\']*\'|[^\'\">])*>",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL });
		ret.add(new Object[] {
				"window\\.location|window\\.|\\.location|document\\.cookie|document\\.|alert\\(.*?\\)|window\\.open\\(\\)*",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL });
		ret.add(new Object[] {
				"<+\\s*\\w*\\s*(oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondblclick|ondeactivate|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragstart|ondrop|onerror=|onerroupdate|onfilterchange|onfinish|onfocus|onfocusin|onfocusout|onhelp|onkeydown|onkeypress|onkeyup|onlayoutcomplete|onload|onlosecapture|onmousedown|onmouseenter|onmouseleave|onmousemove|onmousout|onmouseover|onmouseup|onmousewheel|onmove|onmoveend|onmovestart|onabort|onactivate|onafterprint|onafterupdate|onbefore|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onblur|onbounce|oncellchange|onchange|onclick|oncontextmenu|onpaste|onpropertychange|onreadystatechange|onreset|onresize|onresizend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onselect|onselectionchange|onselectstart|onstart|onstop|onsubmit|onunload)+\\s*=+",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL });
		ret.add(new Object[] {"[\" _`~!@#$^*()+|{}':;',<>~!@#¥%……&*()——+|{}]|\\n|\\r|\\t|LF|CR",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL});
		
		return ret;
	}

	private static List<Pattern> getPatterns() {
		if (patterns == null) {
			List<Pattern> list = new ArrayList<Pattern>();
			String regex = null;
			Integer flag = null;
			int arrLength = 0;

			for (Object[] arr : getXssPatternList()) {
				arrLength = arr.length;
				for (int i = 0; i < arrLength; i++) {
					regex = (String) arr[0];
					flag = (Integer) arr[1];
					list.add(Pattern.compile(regex, flag));
				}
			}

			patterns = list;
		}
		return patterns;
	}
// 存在特殊字符时,字符串置空
	public static String stripXss(String value) {
		if (StringUtils.isNotBlank(value)) {
			Matcher matcher = null;                    
			for (Pattern pattern : getPatterns()) {
				matcher = pattern.matcher(value.toLowerCase());
				// 匹配
				if (matcher.find()) { // 删除相关字符串
					value = "";
				}
			}
			// value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
		}
		return value;
	}
// 存在特殊字符时,返回true
	public static boolean strXss(String value) {
		boolean bool=false;
		if (StringUtils.isNotBlank(value)) {
			Matcher matcher = null;                    
			for (Pattern pattern : getPatterns()) {
				matcher = pattern.matcher(value.toLowerCase());
				// 匹配
				if (matcher.find()) { // 删除相关字符串
					bool = true;
				}
			}
		}
		return bool;
	}

	/**
	 * 验证url
	 * @param str
	 * @return
	 */

	public static String isSpecialChar(String str) {
		String regEx = "[\" _`~!@#$^*()+|{}':;',<>~!@#¥%……&*()——+|{}]|\\n|\\r|\\t|LF|CR";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(str);
		if (m.find()) {
			str = "";
		}
		return str;
	}
// 方法测试
	public static void main(String[] args) { 
		  String value = null; 
		  value =XssShieldUtil.stripXss("<script language=text/javascript>alert(document.cookie);</script>"); 
		  System.out.println(value);
	  }
}


3、越权操作

水平越权,仅通过js验证,对用户权限的检查不完善,权限的凭证可以被用户控制。

解决方法:在服务端严格检查进行操作的用户权限;

垂直越权,低权限操作高权限功能。

解决方法:sessionID进行功能比对。
4、任意文件上传

解决方法:禁止上传asp、cgi、aspx等,推荐使用白名单;

5、检测到目标URL存在跨站漏洞

跨站脚本攻击(也称为XSS)指利用网站漏洞从用户那里恶意盗取信息。

解决方法:设置过滤器,获取request请求参数,循环读取判断是否包含XSS攻击字符,如果存在返回403,不存在正常处理请求。

web.xml文件,配置过滤器
<filter>   
    <filter-name>jspFilter</filter-name>   
    <filter-class>com.XXX.filter.JspFilter</filter-class>    
</filter>  
<filter-mapping>   
    <filter-name>jspFilter</filter-name>   
    <url-pattern>指定路径</url-pattern>    
</filter-mapping>
过滤器JspFilter,获取request请求参数,循环读取判断是否包含XSS攻击字符,如果存在返回403,不存在正常处理请求。

import java.io.IOException;
import java.util.Enumeration;

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

import com.ivan.utils.XssShieldUtil;

public class JspFilter implements Filter {

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

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, 
			FilterChain filterChain) throws IOException, ServletException {
		// TODO Auto-generated method stub

	   Enumeration  enu=request.getParameterNames();    
       while(enu.hasMoreElements()){    
          String  paramName=(String)enu.nextElement();                        
          String[]  values=request.getParameterValues(paramName);    
          for(int  i=0;i<values.length;i++){   
        	  if(XssShieldUtil.strXss(values[i])){
        		  ((HttpServletResponse) response).setStatus(403);
        		  System.out.println("["+i+"]   "+paramName+"  "+values[i]);   
        		  return;
        	  }
          }
       } 
       filterChain.doFilter(request, response);  
	}

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

}

6、检测到目标URL存在http host头攻击漏洞

为了方便的获得网站域名,开发人员一般依赖于HTTP Host header。例如,在php里用_SERVER["HTTP_HOST"]。但是这个header是不可信赖的,如果应用程序没有对host header值进行处理,就有可能造成恶意代码的传入。

解决方法:web应用程序应该使用SERVER_NAME而不是host header。Java项目通过设置访问白名单处理,host不在此名单内的所有请求,将返回403.

web.xml中配置过滤器

<filter>   
	<filter-name>SessionFilter</filter-name>   
	<filter-class>com.XXX.filter.SessionFilter</filter-class>    
</filter>  
<filter-mapping>   
	<filter-name>SessionFilter</filter-name>   
	<url-pattern>/*</url-pattern>    
</filter-mapping>
过滤器内容。

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;
import javax.servlet.http.HttpServletResponse;

import com.ivan.utils.ServerWhiteListUtil;

public class SessionFilter implements Filter {

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

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        // 头攻击检测
        String requestHost = request.getServerName();
        if (requestHost != null && !ServerWhiteListUtil.isWhite(requestHost)){
        	System.out.println("响应头Code:403");
            response.setStatus(403);
            return;
        }else {
        	chain.doFilter(request, response); 
		}
	}

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

}
白名单对比工具类。

import java.util.ArrayList;
import java.util.List;


public class ServerWhiteListUtil {
	private static List<String> whiteList = new ArrayList<String>();

    static {
        try {
        	String[] strarr = {"localhost:8080"};
        	for(int i=0;i<strarr.length;i++) {
        		whiteList.add(strarr[i]);
        	}
           /* // 读取白名单列表
            whiteList = new Gson().fromJson(
                    new InputStreamReader(ServerWhiteListUtil.class.getResourceAsStream("/resources/serverWhiteList.json")),
                    new TypeToken<List<String>>() {}.getType());*/
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断当前host是否在白名单内 
     * @param host 待查host
     * @return boolean 是否在白名单内
     */
    public static boolean isWhite(String host) {
        if (whiteList == null || whiteList.size() == 0) {
            return true;
        }
        for (String str : whiteList) {
            if (str != null && str.equals(host)) {
                return true;
            }
        }
        return false;
    }
}

7、点击劫持:X-Frame-Options未配置

点击劫持(ClickJacking)是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。
HTTP 响应头信息中的X-Frame-Options,可以指示浏览器是否应该加载一个 iframe 中的页面。如果服务器响应头信息中没有X-Frame-Options,则该网站存在ClickJacking攻击风险。网站可以通过设置 X-Frame-Options 阻止站点内的页面被其他页面嵌入从而防止点击劫持。

解决方法:修改web服务器配置,添加X-Frame-Options响应头。赋值有如下三种:
1、DENY:不能被嵌入到任何iframe或者frame中。
2、SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中。
3、ALLOW-FROM uri:只能被嵌入到指定域名的框架中。

web.xml 配置

<filter>  
	<filter-name>httpHeaderSecurity</filter-name>  
	<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>  
	<init-param>  
		<param-name>antiClickJackingOption</param-name>  
		<param-value>SAMEORIGIN</param-value>
		<!-- <param-value>DENY</param-value> -->  
	</init-param>  
	<async-supported>true</async-supported>  
</filter>  

8、CSRF跨站请求伪造

攻击者通过伪造来自受信任用户的请求,达到增加、删除、篡改网站内容的目的。

解决方法:请求地址中添加token并验证(token不放在cookie中,放在http请求参数中,服务端对其进行验证);将token加入http头属性中,避免了token出现在浏览器中,被泄露。

web.xml配置过滤器

<!-- 用于生成token值 -->
<filter>   
	<filter-name>cookieHttpFilter</filter-name>   
	<filter-class>com.XXX.filter.CookieHttpFilter</filter-class>    
</filter>  
<!-- 用于验证token值 -->
<filter>   
	<filter-name>csrfFilter</filter-name>   
	<filter-class>com.XXX.filter.CsrfFilter</filter-class>    
</filter>  
token值是根据系统当前时间,通过base64进行编码生成,存放在session中。


import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class CookieHttpFilter implements Filter {

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

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, 
			FilterChain filterChain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req = (HttpServletRequest) request;   
		
		Cookie[] cookies = req.getCookies();  
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");//设置日期格式
		HttpSession session = req.getSession(); 
		
	   if(cookies!=null){
		   final Base64.Encoder encoder = Base64.getEncoder();
		   byte[] tokenByte = df.format(new Date()).getBytes("UTF-8");
		   String token=encoder.encodeToString(tokenByte);
		   
		   session.setAttribute("csrftoken", token);
	   }
	   filterChain.doFilter(request, response);  
	}

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

}
通过request获取session值,通过session的key获取token值,通过token值进行验证,验证通过则继续处理请求,验证不通过,则返回403.


import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class CsrfFilter implements Filter {

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

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		
		HttpServletRequest req = (HttpServletRequest)request; 
		HttpSession s = req.getSession(); 
		// 从 session 中得到 csrftoken 属性
		String sToken = (String)s.getAttribute("csrftoken"); 
		
		Cookie[] cookies = req.getCookies(); 
		if(cookies != null){
			if(sToken == null){
				((HttpServletResponse) response).setStatus(403);
			} else{ 
				final Base64.Encoder encoder = Base64.getEncoder();
				// 生成token值
				SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");//设置日期格式
				byte[] tokenByte = df.format(new Date()).getBytes("UTF-8");
				String xhrToken = encoder.encodeToString(tokenByte); 
				if(xhrToken != null && sToken.equals(xhrToken)){ 
					chain.doFilter(request, response); 
				}else{ 
					((HttpServletResponse) response).setStatus(403);
				} 
			}
		}else{
			chain.doFilter(request, response); 
		}
	}

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

}

9、控制器不允许直接访问jsp

web.xml中配置

<security-constraint>
	<web-resource-collection>
		<url-pattern>/*</url-pattern>
		<http-method>PUT</http-method>
		<http-method>DELETE</http-method>
		<http-method>HEAD</http-method>
		<http-method>OPTIONS</http-method>
		<http-method>TRACE</http-method>
	</web-resource-collection>
	<auth-constraint>
	</auth-constraint>
</security-constraint>

参考资料:https://blog.csdn.net/tc2015/article/details/51774454


10、其他

信息泄露,使用合适的错误页面;

目录遍历,字符串拼接下载,利用../来遍历目录;

整数溢出,计算功能,对输入值进行合理验证,错误页面的信息进行处理。

猜你喜欢

转载自blog.csdn.net/u013153374/article/details/84768967