安全漏洞: XSS跨站脚本攻击与Sql注入攻击

目录

  • 一 . XSS跨站脚本攻击
      • 1、漏洞简介
      • 2、漏洞分类
      • 3、漏洞危害
      • 4、防护建议
  • 二 . SQL注入攻击
      • 1、漏洞简介
      • 2、漏洞危害
      • 3、防护建议
      • 4、mybatis中#可以有效防止sql注入
  • 三. 解决方案

一 . XSS跨站脚本攻击

1、漏洞简介

跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!

2、漏洞分类

XSS分为:存储型 、反射型 、DOM型XSS
存储型XSS:存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie
反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面
DOM型XSS:不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。

安全漏洞: XSS跨站脚本攻击与Sql注入攻击_第1张图片
安全漏洞: XSS跨站脚本攻击与Sql注入攻击_第2张图片

3、漏洞危害

安全漏洞: XSS跨站脚本攻击与Sql注入攻击_第3张图片

4、防护建议

<1>限制用户输入,表单数据规定值得类型,例如年龄只能是int,name为字母数字组合。
<2>对数据进行html encode处理。
<3>过滤或移除特殊的html标签。
<4>过滤javascript事件的标签。

二 . SQL注入攻击

1、漏洞简介

SQL注入(SQLi)是一种注入攻击,,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加,修改和删除数据库中的记录。
__
SQL注入漏洞可能会影响使用SQL数据库(如MySQL,Oracle,SQL Server或其他)的任何网站或Web应用程序。犯罪分子可能会利用它来未经授权访问用户的敏感数据:客户信息,个人数据,商业机密,知识产权等。SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。

2、漏洞危害

1.数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。
2.网页篡改:通过操作数据库对特定网页进行篡改。
3.网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
4.数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
5.服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或 控制操作系统。
6.破坏硬盘数据,瘫痪全系统。

3、防护建议

<1>过滤用户输入,对用户输入输出进行校验
<2>不使用动态拼装SQL,使用参数化的SQL或者使用存储过程进行数据查询存取。
<3>封装异常信息
<4>设立数据库连接分级授权

4、mybatis中#可以有效防止sql注入

一: #能防止sql注入, $不能

① 使用#: Mybatis的sql是一个具有“输入+输出”功能,类似于函数的结构,如下:

<select id="getBlogById" resultType="Blog" parameterType=int>
       select id,title,author,content
       from blog where id=#{id}
</select>

 打印出执行的sql语句,会看到sql是这样的:
select id,title,author,content from blog where id = ?

不管输入什么参数,打印出的sql都是这样的。这是因为mybatis启用了预编译功能,在sql执行前,会先将上面的sql发送给数据库进行编译,执行时,直接使用编译好的sql,替换占位符“?”就可以了。因为sql注入只能对编译过程起作用,所以这样的方式就很好地避免了sql注入的问题。

mybatis是如何做到sql预编译的呢?
其实在框架底层,是jdbc中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的sql语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行一个sql时,能够提高效率,原因是sql已编译好,再次执行时无需再编译。

② 使用$:

<select id="orderBlog" resultType="Blog" parameterType=”map”>
       select id,title,author,content
       from blog order by ${orderParam}
</select>

仔细观察,内联参数的格式由“#{xxx}”变为了${xxx}。如果我们给参数“orderParam”赋值为”id”,将sql打印出来,是这样的:

select id,title,author,contet from blog order by id

显然,这样是无法阻止sql注入的。在mybatis中,” x x x ” 这 样 格 式 的 参 数 会 直 接 参 与 s q l 编 译 , 从 而 不 能 避 免 注 入 攻 击 。 但 涉 及 到 动 态 表 名 和 列 名 时 , 只 能 使 用 “ {xxx}”这样格式的参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“ xxxsql使{xxx}”这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。
结论:在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。

