JAVA覆写Request过滤XSS跨站脚本攻击

注:本文非本人原著。

demo的地址:链接:http://pan.baidu.com/s/1miEmHMo 密码:k5ca

如何过滤Xss跨站脚本攻击,我想,Xss跨站脚本攻击令人为之头疼。为什么呢。

尤其是有富文本编辑器的产品。xss可能出现在http的head,不说别的,新浪多次出现。

xss可以出现在post数据的正文。图片的url。

于是各种Xss横行,如今Xss跨站脚本漏洞的流行程度甚至超过了当年的sql。

那么对于JAVA语言,如何防御呢。

笔者分享一个思路:所有的web项目,所有的参数都是request获得。

不管是json合适xml又或者post表单数据。甚至图片、文件等等都是如此。

那么,如果对request做个手脚。是不是就可以过滤xss了呢。

正是如此。

如下分享代码。网络上也有类似的过滤器,但不如笔者这份强悍。

  1
  2 package com.blog.web.base.wrapper;
  3
  4 import java.io.ByteArrayInputStream;
  5 import java.io.ByteArrayOutputStream;
  6 import java.io.IOException;
  7 import java.io.InputStream;
  8 import java.util.ArrayList;
  9 import java.util.Enumeration;
 10 import java.util.HashMap;
 11 import java.util.List;
 12 import java.util.Map;
 13 import java.util.regex.Pattern;
 14
 15 import javax.servlet.ServletInputStream;
 16 import javax.servlet.http.HttpServletRequest;
 17 import javax.servlet.http.HttpServletRequestWrapper;
 18
 19 /**
 20  * 覆写Request方法,过滤XSS恶意脚本
 21  *
 22  * @author WebSOS
 23  * @time 2015-06-09
 24  */
 25 public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
 26
 27 	HttpServletRequest orgRequest = null;
 28
 29 	public XssHttpServletRequestWrapper(HttpServletRequest request) {
 30 		super(request);
 31 		orgRequest = request;
 32 	}
 33
 34 	/**
 35 	 * 覆盖getParameter方法,将参数名和参数值都做xss过滤。
 36 	 */
 37 	@Override
 38 	public String getParameter(String name) {
 39 		String value = super.getParameter(name);
 40 		if (value != null) {
 41 			value = xssEncode(value);
 42 		}
 43 		return value;
 44 	}
 45
 46 	/**
 47 	 * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 避免部分head操作引发的xss
 48 	 */
 49 	@Override
 50 	public String getHeader(String name) {
 51
 52 		String value = super.getHeader(name);
 53 		if (value != null) {
 54 			value = xssEncode(value);
 55 		}
 56 		return value;
 57 	}
 58
 59 	/**
 60 	 * 覆盖getHeaderNames方法,避免穷举head参数名引发的xss
 61 	 */
 62 	@Override
 63 	public Enumeration<String> getHeaderNames() {
 64
 65 		Enumeration<String> headNames = super.getHeaderNames();
 66 		String value = null;
 67 		List<String> values = new ArrayList<String>();
 68 		while (headNames.hasMoreElements()) {
 69 			try {
 70 				value = (String) headNames.nextElement();
 71 				if (value == null) {
 72 					continue;
 73 				}
 74 				value = xssEncode(value);
 75 				values.add(value);
 76 			} catch (Exception e) {
 77 				e.printStackTrace();
 78 			}
 79 		}
 80 		if (values.isEmpty()) {
 81 			return null;
 82 		}
 83 		headNames = new XssEnumerator(0, values.size(), values);
 84 		return headNames;
 85 	}
 86
 87 	/**
 88 	 * 覆盖getParameterNames方法,避免穷举参数名引发的xss
 89 	 */
 90 	@Override
 91 	public Enumeration<String> getParameterNames() {
 92 		Enumeration<String> paraNames = super.getParameterNames();
 93 		if (paraNames == null) {
 94 			return null;
 95 		}
 96 		String value = null;
 97 		List<String> values = new ArrayList<String>();
 98 		while (paraNames.hasMoreElements()) {
 99 			try {
100 				value = (String) paraNames.nextElement();
101 				if (value == null) {
102 					continue;
103 				}
104 				value = xssEncode(value);
105 				values.add(value);
106 			} catch (Exception e) {
107 				e.printStackTrace();
108 			}
109 		}
110 		if (values.isEmpty()) {
111 			return null;
112 		}
113 		paraNames = new XssEnumerator(0, values.size(), values);
114 		return paraNames;
115 	}
116
117 	/**
118 	 * 覆盖getParameterMap方法,避免穷举参数名或值引发的xss
119 	 */
120 	@Override
121 	public Map<String, String[]> getParameterMap() {
122 		Map<String, String[]> map = super.getParameterMap();
123 		Map<String, String[]> paraMap = new HashMap<String, String[]>();
124 		if (map == null) {
125 			return null;
126 		}
127 		String[] values = null;
128 		for (String key : map.keySet()) {
129 			try {
130 				values = map.get(key);
131 				if (values != null) {
132 					for (int i = 0; i < values.length; i++) {
133 						try {
134 							values[i] = xssEncode(values[i]);
135 						} catch (Exception e) {
136 							e.printStackTrace();
137 						}
138 					}
139 				}
140 				paraMap.put(xssEncode(key), values);
141 			} catch (Exception e) {
142 				e.printStackTrace();
143 			}
144 		}
145 		return paraMap;
146 	}
147
148 	/**
149 	 * 覆盖getInputStream方法,避免上传文件出现的xss或脚本代码
150 	 */
151 	@Override
152 	public ServletInputStream getInputStream() throws IOException {
153 		XSSServletInputStream xssServletInputStream = new XSSServletInputStream();
154 		ServletInputStream inputStream = orgRequest.getInputStream();
155
156 		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
157 		try {
158 			int ch;
159 			while ((ch = inputStream.read()) != -1) {
160 				byteStream.write(ch);
161 			}
162 		} finally {
163 			inputStream.close();
164 		}
165 		xssServletInputStream.stream = new ByteArrayInputStream(xssEncode(
166 				new String(byteStream.toByteArray(), "iso-8859-1")).getBytes(
167 				"iso-8859-1"));
168 		return xssServletInputStream;
169 	}
170
171 	/**
172 	 * 将容易引起xss漏洞的字符清理掉
173 	 *
174 	 * @param s
175 	 * @return
176 	 */
177 	private static String xssEncode(String value) {
178 		if (value != null) {
179 			/*
180 			 * value = value.replace("<", "&lt;"); value = value.replace(">",
181 			 * "&gt;");
182 			 */
183 			// 如需开启富文本请撤销以下注释
184
185 			Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>",
186 					Pattern.CASE_INSENSITIVE);
187 			value = scriptPattern.matcher(value).replaceAll("");
188
189 			scriptPattern = Pattern.compile("</script>",
190 					Pattern.CASE_INSENSITIVE);
191 			value = scriptPattern.matcher(value).replaceAll("");
192
193 			scriptPattern = Pattern.compile("<img.*?on.*?=.*?>",
194 					Pattern.CASE_INSENSITIVE);
195 			value = scriptPattern.matcher(value).replaceAll("");
196
197 			scriptPattern = Pattern.compile("<script(.*?)>",
198 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
199 							| Pattern.DOTALL);
200 			value = scriptPattern.matcher(value).replaceAll("");
201
202 			scriptPattern = Pattern.compile("eval\\((.*?)\\)",
203 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
204 							| Pattern.DOTALL);
205 			value = scriptPattern.matcher(value).replaceAll("");
206
207 			scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)",
208 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
209 							| Pattern.DOTALL);
210 			value = scriptPattern.matcher(value).replaceAll("");
211
212 			scriptPattern = Pattern.compile("expression\\((.*?)\\)",
213 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
214 							| Pattern.DOTALL);
215 			value = scriptPattern.matcher(value).replaceAll("");
216
217 			scriptPattern = Pattern.compile("javascript:",
218 					Pattern.CASE_INSENSITIVE);
219 			value = scriptPattern.matcher(value).replaceAll("");
220
221 			scriptPattern = Pattern.compile("vbscript:",
222 					Pattern.CASE_INSENSITIVE);
223 			value = scriptPattern.matcher(value).replaceAll("");
224
225 			scriptPattern = Pattern.compile("onload(.*?)=",
226 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
227 							| Pattern.DOTALL);
228 			value = scriptPattern.matcher(value).replaceAll("");
229
230 			scriptPattern = Pattern.compile("<%.*?java.*?%>", Pattern.CASE_INSENSITIVE
231 					| Pattern.MULTILINE | Pattern.DOTALL);
232 			value = scriptPattern.matcher(value).replaceAll("");
233
234 			scriptPattern = Pattern.compile("<jsp:.*?>.*?</jsp:.*?>",
235 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
236 							| Pattern.DOTALL);
237 			value = scriptPattern.matcher(value).replaceAll("");
238
239 			scriptPattern = Pattern.compile("<meta.*?>",
240 					Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
241 							| Pattern.DOTALL);
242 			value = scriptPattern.matcher(value).replaceAll("");
243
244 		}
245 		return value;
246 	}
247
248 	/**
249 	 * 获取最原始的request
250 	 *
251 	 * @return
252 	 */
253 	public HttpServletRequest getOrgRequest() {
254
255 		return orgRequest;
256 	}
257
258 	/**
259 	 * 获取最原始的request的静态方法
260 	 *
261 	 * @return
262 	 */
263 	public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
264 		if (req instanceof XssHttpServletRequestWrapper) {
265 			return ((XssHttpServletRequestWrapper) req).getOrgRequest();
266 		}
267
268 		return req;
269 	}
270
271 	private class XSSServletInputStream extends ServletInputStream {
272 		private InputStream stream;
273
274 		@Override
275 		public int read() throws IOException {
276 			return stream.read();
277 		}
278 	}
279
280 	private class XssEnumerator implements Enumeration<String> {
281 		int count; // 计数器
282 		int length; // 存储的数组的长度
283 		List<String> dataArray; // 存储数据数组的引用
284
285 		XssEnumerator(int count, int length, List<String> dataArray) {
286 			this.count = count;
287 			this.length = length;
288 			this.dataArray = dataArray;
289
290 		}
291
292 		public boolean hasMoreElements() {
293 			return (count < length);
294 		}
295
296 		public String nextElement() {
297 			return dataArray.get(count++);
298 		}
299 	}
300
301 	public static void main(String[] args) {
302 		Enumeration<String> paraNames = (Enumeration<String>) new ArrayList();
303 	}
304 }
时间: 2024-08-16 06:01:09

