在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

Web安全-防御前端渗透的编码技巧

2016-12-20 13:11| 发布者: zhangjf| 查看: 567| 评论: 0

摘要: 防御前端渗透的编码技巧 前端攻击主要包括XSS(跨站脚本攻击)、CSRF(跨站请求伪造)、SQL注入。网上有很多,“Noodles”的技术周刊 中就有很多详细的解释。 一、 XSS&SQL注入 它们的共同之处是在用户输入或抓 ...
防御前端渗透的编码技巧

前端攻击主要包括XSS(跨站脚本攻击)、CSRF(跨站请求伪造)、SQL注入。网上有很多,“Noodles”的技术周刊 中就有很多详细的解释。

一、 XSS&SQL注入

它们的共同之处是在用户输入或抓包修改的情况下,由于前后端没有有效过滤,导致恶意代码的执行。

1、XSS&SQL注入编码技巧:

前端的转义是必不可少的,但是抓包就除外了,所以我们重点放在后端。网上有个XSSProject,地址为:http://yunjiechao-163-com.ite...

也可以直接用下面的代码:

  1. /**
  2. *
  3. * XSS过滤
  4. * @author Alex
  5. *
  6. */
  7. public class XSSFilter implements Filter{
  8. public void doFilter(ServletRequest arg0, ServletResponse arg1,
  9. FilterChain arg2) throws IOException, ServletException {
  10. // TODO Auto-generated method stub
  11. HttpServletRequest request = (HttpServletRequest) arg0;
  12. HttpServletResponse response = (HttpServletResponse) arg1;
  13. XssAndSqlHttpServletRequestWrapper xssRequest = new XssAndSqlHttpServletRequestWrapper(request);//采用包装器过滤掉恶意输入
  14. arg2.doFilter(xssRequest, response);
  15. }
  16. }