三. 解决方案

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

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 XssFilter implements Filter {  
	
	// 无权限警告页面
	// private final String warnPageurl = "null";

    Logger log  = LoggerFactory.getLogger(this.getClass());

    /** 
     * 排除部分URL不做过滤 
     */   
	// 忽略权限检查的JSP
 	private final String[] excludeUrls = new String[]{
        "null"
 			};
 	// 忽略权限检查的URL
  /*	private final String[] excludePermissionUrls = new String[]{
  			"null"
  			};*/
  
    /** 
     * 公告新增、修改用到富文本,对标签进行转义 
     */  
    // private List noticeUrls = new ArrayList(); 
  
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)  
            throws IOException, ServletException {  

        HttpServletRequest req = (HttpServletRequest) arg0;  
        HttpServletResponse response = (HttpServletResponse) arg1;  
        
        
        String pathInfo = req.getPathInfo() == null ? "" : req.getPathInfo();  
        //获取请求url的后两层
        String url = req.getServletPath() + pathInfo;
        //获取请求你ip后的全部路径  
        String uri = req.getRequestURI();
//        if("".length() < 10){
//        	arg2.doFilter(arg0, arg1);
//        	return;
//        }
        // boolean isNoticeUrl = false;
        // boolean isExcludePermissionUrl = false;//无需检查权限
        // req.getParameterMap();
        //注入xss过滤器实例
        XssHttpServletRequestWraper reqW = new XssHttpServletRequestWraper(req);
        
        // setHttpOnly(req,response);
        // 排除部分URL不做过滤。  
        for (String str : excludeUrls) {  
            if (uri.indexOf(str) >= 0) {  
                arg2.doFilter(reqW, response);  
                return;  
            }  
        }
        //忽略权限检查
        // for (String st : excludePermissionUrls) {  
        //     if (uri.indexOf(st) >= 0) {  
        //     	isExcludePermissionUrl = true;  
        //         break;  
        //     }  
        // }
        //重点检查、包含密码的参数
        // for (String st : noticeUrls) {  
        //     if (uri.indexOf(st) >= 0) {  
        //         isNoticeUrl = true;  
        //         break;  
        //     }  
        // }
       
     
        // 获取请求所有参数,校验防止SQL注入,防止XSS漏洞  
        Enumeration<?> params = req.getParameterNames();  
        String paramN = null;  
        while (params.hasMoreElements()) {  
            paramN = (String) params.nextElement();  
            String paramVale = req.getParameter(paramN);  
            // if (!paramN.toLowerCase().contains("password")) {  
            // }  
            //if (isNoticeUrl) {  
                paramVale = xssEncode(paramVale);  
            //}  
      
            // 校验是否存在SQL注入信息  
            if (checkSQLInject(paramVale, url)) {  
                errorResponse(response, paramN,"输入项中不能包含非法字符。");
                log.error("输入项中不能包含非法字符! URI="+uri+";paramName="+ paramN+";paramVale="+ paramVale);
                // System.out.println("输入项中不能包含非法字符。param="+ paramVale +";"+ uri);
                return;  
            }  
        } 
    	arg2.doFilter(reqW, response); //bgh 2018/05/30  修改
    }  
    
    //用来响应错误信息
    private void errorResponse(HttpServletResponse response, String paramNm,String warning) throws IOException {  
    
        Map<String,Objet> map = new HashMap<>();
        map.put("code",50000);
        map.put("message",xssEncode(warning));
        map.put("paramName",paramNm);
        response.setContentType("text/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write(fromObject.toString());
        out.plush();
        out.close();
    }  
  
    public void destroy() {  
    }  
  
    public void init(FilterConfig filterconfig1) throws ServletException {  
        // 读取文件  
        // String path = XssFilter.class.getResource("/").getFile();  
        // //excludeUrls = readFile(path + "xssWhite.txt");  
        // noticeUrls.add("notice!saveNotice");  
        // noticeUrls.add("notice!updateNoticeById");  
    }  

    //是否包含特殊字符,特殊字符替换
    private String xssEncode(String s) {  
        if (s == null || s.isEmpty()) {  
            return s;  
        }  
        //不是线程安全(不能同步访问),效率比StringBuffer高,适合在单线程下使用
        //容量大小的基础上+16字节
        StringBuilder sb = new StringBuilder(s.length() + 16);  
        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;
            default:  
                sb.append(c);  
                break;  
            }  
        }  
        return sb.toString();  
    }  
    
  
    /** 
     *  
     * 检查是否存在非法字符,防止SQL注入 
     *  
     * @param str 
     *            被检查的字符串 
     * @return ture-字符串中存在非法字符,false-不存在非法字符 
     */  
    public static boolean checkSQLInject(String str, String url) {  

        // 如果传入空串则认为不存在非法字符  
        if (StringUtils.isEmpty(str)) {  
            return false;
        }  
  
        // 判断黑名单  
        String[] inj_stra = { "script", "mid", "master", "truncate", "insert", "select", "delete", "update", "declare", "drop", "grant", 
                "iframe", "'", "onreadystatechange", "alert", "atestu", ";", "--", "xss", " and ", " or ", "(", ")", "eval", "from dual", 
                "\\", "svg111", "confirm", "prompt", "onload", "onmouseover", "onfocus", "onerror", "exec", "sleep" , "count" , "*" , "%" ,
                "chr" , "char" , "+" , "roomid" , "org_no" , "cxtj" }; 
  
        str = str.toLowerCase(); // sql不区分大小写  
  
        for (int i = 0; i < inj_stra.length; i++) {  
            if (str.indexOf(inj_stra[i]) >= 0) {  
                return true;  
            }  
        }  
        return false;  
    }  
	
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class XssHttpServletRequestWraper extends HttpServletRequestWrapper {

	Logger log  = LoggerFactory.getLogger(this.getClass());

	
	public XssHttpServletRequestWraper() {
		super(null);
	}

	public XssHttpServletRequestWraper(HttpServletRequest httpservletrequest) {
		super(httpservletrequest);
	}

	public String[] getParameterValues(String s) {
		
		String str[] = super.getParameterValues(s);
		if (str == null) {
			return null;
		}
		int i = str.length;
		String as1[] = new String[i];
		for (int j = 0; j < i; j++) {
			//System.out.println("getParameterValues:"+str[j]);
			as1[j] = cleanXSS(cleanSQLInject(str[j]));
		}

		return as1;
	}

	public String getParameter(String s) {
		String s1 = super.getParameter(s);
		//System.out.println("getParameter:"+s1);
		if (s1 == null) {
			return null;
		} else {
			return cleanXSS(cleanSQLInject(s1));
		}
	}
	
	//bgh 2018/05/30  新增
	/**-----------------------start--------------------------*/
	public Map<String,String[]> getParameterMap(){
		HashMap<String,String[]>   paramMap = (HashMap<String,String[]>)super.getParameterMap();
		paramMap = (HashMap<String,String[]>) paramMap.clone();
		for(Iterator iterator = (Iterator) paramMap.entrySet().iterator();iterator.hasNext();){
			Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) iterator.next();
			String[] values = entry.getValue();
			for(int i=0;i<values.length;i++){
				if(values[i]!=null){
					values[i] = cleanXSS(cleanSQLInject(values[i]));
				}
			}
			entry.setValue(values);
		}
		return paramMap;
	}
	/**-----------------------end--------------------------*/
	
	public String getHeader(String s) {
		String s1 = super.getHeader(s);
		//System.out.println("getHeader:"+s1);
		if (s1 == null) {
			return null;
		} else {
			return cleanXSS(cleanSQLInject(s1));
		}
	}

	public String cleanXSS(String src) {
		String temp = src;

		src = src.replaceAll("<", "<").replaceAll(">", ">");
		src = src.replaceAll("\\(", "(").replaceAll("\\)", ")");
		src = src.replaceAll("'", "'");
		src = src.replaceAll(";", ";");
		//bgh 2018/05/30  新增
		/**-----------------------start--------------------------*/
		src = src.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
		src = src.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41");
		src = src.replaceAll("eval\\((.*)\\)", "");
		src = src.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
		src = src.replaceAll("script", "");
		src = src.replaceAll("link", "");
		src = src.replaceAll("frame", "");
		/**-----------------------end--------------------------*/
		Pattern pattern = Pattern.compile("(eval\\((.*)\\)|script)",
				Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(src);
		src = matcher.replaceAll("");

		pattern = Pattern.compile("[\\\"\\'][\\s]*javascript:(.*)[\\\"\\']",
				Pattern.CASE_INSENSITIVE);
		matcher = pattern.matcher(src);
		src = matcher.replaceAll("\"\"");

		// 增加脚本
		src = src.replaceAll("script", "").replaceAll(";", "")
				/*.replaceAll("\"", "").replaceAll("@", "")*/
				.replaceAll("0x0d", "").replaceAll("0x0a", "");

		if (!temp.equals(src)) {
			// System.out.println("输入信息存在xss攻击!");
			// System.out.println("原始输入信息-->" + temp);
			// System.out.println("处理后信息-->" + src);

			log.error("输入信息存在xss攻击!");
			log.error("原始输入信息-->" + temp);
			log.error("处理后信息-->" + src);
			//this.getSession().setAttribute("xss", "输入信息存在xss攻击!");
			//this.setAttribute("xss", "输入信息存在xss攻击!");
		}
		return src;
	}

	// 需要增加通配,过滤大小写组合
	public String cleanSQLInject(String src) {
		String lowSrc = src.toLowerCase();
		String temp = src;
		String lowSrcAfter = lowSrc.replaceAll("insert ", "forbidI")
				.replaceAll("select ", "forbidS")
				.replaceAll("update ", "forbidU")
				.replaceAll("delete ", "forbidD").replaceAll("and", "forbidA")
				.replaceAll("or ", "forbidO");

		if (!temp.equals(src)) {
			// System.out.println("输入信息存在SQL攻击!");
			// System.out.println("原始输入信息-->" + temp);
			// System.out.println("处理后信息-->" + lowSrc);

			log.error("输入信息存在SQL攻击!");
			log.error("原始输入信息-->" + temp);
			log.error("处理后信息-->" + lowSrc);
			//this.getSession().setAttribute("xss", "输入信息存在xss攻击!");
		}
		if(lowSrcAfter.equals(lowSrc)){
			return src;
		}else{
			return lowSrcAfter;
		}
	}

}

你可能感兴趣的:(安全漏洞,安全漏洞)