JAVA覆写Request过滤XSS跨站脚本攻击的相关文章

Fortify漏洞之Cross-Site Scripting(XSS 跨站脚本攻击)

书接上文,继续对Fortify漏洞进行总结,本篇主要针对XSS跨站脚步攻击漏洞进行总结如下: 1.Cross-Site Scripting(XSS 跨站脚本攻击) 1.1.产生原因: 1. 数据通过一个不可信赖的数据源进入 Web 应用程序.对于 Reflected XSS(反射型),不可信赖的源通常为 Web 请求,只影响攻击到当前操作用户:而对于 Persisted(也称为 Stored 持久型)XSS,该源通常为数据库或其他后端数据存储,可能影响多操作用户. 2. 未检验包含在动态内容中的

PHP漏洞全解(四)-xss跨站脚本攻击

本文主要介绍针对PHP网站的xss跨站脚本攻击.跨站脚本攻击是通过在网页中加入恶意代码,当访问者浏览网页时恶意代码会被执行或者通过给管理员发信息 的方式诱使管理员浏览,从而获得管理员权限,控制整个网站.攻击者利用跨站请求伪造能够轻松地强迫用户的浏览器发出非故意的HTTP请求,如诈骗性的电汇 请求.修改口令和下载非法的内容等请求. XSS(Cross Site Scripting),意为跨网站脚本攻击,为了和样式表css(Cascading Style Sheet)区别,缩写为XSS 跨站脚本主要

