漏洞 host 攻擊 過濾器 新增白名單
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
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.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.ResourceUtils;
import com.itsv.gbp.core.web.filter.CustomException;
/**
* @preserve
*/
public class IntceptorFilter extends HttpServlet implements Filter {
private FilterConfig filterConfig; // Handle the passed-in FilterConfig
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
/**
* Process the request/response pair
*
* @preserve
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// hwj
res.addHeader("Set-Cookie", " Path=/; HttpOnly"); //Cookie 缺少 HttpOnly屬性
res.addHeader("X-Frame-Options","SAMEORIGIN"); //防止 x-frame-options 缺失
/*x-frame-options 屬性值
* DENY 表示該頁面不允許在 frame 中展示,即便是在相同域名的頁面中巢狀也不允許。
* SAMEORIGIN 表示該頁面可以在相同域名頁面的 frame 中展示
* ALLOW-FROM uri表示該頁面可以在指定來源的 frame 中展示。
*/
// 頭攻擊檢測host 新增白名單
String requestHost = req.getHeader("host"); //當前訪問的url地址host
if (requestHost != null && !isWhite(requestHost)) {
res.setStatus(403);
return;
}
// clientRequest 記錄真正的被請求的 URL 比如 /index.jsp;/login.jsp;/
String home = req.getScheme() + "://" + req.getServerName() + ":"
+ req.getServerPort();
String clientRequest = req.getRequestURL() + "?" + req.getQueryString();// req.getServletPath();
System.out.println("過濾器===========" + clientRequest);
// -------lfh 2016.2.24,針對登陸介面的引數判斷--------//
Map parameters = request.getParameterMap();
if (parameters != null && parameters.size() > 0) {
for (Iterator iter = parameters.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
String[] values = (String[]) parameters.get(key);
if ("dwdm".equals(key) || "password".equals(key)
|| "dwdjzh".equals(key)) {
for (int i = 0; i < values.length; i++) {
if (!valueFilter1(values[i])
|| !scriptingFilter(values[i])) {
try {
res.sendRedirect(home);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
}
}
}
}
// ---------------//
// hwj
String oldUrl = req.getRequestURL() + "";
String newUrl = home;
String[] urls = oldUrl.replaceAll(newUrl, "").split("/");// lfh20151116
int urlslen = urls.length;// lfh20151116
if(urlslen>0){
oldUrl = urls[urlslen - 1].toLowerCase();// lfh20151116
}
// oldUrl=oldUrl.replaceAll(newUrl,
// "").replaceAll("/","").toString().toLowerCase();//hwj
oldUrl = oldUrl.substring(0, oldUrl.length());
// if(oldUrl.equals("common") || oldUrl.equals("download") ||
// oldUrl.equals("images") || oldUrl.equals("js") ||
// oldUrl.equals("message") || oldUrl.equals("style")||
// oldUrl.equals("system") || oldUrl.equals("upload") ||
// oldUrl.equals("userfiles"))//hwj
if (oldUrl.equals("system") || oldUrl.equals("userfiles"))// lfh20151116
{
try {
res.sendRedirect(home);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
/*
* if(sqlValidate(clientRequest)) { try { res.sendRedirect(home); }
* catch (IOException e) { // TODO Auto-generated catch block
* e.printStackTrace(); } return; }
*/
// 如果使用者請求url或request引數中含有特殊字元 ,直接跳回首頁面 || !parametersFileter(req)
if (!scriptingFilter(clientRequest)) {
try {
res.sendRedirect(home);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
} else {
req.setCharacterEncoding("GBK");
doNext(request, response, filterChain);
return;
}
}
// 對所有屬性進行過濾
private boolean parametersFileter(HttpServletRequest request) {
Enumeration e = request.getParameterNames();
String parameterName = "";
String parameterValue = "";
while (e.hasMoreElements()) {
parameterName = (String) e.nextElement();
parameterValue = request.getParameter(parameterName);
System.out.println(parameterName + ": " + parameterValue + "");
if (!valueFilter(parameterValue)) {
return false;
}
}
return true;
}
// 判斷屬性中是否含有特殊字元
public boolean valueFilter(String paramValue) {
String param = paramValue.toLowerCase(); // 轉換成小寫
String paramLower = paramValue.toLowerCase();// 轉換成小寫
if (paramValue != null && paramValue.length() > 0) {
paramLower = paramLower.replaceAll("\\(", "").replaceAll("\\)", "")
.replaceAll("\'", "").replaceAll(" ", "")
.replaceAll("\"", "").replaceAll("<", "")
.replaceAll(">", "").replaceAll("\r", "")
.replaceAll("\n", "").replaceAll("!", "")
.replaceAll("=", "").replaceAll("iframe", "")
.replaceAll("alert", "")
.replaceAll("prompt", "").trim();
// .replaceAll("update", "")
// .replaceAll("delete", "")
// .replaceAll("insert", "")
// .replaceAll("select", "")
// .replaceAll("(?i)and","")
// .replaceAll("(?i)or","")
// .replaceAll("(?i)not","")
}
return param.equals(paramLower);
}
public boolean valueFilter1(String paramValue) {
String param = paramValue.toLowerCase(); // 轉換成小寫
String paramLower = paramValue.toLowerCase();// 轉換成小寫
if (paramValue != null && paramValue.length() > 0) {
paramLower = paramLower.replaceAll("\\(", "").replaceAll("\\)", "")
.replaceAll("\'", "").replaceAll(" ", "")
.replaceAll("\"", "").replaceAll("<", "")
.replaceAll(">", "").replaceAll("\r", "")
.replaceAll("\n", "").replaceAll("!", "")
.replaceAll("=", "").replaceAll("iframe", "")
.replaceAll("script", "").replaceAll("alert", "")
.replaceAll("prompt", "").replaceAll("confirm", "")
.replaceAll("update", "").replaceAll("delete", "")
.replaceAll("insert", "").replaceAll("select", "")
.replaceAll("(?i)and", "").replaceAll("(?i)or", "")
.replaceAll("(?i)not", "").trim();
}
return param.equals(paramLower);
}
private void doNext(ServletRequest request, ServletResponse response,
FilterChain filterChain) {
try {
filterChain.doFilter(request, response);
} catch (ServletException sx) {
filterConfig.getServletContext().log(sx.getMessage());
String message = "";
Exception e=(Exception) sx.getRootCause();
if(e instanceof CustomException){
message = "{\"errorCode\":\"999\",\"message\":\""+e.getMessage()+"\"}";
} else if(e instanceof NoSuchMethodException){
String className = sx.getMessage();
if(className.indexOf("com.itsv.chy.wsqh.zdwh.action.WebServiceAction")!=-1){
message="{\"errorCode\":\"998\",\"message\":\"該介面方法不存在\"}";
}
}
if(!StringUtils.isEmpty(message)){
PrintWriter out = null;
try {
response.setContentType("application/json;charset=UTF-8");
out = response.getWriter();
out.print(message);
out.flush();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
} catch (IOException iox) {
filterConfig.getServletContext().log(iox.getMessage());
}
}
/*
* // 對url字串進行過濾 public String scriptingFilter(String value) {
*
* if(value ==null){ return null; }
*
* StringBuffer result = new StringBuffer(value.length());
*
* for(int i=0; i<value.length(); ++i){ switch(value.charAt(i)){ case '<' :
* result.append("<"); break; case '>' : result.append(">"); break;
* case '"' : result.append("""); break; case '\'':
* result.append("'"); break; case '%' : result.append("%"); break;
* // case ';' : result.append(";"); break; case '(' :
* result.append("("); break; case ')' : result.append(")"); break;
* // case '&' : result.append("&"); break; case '+' :
* result.append("+"); break; default : result.append(value.charAt(i));
* break; }
*
* }
*
* return new String(result); }
*/
// 判斷屬性中是否含有特殊字元
public boolean scriptingFilter(String paramValue) {
String param = paramValue.toLowerCase(); // 轉換成小寫
String paramLower = paramValue.toLowerCase();// 轉換成小寫
if (paramValue != null && paramValue.length() > 0) {
paramLower = paramLower.replaceAll("\'", "").replaceAll(" ", "")
.replaceAll("\"", "").replaceAll("<", "")
.replaceAll(">", "").replaceAll("\r", "")
.replaceAll("\n", "").replaceAll("!", "")
// hwj
/*
* .replaceAll("\\(", "") .replaceAll("\\)", "")
* .replaceAll("%7d", "")//} .replaceAll("%7b", "")//{
* .replaceAll("\\[", "") .replaceAll("\\]", "")
*/
.replaceAll("iframe", "")
//.replaceAll("script", "")
.replaceAll("alert", "").replaceAll("confirm", "")
// hwj
/*
* .replaceAll("document", "") .replaceAll("eval", "")
*/
.replaceAll("prompt", "").trim();
}
return param.equals(paramLower);
}
// hwj
/*
* //效驗 protected static boolean sqlValidate(String str) { str =
* str.toLowerCase();//統一轉為小寫 String badStr =
* "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|"
* +
* "char|declare|sitename|net user|xp_cmdshell|;|or|+|,|like'|and|exec|execute|insert|create|drop|"
* + "table|from|grant|group_concat|column_name|" +
* "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|"
* +
* "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|#";//過濾掉的sql關鍵字
* ,可以手動新增 String[] badStrs = badStr.split("\\|"); for (int i = 0; i <
* badStrs.length; i++) { if (str.indexOf(badStrs[i]) >= 0) { return true; }
* } return false; }
*/
public static String StringFilter(String str) throws PatternSyntaxException {
// 清除掉所有特殊字元
String regEx = "[`[email protected]#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?《》]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
return m.replaceAll("").trim();
}
/**
* 判斷host 是否存在白名單內
* serverWhiteList.json 檔案內配置白名單 用;隔開
* @param host
* @return
*/
public static boolean isWhite(String host) {
String jsonstr = readJsonFile("serverWhiteList.json");
if(jsonstr ==null || jsonstr.length()==0){
return true;
}
String[] jsonstrs = jsonstr.split(";");
for(String str : jsonstrs){
if (str != null && str.equals(host)) {
return true;
}
}
return false;
}
/**
* 獲取json 檔案內容
* @param fileName json 檔名稱
* @return
*/
public static String readJsonFile(String fileName) {
String jsonStr = "";
try {
File jsonFile = ResourceUtils.getFile("classpath:"+fileName); //獲取根目錄下的json 檔案
FileReader fileReader = new FileReader(jsonFile);
Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8");
int ch = 0;
StringBuffer sb = new StringBuffer();
while ((ch = reader.read()) != -1) {
sb.append((char) ch);
}
fileReader.close();
reader.close();
jsonStr = sb.toString();
return jsonStr;
} catch (Exception e) {
return jsonStr;
// TODO: handle exception
}
}
/**
* Clean up resources
*
* @preserve
*/
public void destroy() {
}
}
json 檔案內格式 localhost:7001;localhost:7002;