
Markdown: Fix Do not XSS defence
- Failed to defence XSS attack after markdown rendering on server - XSS attack : https://www.owasp.org/index.php/Cross-site_Scripting_(XSS) - Fix : escape string to html special character and using xss.js on server rendering
@39fab7167f686bfe1ac653304545ee3a83fddc84
--- app/utils/Markdown.java
+++ app/utils/Markdown.java
... | ... | @@ -32,6 +32,7 @@ |
32 | 32 |
import java.io.InputStream; |
33 | 33 |
import java.io.InputStreamReader; |
34 | 34 |
import java.io.Reader; |
35 |
+import java.lang.System; |
|
35 | 36 |
import java.net.URI; |
36 | 37 |
import java.net.URISyntaxException; |
37 | 38 |
|
... | ... | @@ -122,8 +123,7 @@ |
122 | 123 |
private static String sanitize(String source) { |
123 | 124 |
try { |
124 | 125 |
Object filter = engine.eval("new Filter();"); |
125 |
- Object sanitize = ((Invocable) engine).invokeMethod(filter, "sanitize", source); |
|
126 |
- return new JSInvocable((Invocable) engine, sanitize).invoke("xss"); |
|
126 |
+ return (String) ((Invocable) engine).invokeMethod(filter, "defence", source); |
|
127 | 127 |
} catch (Exception ex) { |
128 | 128 |
throw new RuntimeException(ex); |
129 | 129 |
} |
--- app/views/common/markdown.scala.html
+++ app/views/common/markdown.scala.html
... | ... | @@ -23,7 +23,6 @@ |
23 | 23 |
<link rel="stylesheet" type="text/css" href="@routes.Assets.at("javascripts/lib/highlight/styles/default.css")" /> |
24 | 24 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/highlight/highlight.pack.js")"></script> |
25 | 25 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/marked.js")"></script> |
26 |
-<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/xss.js")"></script> |
|
27 | 26 |
<script type="text/javascript"> |
28 | 27 |
$(document).ready(function(){ |
29 | 28 |
var htOptions = {}; |
--- app/views/common/scripts.scala.html
+++ app/views/common/scripts.scala.html
... | ... | @@ -74,6 +74,7 @@ |
74 | 74 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/humanize.js")"></script> |
75 | 75 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/validate.js")"></script> |
76 | 76 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/spin.js")"></script> |
77 |
+<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/xss.js")"></script> |
|
77 | 78 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/common/yobi.Attachments.js")"></script> |
78 | 79 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/common/yobi.Files.js")"></script> |
79 | 80 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/common/yobi.Mention.js")"></script> |
... | ... | @@ -153,8 +154,8 @@ |
153 | 154 |
} |
154 | 155 |
|
155 | 156 |
welTarget.popover({ |
156 |
- "title" : htData.title, |
|
157 |
- "content" : htData.body, |
|
157 |
+ "title" : htData.title.replace('<', '<'), |
|
158 |
+ "content" : $yobi.xssClean(htData.body), |
|
158 | 159 |
"html" : true, |
159 | 160 |
"placement": "right", |
160 | 161 |
"trigger" : "hover" |
--- public/javascripts/common/yobi.Common.js
+++ public/javascripts/common/yobi.Common.js
... | ... | @@ -412,6 +412,12 @@ |
412 | 412 |
return null; |
413 | 413 |
} |
414 | 414 |
|
415 |
+ function xssClean(str) { |
|
416 |
+ var filter = new Filter(); |
|
417 |
+ |
|
418 |
+ return filter.defence(str); |
|
419 |
+ } |
|
420 |
+ |
|
415 | 421 |
/* public Interface */ |
416 | 422 |
return { |
417 | 423 |
"setScriptPath" : setScriptPath, |
... | ... | @@ -430,7 +436,8 @@ |
430 | 436 |
"nl2br" : nl2br, |
431 | 437 |
"tmpl" : processTpl, |
432 | 438 |
"htmlspecialchars": htmlspecialchars, |
433 |
- "isImageFile": isImageFile |
|
439 |
+ "isImageFile": isImageFile, |
|
440 |
+ "xssClean" : xssClean |
|
434 | 441 |
}; |
435 | 442 |
})(); |
436 | 443 |
|
--- public/javascripts/common/yobi.Markdown.js
+++ public/javascripts/common/yobi.Markdown.js
... | ... | @@ -38,7 +38,6 @@ |
38 | 38 |
* @param {Hash Table} htOptions |
39 | 39 |
*/ |
40 | 40 |
function _initVar(htOptions){ |
41 |
- htVar.htFilter = new Filter(); |
|
42 | 41 |
htVar.sMarkdownRendererUrl = htOptions.sMarkdownRendererUrl; |
43 | 42 |
|
44 | 43 |
htVar.htMarkedOption = { |
... | ... | @@ -69,7 +68,7 @@ |
69 | 68 |
* @return {String} |
70 | 69 |
*/ |
71 | 70 |
function _renderMarkdown(sText) { |
72 |
- return htVar.htFilter.sanitize(marked(sText, htVar.htMarkedOption)).xss(); |
|
71 |
+ return $yobi.xssClean(marked(sText, htVar.htMarkedOption)); |
|
73 | 72 |
} |
74 | 73 |
|
75 | 74 |
/** |
... | ... | @@ -125,7 +124,6 @@ |
125 | 124 |
$(elContainer).on("click", 'a[data-mode="preview"]', function(weEvt){ |
126 | 125 |
var welPreview = $(weEvt.delegateTarget).find("div.markdown-preview"); |
127 | 126 |
var sContentBody = welTextarea.val(); |
128 |
- welPreview.html(sContentBody); |
|
129 | 127 |
|
130 | 128 |
_replaceAutoLink(welPreview, sContentBody); |
131 | 129 |
|
--- public/javascripts/common/yobi.ui.Select2.js
+++ public/javascripts/common/yobi.ui.Select2.js
... | ... | @@ -80,7 +80,7 @@ |
80 | 80 |
|| '<div title="[${stateLabel}] ${name}">${name}</div>'; |
81 | 81 |
|
82 | 82 |
var formattedResult = $yobi.tmpl(tplMilestoneItem, { |
83 |
- "name" : itemObject.text.trim(), |
|
83 |
+ "name" : itemObject.text.trim().replace('<', '<'), |
|
84 | 84 |
"state": milestoneState, |
85 | 85 |
"stateLabel": milestoneStateLabel |
86 | 86 |
}); |
--- public/javascripts/lib/xss.js
+++ public/javascripts/lib/xss.js
... | ... | @@ -920,6 +920,10 @@ |
920 | 920 |
return this.str; |
921 | 921 |
} |
922 | 922 |
|
923 |
+ Filter.prototype.defence = function(str) { |
|
924 |
+ return this.sanitize(str).xss(); |
|
925 |
+ } |
|
926 |
+ |
|
923 | 927 |
Filter.prototype.entityDecode = function() { |
924 | 928 |
this.modify(decode(this.str)); |
925 | 929 |
return this.str; |
--- public/javascripts/service/yobi.code.Browser.js
+++ public/javascripts/service/yobi.code.Browser.js
... | ... | @@ -515,7 +515,9 @@ |
515 | 515 |
aCrumbs.push('<a href="' + sLink + '">' + sName + '</a>'); |
516 | 516 |
}); |
517 | 517 |
|
518 |
- htElement.welBreadCrumbs.html(aCrumbs.join("")); |
|
518 |
+ var breadcrumb = $yobi.xssClean(aCrumbs.join("")); |
|
519 |
+ |
|
520 |
+ htElement.welBreadCrumbs.html(breadcrumb); |
|
519 | 521 |
} |
520 | 522 |
|
521 | 523 |
_init(htOptions || {}); |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?