I wanted to show my students example of DOM-base XSS attack. I thought that inserting malicious script by innerHTML will by enough. But to my surprise when I insert script it seems to be not invoked.
Example is here https://jsfiddle.net/vo9baffu/6/ example
My question: is it possible to do DOM-based XSS attack in a way presented in my example. If not then way and what should I change?
BTW.
If you know some good examples of DOM-based XSS please post in comment.
Use the good ol' image:
<img src="/bad.png" onerror="alert(-2)" />
Full code:
function showName() {
tt = "script";
badCode = "John<img onerror='alert(-2)' src='/bad.png'>";
console.log(badCode);
document.getElementById("name").innerHTML = badCode;
}
Where /bad.png should trigger onerror.
And your JSFiddle
Briefly: You can't make a DOM-based XSS attack in the way presented in your example.
You have to include jQuery in your HTML and use the html() method instead. This will will accomplish exactly what you ask for, because the html() method will evaluate the code embedded in the script tag.
With pure JavaScript, you can't make an XSS attack, because the script you insert will not execute in most cases. That happens, because the inline script only executes when the original page is parsed.
You can show your students an XSS attack by using an img tag and an error event as shown below:
<img src="whatever.png" onerror="alert('XSS')" />
as shown in this fiddle .
Related
I have to use some HTML tags in innerHTML. But it's giving some security issues. I can't use innerText etc because I have to show HTML content instead of plain text.
$(this).parent()[0].innerHTML = newInnerHTML;
What are the workarounds for this. or is there a way to resolve the vulnerabilities. I tried sanitizing the HTML but it didn't work. Please provide your suggestions.
Thank you.
I know you said you tried sanitizing it already, but maybe you were doing it wrong. If you need to put user input as an innerHTML string without a risk of xss, you can use a library like https://www.npmjs.com/package/xss-clean to sanitize only the user input. If the html content is hard coded, there isn't a risk of xss. The risk of using innerHTML only applies when a user can submit an HTML string to a server that could be visible to other users.
I got following 2 questions as:
1) How to protect from this kind of XSS Attacks?
https://www.example.com/index.php?javascript:alert('XSS')
If suppose for some reason, the query parameter is embedded in an image load event then it would be like this
<img src=x onload="javascript:alert('XSS')">
//And browser treats as
<img src=x onload="javascript:alert('XSS')">
I am already using PHP's htmlspecialchars() and Filtar_var() with URL Sanitization, but this kind of encoded XSS will easily get pass through these functions
How can we defend such Encoded XSS or neutralize any such attack?
2) Is it necessary for an XSS attack to get embedded in HTML Page, Javascript or CSS etc in order to get triggered? or there can be a way where XSS does not need to be embedded?
htmlspecialchars is a perfectly good defence against XSS when you are inserting user input into an HTML document.
It stops any HTML syntax in the user input from breaking out of where you intend for it to go and being treated as JavaScript.
Your problem has nothing to do with the fact the attack is encoded. The problem is that are are putting user input somewhere that JavaScript is expected (and onload attribute) so it is already being treated as JavaScript.
json_encode is the usual solution here (and then htmlspecialchars because the JavaScript is inside an HTML attribute).
However, that only works when you are taking user input and putting it into a script to be used as data. Here it seems that you are taking user input and just treating the whole thing as a JavaScript function.
If you do that then you are going to be vulnerable to XSS. You can mitigate it to some degree by implementing defenses against CSRF, but you almost certainly shouldn't be doing this in the first place.
Say i have a form with which user inputs some information and is submited to server using php and in PHP code i have say
$data = $_POST['data'];
// or
$data = strip_tags(#$_POST['data']);
I want to know of the strip_tags() is enough to stop javascript injection through html forms. If not how else can this be prevented. I have read here.
And also say i input javascript:void(document.bgColor="blue") in the browser address bar, this changes the whole site background color to blue. How can javascript injection through the address bar be prevented.
Thanks.
i suggest to use htmlspecialchars when ever you want to output something to browser
echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
checkout this
For question 2, I'm not sure if that's even possible to prevent. It's not something I've ever considered before. It sounds like you're trying to prevent executing any javascript that wasn't included by you on the page, which would also mean blocking the devtools in the browser from executing anything in the console. This could potentially be hostile to your users, e.g. if they wanted to use a bookmarklet from Instapaper.
For 1, ultimately your goal is to avoid including this injected javascript from the form when you generate a new page. When you output the data from the form, you can wrap it in htmlspecialchars.
It's depend which output you are trying to get.
In some cases , you'll want to leave the HTML tags including script tags ,but you want that those elements will not run when you output them, in that case you should use htmlspecialchars($_POST['data']), (It's suggested to define also utf8 as the third parameter).
But if you want to remove entierly the tags than strip_tags will prevent XSS
One function cannot fully protect you from script injection. Consider the following program:
<?php
if(isset($_POST['height']))
$height=htmlspecialchars($_POST['height'], ENT_QUOTES, 'UTF-8');
else $height=200;
if(isset($_POST['width']))
$height=htmlspecialchars($_POST['width'], ENT_QUOTES, 'UTF-8');
else $width=300;
echo("
<!DOCTYPE html>
<html>
<body>
<iframe src='whatever' height=$height width=$width>
</iframe>
</body>
</html>
");
The input is sanitized, but javascript will still be executed through a simple injection vector like:
300 onload=alert(String.fromCharCode(88)+String.fromCharCode(83)+String.fromCharCode(83))
You still need to quote your attributes or you are vulnerable like this example.
Another semi-common injection vector exists when user input is echoed into javascript comments, and you can inject new lines or close the comment. I blame it on the 'this shit doesn't work as it should, but let's keep it around in a comment'-style of development.
Note: The XSS protection of many browsers will not run my simple example. If you want to try it use one without protection, or find a vector that defeats it (not sure if there is one for e.g. Chrome).
I'm working on a single page webapp. I'm doing the rendering by directly creating DOM nodes. In particular, all user-supplied data is added to the page by creating text nodes with document.createTextNode("user data").
Does this approach avoid any possibility of HTML injection, cross site scripting (XSS), and all the other evil things users could do?
It creates a plain text node, so yes, as far as it goes.
It is possible to create an XSS problem by using an unsafe method to get the data from whatever channel it is being input into to createTextNode though.
e.g. The following would be unsafe:
document.createTextNode('<?php echo $_GET['xss']; ?>');
… but the danger is from the PHP echo, not the JavaScript createTextNode.
Yes, it's XSS safe, as would be using someElement.innerText = "...".
(The sibling answer adds confusion by including the XSS-vulnerable PHP snippet.)
I am interested in building a text editor in a CMS backend that allows users to write Javascript into a textarea and test it while editing.
The closest I can think of is something like.
document.head.appendChild(document.createElement('script')).src='http://site.com/file.js';
But instead of
.src='http://site.com/file.js';
I would need to fill the script element with the textarea value. Does anyone have any idea as how to handle something like this?
I have written a simple one of these myself (doesn't work in IE) here: http://phrogz.net/tmp/simplejs.html
Use the eval() function.
eval(document.getElementById('wmd-input').value);
And if you're going to let users enter JavaScript into your CMS, be sure you're up to speed on cross-site scripting (XSS).
I think you should make an ajax call to load the page. I'd recommend JQuery, which makes it very easy, and there are plenty of examples on their site.
It would look something like this:
$.get('http://site.com/file.j', function(data) {
$('#txta').text(data);
});
Where 'txta' is the id of the textarea.
If you want to execute the script in the browser, you can use the javascript eval() function - but I would exercise extreme caution with this approach since it can lead to all sorts of security flaws, including cross-site scripting attacks.