Open manangurjar opened 3 years ago
Your policy is simple and this looks like a legit bypass. More from us soon and thank you for the report.
-- Jim Manico @Manicode
On Dec 14, 2020, at 7:33 AM, Manan Gurjar notifications@github.com wrote:
I am using below policy -
PolicyFactory policy = new HtmlPolicyBuilder() .allowElements("a", "pre") .allowUrlProtocols("https", "http") .allowAttributes("href").onElements("a") .requireRelNofollowOnLinks().toFactory(); And I am trying to filter out below html string -
String text = "
<img src=\"/\" onerror=\"confirm(document.domain)\";>"; But if I try to sanitize the text and filter the string out it leaves the img tag as is -
String text = "
<img src=\"/\" onerror=\"confirm(document.domain)\";>"; PolicyFactory msLinkablePolicyFactory = new HtmlPolicyBuilder() .allowElements("a", "pre") .allowUrlProtocols("https", "http") .allowAttributes("href").onElements("a") .requireRelNofollowOnLinks().toFactory();
String sanitizedText = msLinkablePolicyFactory.sanitize(StringEscapeUtils.unescapeHtml4(text)); System.out.println(StringEscapeUtils.unescapeHtml4(sanitizedText)); Output - <img src="/" onerror="confirm(document.domain)";>
May be the policy might need some correction, but could you please take a look and confirm
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.
What are the StringEscapeUtils.unescapeHtml4
calls for?
The following test without those calls passes for me. What am I missing?
@Test
public static final void testIssue219() {
String text = "<plaintext><img src=\"/\" onerror=\"confirm(document.domain)\";>";
PolicyFactory policy = new HtmlPolicyBuilder()
.allowElements("a", "pre")
.allowUrlProtocols("https", "http")
.allowAttributes("href").onElements("a")
.requireRelNofollowOnLinks()
.toFactory();
String sanitizedText = policy.sanitize(text);
assertEquals(
"<img src="/" onerror="confirm(document.domain)";>",
sanitizedText
);
}
The policy does not
leave the img tag as is
because there is no img
tag in "<plaintext><img src=\"/\" onerror=\"confirm(document.domain)\";>"
, only text characters.
The HTML spec explains:
Once a start tag with the tag name "plaintext" has been seen, that will be the last token ever seen other than character tokens (and the end-of-file token), because there is no way to switch out of the PLAINTEXT state.
The sanitizer correctly escapes those text characters which this line then unescapes before printing:
System.out.println(StringEscapeUtils.unescapeHtml4(sanitizedText));
ok understood. I was using the policy to sanitze the blog comments and to allow only specific tags. But then it was figured that using plaintext tag, user was able to bypass the policy and was able to execute any JS, which I thought is a possible attack.
So, I think I will have to deal with plaintext tag separately.
What plaintext bypass? Just don't unescape the html. If you unescape, there's a much simpler bypass: <script>...</script>
.
Thank you Mike and I’m sorry for the false alarm.
-- Jim Manico @Manicode
On Dec 14, 2020, at 6:23 PM, Mike Samuel notifications@github.com wrote:
What plaintext bypass? Just don't unescape the html. If you unescape, there's a much simpler bypass: <script>...</script>.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.
I am using below policy -
And I am trying to filter out below html string -
But if I try to sanitize the text and filter the string out it leaves the img tag as is -
Output -
<img src="/" onerror="confirm(document.domain)";>
May be the policy might need some correction, but could you please take a look and confirm