recently I found this tutorial about XSS and web application security -> https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#XSS_Locator
At the start there are some strings to inject in order to test that a site is vulnerable to xss or not. These strings are:
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";
alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--
></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
and
'';!--"<XSS>=&{()}
I know the basic concepts of XSS, but here I can't understand why there's that repetition of 'alert(String.fromCharCode(88,83,83))' in the first string and why those //'; //"; //--> comments are needed for (do they mean something special when used in such a way whilesearching for xss bugs?).
And in the second string, what is the purpose of the &{()} sequence?
Could anyone exlain me with concrete examples how this two strings should work in order to retrieve an xss bug inside a web app? Cause on the site I linked no explanation is given...
This looks like it's trying several different injections, so I'll try and break them down one at a time:
The First Injection
';alert(String.fromCharCode(88,83,83))//
This injection attempts to terminate a JavaScript string literal (using '), then terminate the statement (with ;) and makes a call to alert(String.fromCharCode(88,83,83)) which will cause a popup box containing "XSS". The following // is an attempt to "comment out" the rest of the statement, so that a syntax error will not occur and the script will execute.
The Second Injection
";alert(String.fromCharCode(88,83,83))//
Like the first injection, but it uses " in an attempt to terminate a JavaScript string literal.
The Third Injection
--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
This attempts to do the following things:
Terminate an HTML (or XML) comment (with -->)
Terminate an existing <SCRIPT> tag using </SCRIPT>
This is done to prevent the injected script causing a syntax error, which would prevent the injected script from executing.
Terminate an HTML attribute and tag, using ">
Terminate an HTML attribute and tag, using '>
Inject JavaScript using <SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
The Fourth Injection
'';!--"<XSS>=&{()}
This is a common string used to test what, if any, filters and/or encoding are being used on user input. Typically, the source of the page after this injection will contain either <XSS or <XSS. If the second is found, the application is most likely not filtering user input (as it allowed the addition of an arbitrary tag) and is likely vulnerable to XSS.
To answer your more direct questions:
why there's that repetition of 'alert(String.fromCharCode(88,83,83))'
This is a common "Proof of Concept" function, that will cause a popup box to appear containing "XSS". If this occurs, the injected JavaScript was executed.
why there's that repetition of 'alert(String.fromCharCode(88,83,83))' in the first string and why those //'; //"; //-->
These are used to prevent syntax errors, which can cause the injected JavaScript to fail to execute.
Related
I'd like to show a text with HTML execution (formated) in the browser so it will be easy to read BUT without any JavaScript execution. It's a large text and it's very hard to read between HTML tags. So, execute HTML but not JavaScript.
What I did: I loaded this text in an <iframe> so I can have full control and I tried to show the text like this:
<script>
throw new Error('This is just to abort javascript');
</script>
<?php echo $text ?>
<script>
throw new Error('This is just to abort javascript');
</script>
The console does show an error but even so, if I have
$text = '<script>alert(1)</script>'; this script gets executed anyway.
Another XSS example that I'd like to avoid.
$text = 'this is a fake url';
Basically, abort any JavaScript execution from the page.
Thanks in advance!
Unfortunately this isn't really possible. The reason that that doesn't work is because the error stops that script from executing, but doesn't stop all scripts on the page from executing.
If you're trusting HTML input from the user, you're simply going to have XSS vulnerabilities, unless you try to parse their input and remove anything that could cause a javascript event to fire. Don't try this, you're in for a lot of heartache if you do.
Ultimately, this is why things like MarkDown and Textile exist.
I guess the answer to "what you should do" depends on what you're expecting the user to actually send you, but ultimately you should be running any user input through htmlentities and/or strip_tags
You can specify a Content Security Policy to prevent any inline JavaScript from executing.
See here for browser compatibility.
It is also recommended to run any user input through an HTML sanitizer too, as this will help protect browsers without CSP support. Using BBcode or something like MarkDown is also recommended, rather than allowing users to enter raw HTML as this is much simpler (and complexity is the enemy of security).
I came across some interesting behaviour of the javascript code on my XPages
//'rdoGeschlecht1' is present on page Basis (no problems there),
//but not on page 'Stufe1'.
var level = "Stufe1";
if(level == "Basis")
{
alert("1");
// var rdoGeschlecht1 = '#{javascript:getClientId("rdoGeschlecht1")}';
}
else if(level == "Stufe1")
{
alert("2");
}
The code above always ends in an error when executed on a page where the element is not present - "Ungültiger Komponentenname rdoGeschlecht1 kann in getClientId nicht aufgelöst werden." - it seems to me that Notes tries to resolve the object ID even if the line is not used in the actual execution and even when uncommented.
I have found a quick&dirty workaround of course, but I am surely not the first one to stumble upon this behaviour and I would really be interested in how experienced XPages programmers would be going about this?
The problem is you're commenting out the client-side JavaScript which is going to be run on the browser. But the server-side JavaScript code within #{javascript: (which needs to run on the server) is not commented out.
Perhaps it will help to explain what happens you put SSJS or EL in a string property or, in this case, a script block. Because the key is that the CSJS is not parsed on the server, it's just passed as a string to the browser.
The parser reads the string and looks for #{javascript: which tells it that the following code up to the closing } needs to be passed to the SSJS parser and the result added to the string that gets written to the browser. Any lines within that SSJS block that begin "//" will get omitted. But the parser will not take into account anything outside the #{javascript: because that is just text being passed to the browser. It is the browser that interprets the whole thing as client-side JavaScript.
Hopefully that clarified why it's working the way it is.
If you want to comment out a line in a script block that includes SSJS and you want to prevent the SSJS from running, you'll need to comment out the CSJS (so the browser doesn't run it) and the SSJS (so the server doesn't run it).
I use Aptana Studio to code JavaScript.
When I write string with </, there will be warning saying
'<' + '/' + letter not allowed here
But it does not trigger error in browsers.
what does </ mean in JavaScript?
For inline scripts (e.g, using <script>), some HTML parsers may interpret anything that looks like </this (especially </script>) as an HTML tag, rather than part of your source code. Your IDE is trying to keep you from typing this by mistake.
This means that, if you're using an inline script, you can't have a </tag> as a constant string in JavaScript:
var endTag = "</tag>"; // don't do this!
You'll need to break it up somehow to keep it from being interpreted as a tag:
var endTag = "<" + "/tag>";
Note that this only applies to inline scripts. Standalone scripts (e.g, a .js file) can have anything they want in them.
It doesn't mean anything in a string, outside of a string it would be a syntax error.
EDIT: Before someone nitpicks there are some exceptions, eg var i = 1 </* comment */ 2; is legal and there may be some other cases (like performing less-than operation on a regex) but generally speaking it signifies nothing by itself.
It sounds like it's your IDE is denying it. Aptana Studio may be assuming some sort of injection attack, and thus throws an error.
You would probably get a more direct answer by asking them directly though; a general program help site like StackOverflow is less likely to know the reasoning for specific cases such as this.
I see the following HTML code used a lot to load jQuery from a content delivery network, but fall back to a local copy if the CDN is unavailable (e.g. in the Modernizr docs):
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.1.min.js">\x3C/script>')</script>
My question is, why is the last < character in the document.write() statement replaced with the escape sequence \x3C? < is a safe character in JavaScript and is even used earlier in the same string, so why escape it there? Is it just to prevent bad browser implementations from thinking the </script> inside the string is the real script end tag? If so are there really any browsers out there that would fail on this?
As a follow-on question, I've also seen a variant using unescape() (as given in this answer) in the wild a couple of times too. Is there a reason why that version always seems to substitute all the < and > characters?
When the browser sees </script>, it considers this to be the end of the script block (since the HTML parser has no idea about JavaScript, it can't distinguish between something that just appears in a string, and something that's actually meant to end the script element). So </script> appearing literally in JavaScript that's inside an HTML page will (in the best case) cause errors, and (in the worst case) be a huge security hole.
That's why you somehow have to prevent this sequence of characters to appear. Other common workarounds for this issue are "<"+"/script>" and "<\/script>" (they all come down to the same thing).
While some consider this to be a "bug", it actually has to happen this way, since, as per the specification, the HTML part of the user agent is completely separate from the scripting engine. You can put all kinds of things into <script> tags, not just JavaScript. The W3C mentions VBScript and TCL as examples. Another example is the jQuery template plugin, which uses those tags as well.
But even within JavaScript, where you could suggest that such content in strings could be recognized and thus not be treated as ending tags, the next ambiguity comes up when you consider comments:
<script type="text/javascript">foo(42); // call the function </script>
– what should the browser do in this case?
And finally, what about browsers that don't even know JavaScript? They would just ignore the part between <script> and </script>, but if you gave different semantics to the character sequence </script> based on the browsers knowledge of JavaScript, you'd suddenly have two different results in the HTML parsing stage.
Lastly, regarding your question about substituting all angle brackets: I'd say at least in 99% of the cases, that's for obfuscation, i.e. to hide (from anti-virus software, censoring proxies (like in your example (nested parens are awesome)), etc.) the fact that your JavaScript is doing some HTML-y stuff. I can't think of good technical reasons to hide anything but </script>, at least not for reasonably modern browsers (and by that, I mean pretty much anything newer than Mosaic).
Some parsers handle the < version as the closing tag and interpret the code as
<script>
window.jQuery || document.write('<script src="js/libs/jquery-1.6.1.min.js">
</script>
\x3C is hexadecimal for <. Those are interchangable within the script.
JSON responses can be exploited by overriding Array constructors or if hostile values are not JavaScript string-escaped.
Let's assume both of those vectors are addressed in the normal way. Google famously traps JSON response direct sourcing by prefixing all JSON with something like:
throw 1; < don't be evil' >
And then the rest of the JSON follows. So Dr. Evil cannot, using the sort of exploit discussed here. Get your cookie (assuming you're logged in) by putting the following on his site:
<script src="http://yourbank.com/accountStatus.json">
As for string escaping rules, well if we're using double quotes, we need to prefix each with a backslash and each backslash with another backslash etc.
But my question is, what if you're doing all of this?
Burp Suite (the automated security tool) detects embedded XSS attempts that are returned unHTML-escaped in a JSON response and it reports it as an XSS vulnerability. I have a report that my application contains vulnerabilities of this kind but I am not convinced. I've tried it and I can't make an exploit work.
So I don't think this is correct.
There is one specific case, that of IE MIME-type sniffing that I think could result in an exploit. After all, IE 7 still had the "feature" that script tags embedded in image comments were executed regardless of the Content-Type header. Let's also leave such clearly stupid behaviour aside at first.
Surely the JSON would be parsed by either the native JavaScript parser (Window.JSON in Firefox) or by an eval() as per the old default jQuery behaviour. In neither case would the following expression result in the alert being executed:
{"myJSON": "legit", "someParam": "12345<script>alert(1)</script>"}
Am I right or am I wrong?
This potential xss vulnerability can be avoided by using the correct Content-Type. Based on RFC-4627 all JSON responses should use the application/json type. The following code is not vulnerable to xss, go ahead test it:
<?php
header('Content-type: application/json');
header("x-content-type-options: nosniff");
print $_GET['json'];
?>
The nosniff header is used to disable content-sniffing on old versions of Internet Explorer. Another variant is as follows:
<?php
header("Content-Type: application/json");
header("x-content-type-options: nosniff");
print('{"someKey":"<body onload=alert(\'alert(/ThisIsNotXSS/)\')>"}');
?>
when the above code is viewed by a browser the user was prompted to download a JSON file, the JavaScript was not executed on modern versions of Chrome, FireFox and Internet Explorer. This would be an RFC violation.
If you use JavaScript to eval() the JSON above or write the response to the page then it becomes DOM Based XSS. DOM based XSS is patched on the client by sanitizing the JSON before acting on this data.
Burpsuite (the automated security tool) detects embedded XSS attempts
that are returned unHTML-escaped in a JSON response and it reports it
as an XSS vulnerability.
Maybe it tries to prevent the vulnerability described in the rule 3.1 of OWASP XSS Cheat Sheet.
They give the following example of vulnerable code:
<script>
var initData = <%= data.to_json %>;
</script>
Even if double quotes, slashes and newlines are properly escaped, you can break out of JSON if it's embedded in HTML:
<script>
var initData = {"foo":"</script><script>alert('XSS')</script>"};
</script>
jsFiddle.
to_json() function can prevent this issue by prefixing each slash with a backslash. If JSON is used in HTML attribute, the whole JSON string must be HTML-escaped. If it's used in a href="javascript:" attribute, it must be URL-escaped.
If we limit our scope to IE (all versions), assume you are running a site based on PHP or ASP.NET, and ignore the IE anti-XSS filter, then you are wrong: your users are vulnerable. Setting 'Content-type: application/json' will not help, either.
This is due to (as you mention) IE's content detection behavior, which goes beyond sniffing for HTML tags in the response body to include URI analysis.
This blog posting explains this very well:
https://www.adico.me/post/json-based-xss-exploitation
For the record, although I accepted an answer, for the exact literal question I am asking, I was right and there was no vulnerability due to the presence of non-HTML-escaped yet correctly JSON-escaped HTML inside JSON values. There could be a bug there if that value was inserted into the DOM without client-side escaping but Burpsuite has little chance of knowing if that would happen just by looking at network traffic.
In the general case of determining what is a security vulnerability in these circumstances, it's instructive to recognise that while it may not feel like good design, the response content of a JSON value could legitimately be known to certainly contain no user input and be intended to be already rendered HTML to be safely inserted in the DOM unescaped. Escaping it would be a (non-security) bug as I mentioned in another comment.