XSS via breaking tag parameter using no equal sign - xss

I have found a XSS candidate so the GET request to non-existing page with path like this http://example.com/page/blabla"onclick generates the following HTML: 404 <a href="/page/blabla"onclick>. However, the equal sign urlencodes and I get the following HTML when trying to exploit it: <a href="/page/blabla"onclick%3falert()">. Can I exploit this bug in case of equal sign filtering?

Try with Internet Explorer 9, as this does not automatically encode query string characters.
e.g.
http://example.com/page/blabla" onclick="alert(123)
which should be rendered as
<a href="/page/blabla" onclick="alert(123)">
You might need to disable IE's XSS filter.

Related

Input validation with pattern Angular 2

I'm currently writing a simple form in ionic 2 (Angular 2). I was wondering how I'd add a simple regular expression pattern to the validation:
I basically have this:
<form>
<ion-input stacked-label>
<ion-label>{{label.msisdn}}</ion-label>
<input type="text"
[(ngModel)]="msisdn"
ngControl="msisdnForm"
required
maxlength="10"
minlength="10"
pattern="06([0-9]{8})"
#msisdnForm="ngForm"
>
</ion-input>
<button [disabled]="!msisdnForm.valid" block (click)="requestActivationCode()">
{{label.requestActivationCode}}
</button>
</form>
The maxlength, minlength & required are being picked up (the button is disabled if conditions not met). Now I want to limit the input to numeric and prefix it with 06 (Dutch phone number with minimum amount of numbers).
The pattern is however not picked up in the validation. Can I do it this way, or do I need a code approach?
Add the pattern to a variable
var pattern=/06([0-9]{8})/;
and bind the attribute to it
<input type="text"
[(ngModel)]="msisdn"
ngControl="msisdnForm"
required
maxlength="10"
minlength="10"
[pattern]="pattern"
#msisdnForm="ngForm"
>
Seems this PR https://github.com/angular/angular/pull/6623/files needs to land first.
There is still an open issue https://github.com/angular/angular/issues/7595
This prevents pattern being bound to. The pattern needs to be statically added to the DOM (without binding) to work.
I put more details (Angular 2.0.8 - 3 March 2016):
https://github.com/angular/angular/commit/38cb526
Example from repo:
<input [ngControl]="fullName" pattern="[a-zA-Z ]*">
I tested it, and it worked :) - here is my code:
<form (ngSubmit)="onSubmit(room)" #roomForm='ngForm' >
...
<input
id='room-capacity'
type="text"
class="form-control"
[(ngModel)]='room.capacity'
ngControl="capacity"
required
pattern="[0-9]+"
#capacity='ngForm'>
UPDATE September 2017
I just wanna to say that currently when I have more experience, I usally use following 'cheap' approach to data validation:
Validation is ONLY on server side (not in angular at all!) and if something is wrong then server (Restful API) return some error code e.g HTTP 400 and following json object in response body (which in angular I put to err variable ):
this.err = {
"capacity" : "too_small"
"filed_name" : "error_name",
"field2_name" : "other_error_name",
...
}
(if server return validation error in different format then you can usually easily map it to above structure)
In html template i use separate tag (div/span/small etc.)
<input [(ngModel)]='room.capacity' ...>
<small *ngIf="err.capacity" ...>{{ translate(err.capacity) }}</small>
As you see, when there is some error in 'capacity' then tag with error translation (to user language) will be visible. This approach have following advantages:
it is very simple
in angular we not double validation code which is (and must be) in server (in case of regexp validation this can either prevent or complicate ReDoS attacks)
we have full control on way the error will be shown to user (here as egzample in <small> tag)
because in server response we return error_name (instead of direct error message), we can easily change error message (or translate it) by modify only frontend-angular code (or files with translations). So in that case we not need to touch backend/server code.
Of course sometimes (if this is needed - eg. retypePassword field which is never send to server) I make exceptions of above approach and make some validation in angular (but use similar "this.err" mechanism to show errors (so I not use pattern attribute directly in input tag but rather I make regexp validation in some component method after user raise proper event like input-change or save) .

HTML5 number input field step attribute broken in Internet Explorer 10 and Internet Explorer 11

It appears some of my website's users are experiencing issues when attempting to insert values into input fields of type number with the step attribute set.
I am using Django 1.6 to render the forms to HTML.
The number fields map to an underlying DecimalField model field with max_digits=25 and decimal_places=5
This results in the following example html being rendered for the number field:
<input type="number" value="" step="0.00001" name="quantity" id="id_quantity">
The step attribute I know is not yet supported in FireFox but is in Opera, Chrome, Safari and IE10+
Everything works fine in all browsers except IE10 and IE11. In the above example the maximum range that can be entered is -227 to 227 in IE10 and IE11. If I try to enter a lower or greater value (respectively) than this I get a 'You must enter a valid value' error and cannot submit the form.
According to http://www.w3schools.com/tags/att_input_step.asp
The step attribute specifies the legal number intervals for an element.
Example: if step="3", legal numbers could be -3, 0, 3, 6, etc.
So in my user's example they were attempting to enter 20000 as the value which failed in IE10 and IE11. If my calculations are correct 20000 falls correctly into an interval of 0.00001
A solution for me could be to remove the step attribute from all my forms that use a number field, either via the django forms or using javascript, but I think this would be a very messy solution and one that goes against the grain of HTML5.
Has anyone else encountered a similar problem, have I done something wrong or is this a bug in IE10 and IE11?
Any thoughts, comments or answers welcome. In the meantime I will be forced into providing my usual solution to affected users by suggesting they use a browser that works.
You're not alone, IE is pretty buggy on this.
I'm not sure about IE10, I can only test IE11 right now, and it kinda treats number fields as date fields, which it actually shouldn't support at all, still when passing for example 20000 it says "Insert a valid date" (originally "Geben Sie ein gültiges Datum ein").
And indeed, when entering something like 01.01.2000 or 01-01-2000 it passes validation, though even 20000.01.123456789 passes, just like 90000 or 0.foobar, so I guess the validation is just totally messed up.
So for the time being you'll probably have to use some kind of polyfill in case you want to please IE users.
IE10's HTML5 form validation is really buggy in this case, so you might want to consider disabling HTML5 form validation for this form.
You can do this by adding a novalidate attribute to the form tag. For example, you might want to do something like this:
<form method='POST' action='.' novalidate='novalidate'>
<input type="number" value="" step="0.00001" name="quantity" id="id_quantity">
</form>
Setting novalidate will tell the browser to not try to be useful, which should work out your issue. However, please be aware that this will disable the HTML5 validation for the whole form for all browsers. If you need to keep this for some browsers while removing it from IE, you'll have to add the novalidate attribute via Javascript on page load after checking the browser user agent. This user agent can be spoofed however so it's not an ideal solution.
I ran into the same issue and adding step="any" at the field level fixed the issue for me.
It looks like IE10+ need a MIN and MAX value in order to work properly. If you defines these values it will work just fine with the 10000 value:
<input type="number" value="" step="0.00001" min="-100000" max="100000" name="quantity" id="id_quantity" />
Seems that step attributes for numer input just implemented as for Range Input which needs min, max and step values.
If really you are not able to define a min and max value, you must use Javascript to do that.

Could anyone tell me why / how this XSS vector works in the browser?

I have suffered a number of XSS attacks against my site. The following HTML fragment is the XSS vector that has been injected by the attacker:
<a href="mailto:">
<a href=\"http://www.google.com onmouseover=alert(/hacked/); \" target=\"_blank\">
<img src="http://www.google.com onmouseover=alert(/hacked/);" alt="" /> </a></a>
It looks like script shouldn't execute, but using IE9's development tool, I was able to see that the browser translates the HTML to the following:
<a href="mailto:"/>
<a onmouseover="alert(/hacked/);" href="\"http://www.google.com" target="\"_blank\"" \?="">
</a/>
After some testing, it turns out that the \" makes the "onmouseover" attribute "live", but i don't know why. Does anyone know why this vector succeeds?
So to summarize the comments:
Sticking a character in front of the quote, turns the quote into a part of the attribute value instead of marking the beginning and end of the value.
This works just as well:
href=a"http://www.google.com onmouseover=alert(/hacked/); \"
HTML allows quoteless attributes, so it becomes two attributes with the given values.

Cross Site Scripting with Hidden Inputs

My company gave me the task of resolving all security issues with a particular application. The security tream reported a cross site scripting error. The error lies in the following input field:
<input type="hidden" name="eventId" value="${param.eventId}"/>
The report from security wasn't very detailed, but the say they can make a POST request to the page that has the above tag including the following malicious code:
eventId=%22%3e%3csCrIpT%3ealert(83676)%3c%2fsCrIpT%3e
And that when the page reloads, it will have the following:
<input type="hidden" name="eventId" value=""><sCrIpt>alert(83676)</sCrIpt></value>
I am trying to "be the hacker" and show the vulnerability. But I can't figure out how they manage to get that script in there. I am guessing they include it as a URL parameter in the GET request for the form, but when I try to do it myself I get a 403 error. Does anyone know how the vulnerability can be shown?
I know there is a number of XSS questions on the site, but none seem to hit this topic.
So, I am not sure why, but my original hunch was correct. The script can be put on as a URL parameter. For some reason though, this was not working with our staging site. Only with running the application locally. I am not sure why, but this works (only locally):
http://localhost:8080/myUrl/MyAction.do?eventId=%22%3e%3csCrIpT%3ealert(83676)%3c%2fsCrIpT%3e
Doing that, you see an alert box pop up. I am planning to fix it using JSTL functions.
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="hidden" name="eventId" value="${fn:escapeXml(param.eventId)}"/>
Install [TamperData][1] add-on in firefox browser which let you edit the data before submitting. Doesn't matter if it's in POST or GET.
By using this hidden fields can be edited.
What you want to do to fix the problem, is to HTMLAttributeEncode the value before putting it inside the value-attribute. See OWASP ESAPI or MS AntiXSS for methods for doing HTML attribute encoding.
Seeing how the attack string is URL encoding, I think you guess about including it as a GET parameter seems reasonable.
I used the OWASP ESAPI API as the legacy jsp's didn't have JSTL available. This is what I used:
<input type="hidden" name="dataValue" value="<%=ESAPI.encoder().encodeForHTMLAttribute(dataValue)%>">
You can also use the API to filter request.Parameter() which I also needed, as in:
String userURL = request.getParameter( "userURL" )
boolean isValidURL = ESAPI.validator().isValidInput("URLContext", userURL, "URL", 255, false);
if (isValidURL) {
link
}
and:
String name = (String) request.getParameter("name");
name = ESAPI.validator().getValidInput("name ", name , "SafeString", 35, true);

Django: How do I prepend

I'm exploring Django and got this particular problem.
How do I prepend <span class="label">Note:</span> inside {{article.content_html|safe}}?
The content of {{article.content_html|safe}} are paragraph blocks, and I just wanna add <span class="label">Note:</span> in the very first paragraph.
Thanks!
Sounds like you want to write a custom tag that uses BeautifulSoup to parse the HTML and inject the fragment.
There's no easy way. You can easily prepend to all articles.
<span class="label">Note:</span>
{{article.content_html|safe}}
If that doesn't help you consider changing the structure of article.content_html so you can manipulate with blocks from django templates, so it should look something like this
{{article.content_header}}
<span class="label">Note:</span>
{{article.content_html}}
If that solution is not feasible to you and you absolutely need to parse and modify the content of article.content_html, write your own custom filter that does that. You can find documentation about writing custom filters here http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters.
An alternate approach could be to do this with javascript. In jQuery, it would look something like:
var first_p_text = $("p:first").text()
$("p:first").html("<span class="label">Note:</span>" + first_p_text)
Note though that if there are other elements inside your first p, $("p:first").text() will grab the text from those as well - see http://api.jquery.com/text/
Of course, this relies on decent javascript support in the client.
jQuery is the simplest and easiest to implement. You only need one line with the prepend call (documentation):
$('p:first').prepend('<span class="label">Note:</span>');
Explanation: 'p:first' is a jQuery selector similar to the ':first-child' CSS selector. It will select the first paragraph and the prepend call will then insert the span into that selected paragraph.
Note: If there is a paragraph on the page before your content, you may have to surround it with a div:
<div id='ilovesmybbq'>{{article.content_html|safe}}</div>
Then the jQuery call would be:
$('#ilovesmybbq p:first').prepend('<span class="label">Note:</span>');