XSS跨站脚本攻击实验

XSS攻击的原理.方法.常用技巧, 相关防范措施 跨站脚本攻击(Cross Site Scripting,XSS) 漏洞在Web应用中很常见.攻击者可以通过XSS注入恶意代码(一般指为js程序)至受害者的浏览器,进而窃取受害者认证信息. XSS注入有很多实现方式,可将XSS攻击大致分为存储型XSS.反射型XSS和DOM型XSS. 1)存储型XSS 存储型XSS攻击流程如下: (1) 黑客在目标服务器(正常服务器)上构造XSS恶意脚本,并将其保存在数据库中: (2) 用户登录目标服务器,查看了存在

XSS跨站脚本攻击

[XSS跨站脚本攻击] 1.在Get请求的值中插入代码. $name = $_GET['name']; echo "Welcome $name<br>"; 2.输入框中输入代码. 参考: 1.http://www.cnblogs.com/bangerlee/archive/2013/04/06/3002142.html

初窥XSS跨站脚本攻击

XSS跨站脚本攻击的分类 一. 反射型XSS跨站脚本攻击 二. 存储型XSS跨站脚本攻击 三. 基于DOM的XSS跨站脚本攻击 1.反射性XSS

python全栈系列之---xss跨站脚本攻击和csrf(xsrf)攻击

xss跨站脚本攻击:恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的. 例如:某些论坛允许用户自由发言,而不对用户的输入数据进行检测,直接显示在页面中. 若是用户输入了某些css样式代码,html表格代码,显示在页面后会改变页面的布局. 若是输入某些js代码,用于获取其他用户的文件,或者修改本地文件,也可以发送用户cookie等信息到自己的计算机中模拟用户登录 一般可以通过函数处理htmlspecial

Java 覆写初探

Java 覆写 继承性的主要特征是子类可以根据父类已有的功能进行功能扩展,但是在子类定义属性或方法的时候有可能定义属性和方法和父类同名,在此类情况下就称为:“覆写”. 方法的覆写:[改良原本功能不足的方法] 子类定义的方法与父类方法名称相同.参数的类型及个数.返回值相同的方法. class A { public void fun() { System.out.println("A.fun()方法") ; } } class B extends A { public void fun()

ASP.NET脚本过滤-防止跨站脚本攻击(收集别人的)

ASP.Net 1.1后引入了对提交表单自动检查是否存在XSS(跨站脚本攻击)的能力.当用户试图用<xxxx>之类的输入影响页面返回结果的时候,ASP.Net的引擎会引发一个 HttpRequestValidationExceptioin.默认情况下会返回如下文字的页面: Server Error in '/YourApplicationPath' Application A potentially dangerous Request.Form value was detected from

XSS跨站脚本攻击防御和Cookie,及SSO单点登录原理

XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性.其原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的.如,盗取用户Cookie.破坏页面结构.重定向到其它网站等. XSS攻击 XSS攻击类似于SQL注入攻击,攻击之前,我们先找到一个存在XSS漏洞的网站,XSS漏洞分为两种,一种是DOM Based X