什么是xss攻擊?
請點擊這里
怎么樣避免xss攻擊?
使用jsp tag來輸出,比如<c:out/><s:property/>,這些tag默認都對html代碼轉義了
但是又引入了一個新的難題,怎么使用富文本編輯器?
富文本編輯器最終得到的內容是html代碼,并且要原樣輸出.但是html代碼是可以直接或者間接編輯的,這樣的話就可以插入任何代碼,可以用<script>標簽,可以用<a href="javascript:xxx">,可以用css里面的expression,<img onload="xxx">等等.
解決方法有兩個
1.在服務器端過濾這些script,很難全部過濾,不知道有沒有現成的lib可以用
2.干脆不使用,像大部分論壇那樣搞幾個定義好的tag,比如[a][/a]插入超鏈接,這樣不夠靈活也做不到所見即所得,但是安全第一
不知道大家有什么好的解決方法?
請點擊這里
怎么樣避免xss攻擊?
使用jsp tag來輸出,比如<c:out/><s:property/>,這些tag默認都對html代碼轉義了
但是又引入了一個新的難題,怎么使用富文本編輯器?
富文本編輯器最終得到的內容是html代碼,并且要原樣輸出.但是html代碼是可以直接或者間接編輯的,這樣的話就可以插入任何代碼,可以用<script>標簽,可以用<a href="javascript:xxx">,可以用css里面的expression,<img onload="xxx">等等.
解決方法有兩個
1.在服務器端過濾這些script,很難全部過濾,不知道有沒有現成的lib可以用
2.干脆不使用,像大部分論壇那樣搞幾個定義好的tag,比如[a][/a]插入超鏈接,這樣不夠靈活也做不到所見即所得,但是安全第一
不知道大家有什么好的解決方法?
* 濾除帖子中的危險 HTML 代碼, 主要是腳本代碼, 滾動字幕代碼以及腳本事件處理代碼
*
* @param content
* 需要濾除的字符串
* @return 過濾的結果
*/
public static String replaceHtmlCode(String content) {
if (isEmpty(content)) {
return "";
}
// 需要濾除的腳本事件關鍵字
String[] eventKeywords = { "onmouseover", "onmouseout", "onmousedown",
"onmouseup", "onmousemove", "onclick", "ondblclick",
"onkeypress", "onkeydown", "onkeyup", "ondragstart",
"onerrorupdate", "onhelp", "onreadystatechange", "onrowenter",
"onrowexit", "onselectstart", "onload", "onunload",
"onbeforeunload", "onblur", "onerror", "onfocus", "onresize",
"onscroll", "oncontextmenu" };
content = replace(content, "<script", "<script", false);
content = replace(content, "</script", "</script", false);
content = replace(content, "<marquee", "<marquee", false);
content = replace(content, "</marquee", "</marquee", false);
// FIXME 加這個過濾換行到 BR 的功能會把原始 HTML 代碼搞亂 2006-07-30
// content = replace(content, "\r\n", "<BR>");
// 濾除腳本事件代碼
for (int i = 0; i < eventKeywords.length; i++) {
content = replace(content, eventKeywords[i],
"_" + eventKeywords[i], false); // 添加一個"_", 使事件代碼無效
}
return content;
}
* 將字符串 source 中的 oldStr 替換為 newStr, 并以大小寫敏感方式進行查找
*
* @param source
* 需要替換的源字符串
* @param oldStr
* 需要被替換的老字符串
* @param newStr
* 替換為的新字符串
*/
public static String replace(String source, String oldStr, String newStr) {
return replace(source, oldStr, newStr, true);
}
/**
* 將字符串 source 中的 oldStr 替換為 newStr, matchCase 為是否設置大小寫敏感查找
*
* @param source
* 需要替換的源字符串
* @param oldStr
* 需要被替換的老字符串
* @param newStr
* 替換為的新字符串
* @param matchCase
* 是否需要按照大小寫敏感方式查找
*/
public static String replace(String source, String oldStr, String newStr,
boolean matchCase) {
if (source == null) {
return null;
}
// 首先檢查舊字符串是否存在, 不存在就不進行替換
if (source.toLowerCase().indexOf(oldStr.toLowerCase()) == -1) {
return source;
}
int findStartPos = 0;
int a = 0;
while (a > -1) {
int b = 0;
String str1, str2, str3, str4, strA, strB;
str1 = source;
str2 = str1.toLowerCase();
str3 = oldStr;
str4 = str3.toLowerCase();
if (matchCase) {
strA = str1;
strB = str3;
} else {
strA = str2;
strB = str4;
}
a = strA.indexOf(strB, findStartPos);
if (a > -1) {
b = oldStr.length();
findStartPos = a + b;
StringBuffer bbuf = new StringBuffer(source);
source = bbuf.replace(a, a + b, newStr) + "";
// 新的查找開始點位于替換后的字符串的結尾
findStartPos = findStartPos + newStr.length() - b;
}
}
return source;
}
css的expression沒有過濾,ie下面可以運行
<img lowsrc="javascript:alert('XSS')"/>這個在ie下面可以自動運行,還有鏈接里面使用javascript:xxx等其他協議比如firefoxurl:xxx
import java.util.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.Perl5Substitution;
import org.apache.oro.text.regex.Util;
public class AntiXSS {
static final Pattern SCRIPT_TAG_PATTERN = Pattern.compile(
"<script[^>]*>.*</script[^>]*>", Pattern.CASE_INSENSITIVE);
static final PatternCompiler pc = new Perl5Compiler();
static final PatternMatcher matcher = new Perl5Matcher();
// http://www.bitscn.com/hack/young/200708/108278.html
public static String antiXSS(String content) {
String old = content;
String ret = _antiXSS(content);
while (!ret.equals(old)) {
old = ret;
ret = _antiXSS(ret);
}
return ret;
}
private static String _antiXSS(String content) {
try {
return stripAllowScriptAccess(stripProtocol(stripCssExpression(stripAsciiAndHex(stripEvent(stripScriptTag(content))))));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static String stripScriptTag(String content) {
Matcher m = SCRIPT_TAG_PATTERN.matcher(content);
content = m.replaceAll("");
return content;
}
private static String stripEvent(String content) throws Exception {
String[] events = { "onmouseover", "onmouseout", "onmousedown",
"onmouseup", "onmousemove", "onclick", "ondblclick",
"onkeypress", "onkeydown", "onkeyup", "ondragstart",
"onerrorupdate", "onhelp", "onreadystatechange", "onrowenter",
"onrowexit", "onselectstart", "onload", "onunload",
"onbeforeunload", "onblur", "onerror", "onfocus", "onresize",
"onscroll", "oncontextmenu" };
for (String event : events) {
org.apache.oro.text.regex.Pattern p = pc.compile("(<[^>]*)("
+ event + ")([^>]*>)", Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util.substitute(matcher, p, new Perl5Substitution(
"$1" + event.substring(2) + "$3"), content,
Util.SUBSTITUTE_ALL);
}
return content;
}
private static String stripAsciiAndHex(String content) throws Exception {
// filter &# \00xx
org.apache.oro.text.regex.Pattern p = pc.compile(
"(<[^>]*)(&#|\\\\00)([^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util
.substitute(matcher, p, new Perl5Substitution("$1$3"),
content, Util.SUBSTITUTE_ALL);
return content;
}
private static String stripCssExpression(String content) throws Exception {
org.apache.oro.text.regex.Pattern p = pc.compile(
"(<[^>]*style=.*)/\\*.*\\*/([^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util
.substitute(matcher, p, new Perl5Substitution("$1$2"),
content, Util.SUBSTITUTE_ALL);
p = pc
.compile(
"(<[^>]*style=[^>]+)(expression|javascript|vbscript|-moz-binding)([^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util
.substitute(matcher, p, new Perl5Substitution("$1$3"),
content, Util.SUBSTITUTE_ALL);
p = pc.compile("(<style[^>]*>.*)/\\*.*\\*/(.*</style[^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util
.substitute(matcher, p, new Perl5Substitution("$1$2"),
content, Util.SUBSTITUTE_ALL);
p = pc
.compile(
"(<style[^>]*>[^>]+)(expression|javascript|vbscript|-moz-binding)(.*</style[^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util
.substitute(matcher, p, new Perl5Substitution("$1$3"),
content, Util.SUBSTITUTE_ALL);
return content;
}
private static String stripProtocol(String content) throws Exception {
String[] protocols = { "javascript", "vbscript", "livescript",
"ms-its", "mhtml", "data", "firefoxurl", "mocha" };
for (String protocol : protocols) {
org.apache.oro.text.regex.Pattern p = pc.compile("(<[^>]*)"
+ protocol + ":([^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util.substitute(matcher, p, new Perl5Substitution(
"$1/$2"), content, Util.SUBSTITUTE_ALL);
}
return content;
}
private static String stripAllowScriptAccess(String content)
throws Exception {
org.apache.oro.text.regex.Pattern p = pc.compile(
"(<[^>]*)AllowScriptAccess([^>]*>)",
Perl5Compiler.CASE_INSENSITIVE_MASK);
if (null != p)
content = Util.substitute(matcher, p, new Perl5Substitution(
"$1Allow_Script_Access$2"), content, Util.SUBSTITUTE_ALL);
return content;
}
}