摘要:注入編碼技巧前端的轉義是必不可少的,為了防止抓包修改參數值,我們重點放在后端。為了契合前后分離的說法。所以請不要認為可以預防,這是一種錯誤的理解目前存儲的方式有以下幾種存取優點不易遭受可設置弊端易遭受。
前端攻擊主要包括XSS(跨站腳本攻擊)、CSRF(跨站請求偽造)、SQL注入。“Noodles”的技術周刊 中有詳細解釋。
一、XSS&SQL注入它們的發生是在用戶惡意輸入和抓包修改情況下,由于前后端沒有做字符過濾,導致惡意代碼的執行。
1、XSS&SQL注入編碼技巧前端的轉義是必不可少的,為了防止抓包修改參數值,我們重點放在后端。網上有個XSSProject,地址為:http://yunjiechao-163-com.ite...,其中封裝好了一些功能,特別方便。。。
也可以用下面的代碼:
/** * * XSS過濾 * @author Alex * */ public class XSSFilter implements Filter{ public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub HttpServletRequest request = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; XssAndSqlHttpServletRequestWrapper xssRequest = new XssAndSqlHttpServletRequestWrapper(request);//采用包裝器過濾掉惡意字符 arg2.doFilter(xssRequest, response); } }
/** * * XSS包裝器 * @author Alex * */ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper { private Logger log = Logger.getLogger(getClass()); private HttpServletRequest orgRequest = null; public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) { super(request); orgRequest = request; } @Override public String getParameter(String name) { String value = null; try { //不過濾菜單 if(!name.equals("menuHtml")){//自己的菜單,無視掉 value = super.getParameter(xssEncode(name)); if (value != null) { value = URLDecoder.decode(value, Constant.UTF);//處理中文亂碼 value = xssEncode(value); } }else{ value = super.getParameter(name); } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e.getMessage()); } return value; } @Override public String getHeader(String name) {//請求頭也可能插入 String value = null; try { value = super.getHeader(xssEncode(name)); if (value != null) { value = xssEncode(value); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e.getMessage()); } return value; } private static String xssEncode(String s) {//替換成中文字符 if (s == null || s.isEmpty()) { return s; }else{ s = stripXSSAndSql(s); } StringBuilder sb = new StringBuilder(s.length() + 16); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { 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(c); break; } } return sb.toString(); } public HttpServletRequest getOrgRequest() { return orgRequest; } public static HttpServletRequest getOrgRequest(HttpServletRequest req) { if (req instanceof XssAndSqlHttpServletRequestWrapper) { return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest(); } return req; } public static String stripXSSAndSql(String value) { if (value != null) { // Avoid anything between script tags Pattern scriptPattern = Pattern.compile("<[ | | ]*script[ | | ]*>(.*?)[ | | ]*script[ | | ]*>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e-xpression scriptPattern = Pattern.compile("src[ | | ]*=[ | | ]*["|"](.*?)["|"]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome tag scriptPattern = Pattern.compile("[ | | ]*script[ | | ]*>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome ,如果Chrome沒有顯示彈出,請設置:上圖的設置會取消瀏覽器的xss-auditor啟動(一種瀏覽器內建的xss防御模塊,可阻止大多數反射型xss)。如果不想使用上圖的方式啟動,可以將服務端代碼改為:
@app.route("/hello-injection") def hello_inject(): person = {"name": "asd", "secret": "aaaaaaaaaaa"} if request.args.get("name"): person["name"] = request.args.get("name") template = """Hello %s
""" % person["name"] response = make_response(person["name"]) response.headers["X-XSS-Protection"] = "0" # xss auditor關閉 return response將xss-auditor關閉可以彈出。如果開啟呢?還能彈出嗎?修改成以下代碼:
@app.route("/hello-injection") def hello_inject(): person = {"name": "asd", "secret": "aaaaaaaaaaa"} if request.args.get("name"): person["name"] = request.args.get("name") template = """Hello %s
""" % person["name"] response = make_response(person["name"].replace(">", ">;")) response.headers["X-XSS-Protection"] = "1" # xss auditor開啟 return response竟然可以彈出。。。這里介紹下auditor的:
通常情況下,我們都會對用戶提交的數據進行一些處理,如果這些處理導致和提交的內容不一樣了,但是仍然可以執行,比如像本例一樣。那么xss auditor 就無能為力了。不過xss auditor本身的智能度也挺高,像字符編碼,大小寫變化這種變化依然躲不過xss auditor。二、CSRF 1、Referer在過濾器或攔截器中判讀請求頭的Referer值,如果同域名就可以繼續訪問,否則請求被攔截。
String referer = request.getHeader("Referer"); if(referer.startsWith("http://www.xxx.com")){ chain.doFilter(request, response); }else{ return ; }弊端:有些網站或用戶會停用Referer,所以上面這種方式會導致正常用戶也不能訪問系統。
2、Token這種方式用的最多,是將Token作為每次請求的參數來驗證請求是否有效。
弊端:黑客可通過發送用戶鏈接,盜取Token值。
3、JWT為何用JWT?
白話意思是用戶的信息可放在客戶端保存,代替之前服務器session的保存方式。為了契合前后分離的說法。所以請不要認為JWT可以預防CSRF,這是一種錯誤的理解!
目前存儲JWT的方式有以下幾種:
1、Cookie存取
優點:不易遭受XSS(可設置HttpOnly)
弊端:易遭受CSRF。
2、LocalStorage
優點:不產生CSRF、存儲量大
缺點:易遭受XSS、難清除(Android機很難清除)
3、YOU stick the (JWT) token in the Authorization HTTP header of a request.這是http://stackoverflow.com/描述的一種方法。
總結起來就是各有優缺點。個人覺得CSRF較難防御,看個人輕重程度了。
下面是代碼:
其中有些是自己項目的邏輯,請需修改。
/** * * @author Alex * */ public class JWTFilter implements Filter{ private Logger log = Logger.getLogger(getClass()); public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub HttpServletRequest request = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal(); try { String jwt = null; Cookie[] cookies = request.getCookies(); for(Cookie cookie:cookies){ if(cookie.getName().equals("jwt")){ jwt = cookie.getValue(); break; } } String referer = request.getHeader("Referer"); String userName = (String) principal.getName(); if(referer!=null&&referer.indexOf("/XXX/login")!=-1&&jwt==null){//登錄時設置JWT及判斷Cookie中有無JWT jwt = JWTWrapper.createJWT(userName);//userName單點登錄用戶名 response.addHeader("Set-Cookie", "jwt="+jwt+";Path=/;HttpOnly");//防止JS獲取Cookie }else{ int judge = JWTWrapper.judgeJWT(jwt, userName);//判斷JWT是否過期 if(judge==-1){//被篡改 return ; }else if(judge==0){//過期或將要過期 String jwt_new = JWTWrapper.createJWT(userName); response.addHeader("Set-Cookie", "jwt="+jwt_new+";Path=/;HttpOnly"); } } arg2.doFilter(request, response); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); log.error(e.getMessage()); } } public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }/** * * JWT包裝器 * @author Alex * */ public class JWTWrapper { private static String iss = "XXX";//簽發者 private static Long exp_add = Long.valueOf(30*60*1000);//過期時間半小時 private static String des_key = "XXXXXXX";//des密鑰 /** * 創建JWT * @param aud 接收方 */ public static String createJWT(String aud){ String jwt = null; try { Long iat = System.currentTimeMillis();//簽發時間,應該用秒 String header = "{"typ":"JWT","alg":"DES"}";//頭部 String payload = "{"iss":""+iss+"","aud":""+aud+"","iat":"+iat+","exp":"+(iat+exp_add)+"}";//載荷 String signature = null;//簽名 header = Base64.encodeBase64URLSafeString(header.getBytes(Constant.UTF)); payload = Base64.encodeBase64URLSafeString(payload.getBytes(Constant.UTF)); signature = DesUtil.encrypt(header+"."+payload, des_key);//可用其它加密 jwt = header+"."+payload+"."+signature; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); System.out.println(e.getMessage()); } return jwt; } /** * 驗證JWT * @param jwt * @param aud 接收方 * @return */ public static int judgeJWT(String jwt,String aud){ int judge = -1;//-1:篡改的JWT try { if(jwt!=null&&jwt.indexOf(".")!=-1){//分割JWT String[] strs = jwt.split("."); String signature_new = strs[0]+"."+strs[1]+"."+DesUtil.encrypt(strs[0]+"."+strs[1], des_key);//簽名 if(signature_new.startsWith(jwt)){//未被篡改 String payload = new String(Base64.decodeBase64(strs[1]), Constant.UTF);//載荷 JSONObject JO = JSONObject.fromObject(payload); if(JO.getString("iss").equals(iss)&&JO.getString("aud").equals(aud)){ Long exp = JO.getLong("exp"); Long iat = System.currentTimeMillis();//簽發時間 if(exp>iat&&(exp-iat)>1*60*1000){//過期時間>1分鐘 judge = 1;//正常,不需更新JWT }else{ judge = 0;//JWT過期或將要過期 } } } } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); System.out.println(e.getMessage()); } return judge; } }先這樣吧,不太會寫文章,希望大家海涵。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88063.html
摘要:注入編碼技巧前端的轉義是必不可少的,為了防止抓包修改參數值,我們重點放在后端。為了契合前后分離的說法。所以請不要認為可以預防,這是一種錯誤的理解目前存儲的方式有以下幾種存取優點不易遭受可設置弊端易遭受。 前端攻擊主要包括XSS(跨站腳本攻擊)、CSRF(跨站請求偽造)、SQL注入。Noodles的技術周刊 中有詳細解釋。 一、XSS&SQL注入 它們的發生是在用戶惡意輸入和抓包修改情...
摘要:注入編碼技巧前端的轉義是必不可少的,為了防止抓包修改參數值,我們重點放在后端。為了契合前后分離的說法。所以請不要認為可以預防,這是一種錯誤的理解目前存儲的方式有以下幾種存取優點不易遭受可設置弊端易遭受。 前端攻擊主要包括XSS(跨站腳本攻擊)、CSRF(跨站請求偽造)、SQL注入。Noodles的技術周刊 中有詳細解釋。 一、XSS&SQL注入 它們的發生是在用戶惡意輸入和抓包修改情...
摘要:注入編碼技巧前端的轉義是必不可少的,為了防止抓包修改參數值,我們重點放在后端。為了契合前后分離的說法。所以請不要認為可以預防,這是一種錯誤的理解目前存儲的方式有以下幾種存取優點不易遭受可設置弊端易遭受。 前端攻擊主要包括XSS(跨站腳本攻擊)、CSRF(跨站請求偽造)、SQL注入。Noodles的技術周刊 中有詳細解釋。 一、XSS&SQL注入 它們的發生是在用戶惡意輸入和抓包修改情...
摘要:攻擊方式端口掃描攻擊洪水攻擊洪水攻擊跳轉攻擊防范手段保證服務器系統的安全確保服務器軟件沒有任何漏洞,防止攻擊者入侵。 前端需要知道的web安全知識 標簽(空格分隔): 未分類 安全 [Doc] Crypto (加密) [Doc] TLS/SSL [Doc] HTTPS [Point] XSS [Point] CSRF [Point] 中間人攻擊 [Point] Sql/Nosql ...
摘要:攻擊方式端口掃描攻擊洪水攻擊洪水攻擊跳轉攻擊防范手段保證服務器系統的安全確保服務器軟件沒有任何漏洞,防止攻擊者入侵。 前端需要知道的web安全知識 標簽(空格分隔): 未分類 安全 [Doc] Crypto (加密) [Doc] TLS/SSL [Doc] HTTPS [Point] XSS [Point] CSRF [Point] 中間人攻擊 [Point] Sql/Nosql ...
閱讀 2078·2021-10-08 10:21
閱讀 2471·2021-09-29 09:34
閱讀 3494·2021-09-22 15:51
閱讀 4926·2021-09-22 15:46
閱讀 2314·2021-08-09 13:42
閱讀 3434·2019-08-30 15:52
閱讀 2723·2019-08-29 17:13
閱讀 1555·2019-08-29 11:30