一、跨站点脚本请求编制
问题体现:网页中存在类似
<script>tagJson = decodeURI('${tagJson}')的内容,则容易被注入类似下面内容进行攻击
如果您有这样的问题存在,那只能从您自己的代码中进行解决了,最好不要再页面中存在el表达式;
除去上面提到的这种情况外,其他情况的解决方法:可以对一些特殊的字符进行拦截处理:
类似:http://blog.csdn.net/mym43210/article/details/41082999
我的解决办法,具体代码实现
1、在web.xml文件中配置过滤器
InjectFilter
com.filter.InjectFilter
InjectFilter
/*
2、
过滤器过滤代码:
package com.filter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
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.Filter;
import javax.servlet.http.HttpServlet;
/**
* 通过过滤器过滤注入的特殊字符
* */
public class InjectFilter extends HttpServlet implements Filter {
private static final long serialVersionUID = 5286703103846683570L;
private String failPage = "/error.jsp";//发生注入时,跳转页面
public void doFilter(ServletRequest request,ServletResponse response,
FilterChain filterchain)throws IOException, ServletException {
//判断是否有注入攻击字符
HttpServletRequest req = (HttpServletRequest) request;
String inj = injectInput(req);
if (!inj.equals("")) {
request.getRequestDispatcher(failPage).forward(request, response);
return;
} else {
// 传递控制到下一个过滤器
filterchain.doFilter(request, response);
}
}
/**
* 判断request中是否含有注入攻击字符
* @param request
* @return
*/
public String injectInput(ServletRequest request) {
Enumeration e = request.getParameterNames();
String attributeName;
String attributeValues[];
String inj = "";
String injdb = "";
while (e.hasMoreElements()) {
attributeName = (String)e.nextElement();
//不对密码信息进行过滤,一般密码中可以包含特殊字符
if(attributeName.equals("userPassword")||attributeName.equals("confirmPassword")||attributeName.equals("PASSWORD")
||attributeName.equals("password")||attributeName.equals("PASSWORD2")||attributeName.equals("valiPassword")){
continue;
}
attributeValues = request.getParameterValues(attributeName);
for (int i = 0; i < attributeValues.length; i++) {
if(attributeValues[i]==null||attributeValues[i].equals(""))
continue;
inj = injectChar(attributeValues[i]);
if (!inj.equals(""))
{
return inj;
}
}
}
return inj;
}
/**
* 判断字符串中是否含有注入攻击字符
* @param str
* @return
*/
public String injectChar(String str) {
String inj_str = "\" ) \' * % < > &";
String inj_stra[] = inj_str.split(" ");
for (int i = 0 ; i < inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])>=0)
{
return inj_stra[i];
}
}
return "";
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
// System.out.println("----注入过滤器初始化----");
}
}
二、跨站点请求伪造(CSRF)
package com.common.util;
import javax.servlet.http.HttpServletRequest;
public class CSRFTool {
public static String getToken(HttpServletRequest request) {
return CSRFTokenManager.getTokenForSession(request.getSession());
}
}
package com.common.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.UUID;
/**
* {@link #getTokenForSession(HttpSession)} 得到当前会话的token(token获得的唯一方法)
*/
public final class CSRFTokenManager {
/**
* token参数名
*/
static final String CSRF_PARAM_NAME = "xToken";
/**
* 将token保存在session中
*/
public final static String CSRF_TOKEN_FOR_SESSION_ATTR_NAME = CSRFTokenManager.class.getName() + ".tokenval";
public static String getTokenForSession(HttpSession session) {
String token = null;
DESUtil des = new DESUtil("jrkj123");
synchronized (session) {
token = (String) session.getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);
// token = des.encryptStr(tokens1);
if (null == token) {
String tokens = UUID.randomUUID().toString();
token = des.encryptStr(tokens);
session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME, token);
}
}
return token;
}
/**
* 从会话中提取token值
*
* @param request
* @return
*/
public static String getTokenFromRequest(HttpServletRequest request) {
String token = request.getParameter(CSRF_PARAM_NAME);
if (token == null || "".equals(token)) {
token = request.getHeader(CSRF_PARAM_NAME);
}
return token;
}
private CSRFTokenManager() {
}
}
package com.common.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.SecureRandom;
public class DESUtil {
Key key ;
public DESUtil() {
}
public DESUtil(String str) {
setKey(str); // 生成密匙
}
public Key getKey() {
return key ;
}
public void setKey(Key key) {
this . key = key;
}
public void setKey(String strKey) {
try {
KeyGenerator _generator = KeyGenerator.getInstance ( "DES" );
_generator.init( new SecureRandom(strKey.getBytes("utf-8")));
SecureRandom secureRandom= SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(strKey.getBytes());
_generator.init(56, secureRandom);
this.key = _generator.generateKey();
_generator = null ;
} catch (Exception e) {
throw new RuntimeException("Error initializing class. Cause: " + e);
}
}
/**
* 加密 String 明文输入 ,String 密文输出
*/
public String encryptStr(String strMing) {
byte [] byteMi = null ;
byte [] byteMing = null ;
String strMi = "" ;
BASE64Encoder base64en = new BASE64Encoder();
try {
byteMing = strMing.getBytes( "UTF-8" );
byteMi = this.encryptByte(byteMing);
strMi = base64en.encode(byteMi);
} catch (Exception e) {
throw new RuntimeException("Error initializing class. Cause: " + e);
} finally {
base64en = null ;
byteMing = null ;
byteMi = null ;
}
return strMi;
}
/**
* 解密 以 String 密文输入 ,String 明文输出
*
* @param strMi
* @return
*/
public String decryptStr(String strMi) {
BASE64Decoder base64De = new BASE64Decoder();
byte [] byteMing = null ;
byte [] byteMi = null ;
String strMing = "" ;
try {
byteMi = base64De.decodeBuffer(strMi);
byteMing = this.decryptByte(byteMi);
strMing = new String(byteMing, "UTF-8" );
} catch (Exception e) {
throw new RuntimeException("Error initializing class. Cause: " + e);
} finally {
base64De = null ;
byteMing = null ;
byteMi = null ;
}
return strMing;
}
/**
* 加密以 byte[] 明文输入 ,byte[] 密文输出
*
* @param byteS
* @return
*/
private byte [] encryptByte( byte [] byteS) {
byte [] byteFina = null ;
Cipher cipher;
try {
cipher = Cipher.getInstance ( "DES" );
cipher.init(Cipher.ENCRYPT_MODE , key );
byteFina = cipher.doFinal(byteS);
} catch (Exception e) {
throw new RuntimeException("Error initializing class. Cause: " + e);
} finally {
cipher = null ;
}
return byteFina;
}
/**
* 解密以 byte[] 密文输入 , 以 byte[] 明文输出
*
* @param byteD
* @return
*/
private byte [] decryptByte( byte [] byteD) {
Cipher cipher;
byte [] byteFina = null ;
try {
cipher = Cipher.getInstance ( "DES" );
cipher.init(Cipher.DECRYPT_MODE , key );
byteFina = cipher.doFinal(byteD);
} catch (Exception e) {
throw new RuntimeException("Error initializing class. Cause: " + e);
} finally {
cipher = null ;
}
return byteFina;
}
public static void main(String[] args) throws Exception {
DESUtil des = new DESUtil("jrkj123");
String str1 = "4cdbc040657a4847b2667e31d9e2c3d9" ;
// DES 加密字符串
String str2 = des.encryptStr(str1);
// DES 解密字符串
String deStr = des.decryptStr(str2);
System. out .println( " 加密前: " + str1);
System. out .println( " 加密后: " + str2);
System. out .println( " 解密后: " + deStr);
}
}
package com.common.interceptors;
import com.common.util.CSRFTool;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TokenAjaxInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setContentType("multipart/form-data");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
//从前端获取到的token
String token = request.getHeader("token");
response.setHeader("token", token);//将token放到response中
//后台生成的token
String req_token = CSRFTool.getToken(request);
//判断是不是ajax请求
String requestUri = request.getRequestURI(); //请求完整路径,可用于登陆后跳转
String contextPath = request.getContextPath(); //项目下完整路径
String url = requestUri.substring(contextPath.length()); //请求页面
// System.out.println("发生拦截...");
// System.out.println("来自:"+requestUri+"的请求");
System.out.println("来自url:"+url);
/**
* 拦截目录下请求,是否为ajax请求
* 是:需要验证token是否正常;正常-->通过,不正常-->不通过
* 否:全部拦截
*/
if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")){
//如果是ajax请求响应头会有,x-requested-with
System.out.println("发生ajax请求...");
if(req_token != null){
//验证token是否合理
if(token.equals(req_token) || token == req_token){
System.out.println("token验证正确,请求成功");
return true;
}else{
System.out.println("token验证不正确,请求失败");
return false;
}
}else {
System.out.println("没有token信息,请求失败");
return false;
}
}else{
System.out.println("非ajax请求,拦截...");
return false;
}
}
}
HEAD
PUT
DELETE
OPTIONS
TRACE
/*