WEB安全:XSS漏洞與SQL注入漏洞介紹及解決方案
對web安全方面的知識非常薄弱,這篇文章把Xss跨站攻擊和sql注入的相關知識整理了下,希望大家多多提意見。
對於防止sql注入發生,我只用過簡單拼接字符串的注入及參數化查詢,可以說沒什么好經驗,為避免后知后覺的犯下大錯,專門參考大量前輩們的心得,小小的總結一下,歡迎大家拍磚啊
一、跨站腳本攻擊(XSS)
跨站腳本攻擊的原理
XSS又叫CSS (Cross Site Script) ,跨站腳本攻擊。它指的是惡意攻擊者往Web頁面里插入惡意腳本代碼,而程序對於用戶輸入內容未過濾,當用戶瀏覽該頁之時,嵌入其中Web里面的腳本代碼會被執行,從而達到惡意攻擊用戶的特殊目的。
跨站腳本攻擊的危害:竊取cookie、放蠕蟲、網站釣魚 ...
跨站腳本攻擊的分類主要有:存儲型XSS、反射型XSS、DOM型XSS
XSS漏洞是Web應用程序中最常見的漏洞之一。如果您的站點沒有預防XSS漏洞的固定方法,那么就存在XSS漏洞。這個利用XSS漏洞的病毒之所以具有重要意義是因為,通常難以看到XSS漏洞的威脅,而該病毒則將其發揮得淋漓盡致。
XSS工作流程

如下情況,請求跳轉到百度,並將查詢到的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("&");
break;
case '<': sb.append("<");
break;
case '>': sb.append(">");
break;
case '"': sb.append(""");
break;
case '\'': sb.append("'");
break;
case '/': sb.append("/");
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注入漏洞
SQL注入攻擊的原理:
使用用戶輸入的參數拼湊SQL查詢語句,使用戶可以控制SQL查詢語句。詳細關於sql注入的信息請參考:SQL注入攻防入門詳解
防御方法
- 使用預編譯語句,
- 綁定變量
- 使用安全的存儲過程
- 檢查數據類型
- 使用安全函數
建議方法:不要使用拼接的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)、開放重定向漏洞等等,以后再慢慢學習!!!