复制代码
  1. /**
  2. *
  3. * XSS包装器
  4. * @author Alex
  5. *
  6. */
  7. public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
  8. private Logger log = Logger.getLogger(getClass());
  9. private HttpServletRequest orgRequest = null;
  10. public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
  11. super(request);
  12. orgRequest = request;
  13. }
  14. @Override
  15. public String getParameter(String name) {
  16. String value = null;
  17. try {
  18. //不过滤菜单
  19. if(!name.equals("menuHtml")){//是我自己的菜单,大家无视掉!
  20. value = super.getParameter(xssEncode(name));
  21. if (value != null) {
  22. value = URLDecoder.decode(value, Constant.UTF);//或用BASE处理中文乱码
  23. value = xssEncode(value);
  24. }
  25. }else{
  26. value = super.getParameter(name);
  27. }
  28. } catch (UnsupportedEncodingException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. log.error(e.getMessage());
  32. }
  33. return value;
  34. }
  35. @Override
  36. public String getHeader(String name) {//请求头也可能插入
  37. String value = null;
  38. try {
  39. value = super.getHeader(xssEncode(name));
  40. if (value != null) {
  41. value = xssEncode(value);
  42. }
  43. } catch (Exception e) {
  44. // TODO Auto-generated catch block
  45. e.printStackTrace();
  46. log.error(e.getMessage());
  47. }
  48. return value;
  49. }
  50. private static String xssEncode(String s) {//替换成中文字符
  51. if (s == null || s.isEmpty()) {
  52. return s;
  53. }else{
  54. s = stripXSSAndSql(s);
  55. }
  56. StringBuilder sb = new StringBuilder(s.length() + 16);
  57. for (int i = 0; i < s.length(); i++) {
  58. char c = s.charAt(i);
  59. switch (c) {
  60. case '>':
  61. sb.append(">");// 转义大于号
  62. break;
  63. case '<':
  64. sb.append("<");// 转义小于号
  65. break;
  66. case ''':
  67. sb.append("'");// 转义单引号
  68. break;
  69. case '"':
  70. sb.append(""");// 转义双引号
  71. break;
  72. case '&':
  73. sb.append("&");// 转义&
  74. break;
  75. case '#':
  76. sb.append("#");// 转义#
  77. break;
  78. default:
  79. sb.append(c);
  80. break;
  81. }
  82. }
  83. return sb.toString();
  84. }
  85. public HttpServletRequest getOrgRequest() {
  86. return orgRequest;
  87. }
  88. public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
  89. if (req instanceof XssAndSqlHttpServletRequestWrapper) {
  90. return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();
  91. }
  92. return req;
  93. }
  94. public static String stripXSSAndSql(String value) {
  95. if (value != null) {
  96. // Avoid anything between script tags
  97. Pattern scriptPattern = Pattern.compile("<[rn| | ]*script[rn| | ]*>(.*?)</[rn| | ]*script[rn| | ]*>", Pattern.CASE_INSENSITIVE);
  98. value = scriptPattern.matcher(value).replaceAll("");
  99. // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e-xpression
  100. scriptPattern = Pattern.compile("src[rn| | ]*=[rn| | ]*[\"|\'](.*?)[\"|\']", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  101. value = scriptPattern.matcher(value).replaceAll("");
  102. // Remove any lonesome </script> tag
  103. scriptPattern = Pattern.compile("</[rn| | ]*script[rn| | ]*>", Pattern.CASE_INSENSITIVE);
  104. value = scriptPattern.matcher(value).replaceAll("");
  105. // Remove any lonesome <script ...> tag
  106. scriptPattern = Pattern.compile("<[rn| | ]*script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  107. value = scriptPattern.matcher(value).replaceAll("");
  108. // Avoid eval(...) expressions
  109. scriptPattern = Pattern.compile("eval\((.*?)\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  110. value = scriptPattern.matcher(value).replaceAll("");
  111. // Avoid e-xpression(...) expressions
  112. scriptPattern = Pattern.compile("e-xpression\((.*?)\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  113. value = scriptPattern.matcher(value).replaceAll("");
  114. // Avoid javascript:... expressions
  115. scriptPattern = Pattern.compile("javascript[rn| | ]*:[rn| | ]*", Pattern.CASE_INSENSITIVE);
  116. value = scriptPattern.matcher(value).replaceAll("");
  117. // Avoid vbscript:... expressions
  118. scriptPattern = Pattern.compile("vbscript[rn| | ]*:[rn| | ]*", Pattern.CASE_INSENSITIVE);
  119. value = scriptPattern.matcher(value).replaceAll("");
  120. // Avoid onload= expressions
  121. scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  122. value = scriptPattern.matcher(value).replaceAll("");
  123. }
  124. return value;
  125. }
  126. }
复制代码

web.xml中添加

  1. <filter>
  2. <filter-name>XSSFilter</filter-name>
  3. <filter-class>com.xxx.filter.XSSFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>XSSFilter</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>
复制代码

二、CSRF

1、Referer的方式

在过滤器中判读请求头中Referer的值,如同域名就可以访问。

  1. String referer = request.getHeader("Referer");
  2. if(referer.startsWith("http://www.xxx.com")){
  3. chain.doFilter(request, response);
  4. }
复制代码

弊端:用户过于关心自己的浏览记录,可能会屏蔽这个值,导致正常用户也不能访问系统。

2、采用Token的方式

弊端:黑客发送给用户一个链接,盗取Token,这种方式叫CXRF。

3、JWT的方式

今天闲来无事就试了一下这种方法,感觉还不错,跟大家分享一下。开源社区有源码,我没用那个就自己随便写了点。

下面是代码:

  1. /**
  2. *
  3. * @author Alex
  4. *
  5. */
  6. public class JWTFilter implements Filter{
  7. private Logger log = Logger.getLogger(getClass());
  8. public void destroy() {
  9. // TODO Auto-generated method stub
  10. }
  11. public void doFilter(ServletRequest arg0, ServletResponse arg1,
  12. FilterChain arg2) throws IOException, ServletException {
  13. // TODO Auto-generated method stub
  14. HttpServletRequest request = (HttpServletRequest) arg0;
  15. HttpServletResponse response = (HttpServletResponse) arg1;
  16. try {
  17. String jwt = null;
  18. Cookie[] cookies = request.getCookies();
  19. for(Cookie cookie:cookies){
  20. if(cookie.getName().equals("jwt")){
  21. jwt = cookie.getValue();
  22. break;
  23. }
  24. }
  25. String userName = (String) request.getSession().getAttribute("userName");
  26. if(jwt==null){//Cookie中无JWT
  27. jwt = JWTWrapper.createJWT(userName);//userName设置为接收方
  28. response.addHeader("Set-Cookie", "jwt="+jwt+";Path=/;HttpOnly");//防止JS获取Cookie
  29. }else{
  30. int judge = JWTWrapper.judgeJWT(jwt, userName);//判断JWT是否过期
  31. if(judge==-1){//被篡改
  32. return ;
  33. }else if(judge==0){//过期或将要过期
  34. String jwt_new = JWTWrapper.createJWT(userName);
  35. response.addHeader("Set-Cookie", "jwt="+jwt_new+";Path=/;HttpOnly");
  36. }
  37. }
  38. arg2.doFilter(request, response);
  39. } catch (Exception e) {
  40. // TODO: handle exception
  41. e.printStackTrace();
  42. log.error(e.getMessage());
  43. }
  44. }
  45. public void init(FilterConfig arg0) throws ServletException {
  46. // TODO Auto-generated method stub
  47. }
  48. }
复制代码
  1. /**
  2. *
  3. * JWT包装器
  4. * @author Alex
  5. *
  6. */
  7. public class JWTWrapper {
  8. private static String iss = "XXX";//签发者
  9. private static Long exp_add = Long.valueOf(30*60*1000);//过期时间,默认半小时
  10. private static String des_key = "XXXXXXX";
  11. /**
  12. * 创建JWT
  13. * @param aud 接收方
  14. */
  15. public static String createJWT(String aud){
  16. String jwt = null;
  17. try {
  18. Long iat = System.currentTimeMillis();//签发时间,应该用秒,用毫秒省事了
  19. String header = "{"typ":"JWT","alg":"DES"}";//头部
  20. String payload = "{"iss":""+iss+"","aud":""+aud+"","iat":"+iat+","exp":"+(iat+exp_add)+"}";//载荷
  21. String signature = null;//签名
  22. header = Base64.encodeBase64URLSafeString(header.getBytes(Constant.UTF));
  23. payload = Base64.encodeBase64URLSafeString(payload.getBytes(Constant.UTF));
  24. signature = DesUtil.encrypt(header+"."+payload, des_key);//des加密速度快些,可以用其它加密
  25. jwt = header+"."+payload+"."+signature;
  26. } catch (Exception e) {
  27. // TODO: handle exception
  28. e.printStackTrace();
  29. System.out.println(e.getMessage());
  30. }
  31. return jwt;
  32. }
  33. /**
  34. * 验证JWT
  35. * @param jwt
  36. * @param aud 接收方
  37. * @return
  38. */
  39. public static int judgeJWT(String jwt,String aud){
  40. int judge = -1;//-1:篡改的JWT
  41. try {
  42. if(jwt.indexOf(".")!=-1){//分割JWT
  43. String[] strs = jwt.split("\.");
  44. String signature_new = strs[0]+"."+strs[1]+"."+DesUtil.encrypt(strs[0]+"."+strs[1], des_key);//签名
  45. if(signature_new.startsWith(jwt)){//未被篡改
  46. String payload = new String(Base64.decodeBase64(strs[1]), Constant.UTF);//载荷
  47. JSONObject JO = JSONObject.fromObject(payload);
  48. if(JO.getString("iss").equals(iss)&&JO.getString("aud").equals(aud)){
  49. Long exp = JO.getLong("exp");
  50. Long iat = System.currentTimeMillis();//签发时间
  51. if(exp>iat&&(exp-iat)>1*60*1000){//过期时间>1分钟
  52. judge = 1;//正常,不需更新JWT
  53. }else{
  54. judge = 0;//JWT过期或将要过期
  55. }
  56. }
  57. }
  58. }
  59. } catch (Exception e) {
  60. // TODO: handle exception
  61. e.printStackTrace();
  62. System.out.println(e.getMessage());
  63. }
  64. return judge;
  65. }
  66. }
复制代码

大家有要用的,就动手试试吧!

先这样吧,有时间会继续追加。不太会写文章,本人工作经验不多,希望大家海涵,哈哈。

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-7 20:33

Copyright 2015-2025 djqfx

返回顶部