Can anyone recommend a regex that will reject any string with characters that should be escaped for use in an angular form input like...
<input name="name" type="text" ng-pattern="*REGEX HERE*" ng-model="selectedExercise.name" />
And yes I know that this isn't a good way to sanitize user input. Under the hood I am using also using $sanitize before communicating to the backend and doing full sanitizing on the backend too.
If you are looking to prevent XSS type attacks, then the way to do this is to sanitize the input when it is being rendered to the user and not at time of capture.
If your application is rendering using Angular, then it automatically safely encodes all output on binding.
Related
For the first time ever I had two users come into my app with a .education top level domain. Their email address looked like this: user#domain.education. I'm using the cfinput validate attribute on the form they are filling out as follows:
<cfinput type="text" name="email" required="yes" message="Please enter a valid email address." validate="email">
When the users submits the form they are getting my error message. The form has been working successfully for years on all the other email addresses entered. Are there any tricks to make it take this top level domain? TIA
Avoid all of the ColdFusion UI tags. They will only cause pain.
Each version of ColdFusion updates the built-in email validation to handle the new top-level domains (TLD) of the time. There are nearly 1600 active TLDs at the moment.
Javascript validation isn't going to cut it.
Regular expressions won't either.
You will need to validate on the server if you aren't already.
Better you remove that validation rule for a start and send an email to verify the email account exists before activating the user on your app.
I agree with the other answers about limiting your use of cfinput, but as a quick fix you should be able to use the cfinput PATTERN attribute (https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-i/cfinput.html):
<cfinput type="text" name="email" required="yes" message="Please enter a valid email address." validate="regex" pattern="(?:[a-z0-9!##$%&'+/=?^_{|}~-]+(?:\.[a-z0-9!##$%&'*+/=?^_{|}~-]+)|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])")#(?:(?:a-z0-9?.)+a-z0-9?|[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-][a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])+)])">
The PATTERN attribute can be changed to any regular expression. The one provided is RFC 5322 compliant.
EDIT: Changed pattern to Java based RegEx and escaped #'s
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) .
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.
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);
The basics:
I have a contact form that uses
php to validate the
forms. (in addition to client side) This could be done in any server side language though.
The server side only allows
A-z 0-9 for certain fields (it is
acceptable to validate this field to
English only with that extremely limited range)
If the form contains errors, I repopulate the fields so the user doesn't have to retype before submitting again
I am willing to not let other sites post to my form, even if legitimate use could be found there.
I can easily make a form on a different web site that posts a dirty word to a field. Certain dirty words are perfectly legit according to the validation rules, but my employeer obviously wouldn't like that to happen.
I am under the impression that dedicated hackers can affect cookies, php sessions and of course hidden fields are easy to spoof along with referrers and such. How can I block third party sites from posting to my page?
Please feel free to help me Google for this too. My search terms are weak and bringing up methods I know will fail.
What if somebody submits "d03boy eats cats" via a form on their site and gets people to click a link that submits it to my form? (Admit it is possible, and my company cannot accept any risk) Then when a user clicks the link they see inside the "name" field "d03boy eats cats" and gets super offended and contacts PETA about our site's content. We just cannot explain to the user what happened. True, nothing happened, but upsetting a single users isn't acceptable to my employer.
Our current solution is to not report any user input, which in my opinion is a big usability issue.
This sounds like you need a moderation system in place for user generated content, not a technical solution. Obviously you can check the referrer field, content scrub and attempt to filter the profane, but enumerating badness never works. (It can be an acceptable "first pass", but humans are infinitely resourceful in avoiding such filters).
Put the user submitted content into a queue and have moderators review and approve content. To lighten the load, you can set trusted users to "pre approved", but you have said your client can't accept any risk.
Frankly, I find that impossible: even with moderators there is the risk that a moderator will subvert your system. If that is actually true (that they have zero risk tolerance) then I suggest they not accept any user input, don't trust moderators and in fact eliminate the site itself (because an insider could go rogue and put something improper up). Clearly every act has risk; you need to find out how much they can accept, such as a moderator based approval queue.
I'm not sure I entirely understand your question but I'll do my best to give you a basic answer.
Cross Site Scripting (XSS) happens generally when someone else puts in HTML into your forms. Your website allows this to happen because it isn't escaping the HTML properly. If you use PHP you probably want to make use of the htmlentities($str, ENT_QUOTES) function.
htmlentities($str, ENT_QUOTES)
PHP htmlentities
My attempt
...
<?
$form_token = "";
$token = "";
$encoded_token = "";
$salt = "ThiséèÞ....$ÖyiìeéèÞ"; //it is 70 characters long
...
...
$blnGoodToken = false;
...
...
//Check for the encoded token
session_start();
$encoded_token = GetSuper('POST', 'TOKEN');
if (isset($_SESSION['TOKEN'])) {
if (sha1($_SESSION['TOKEN'] + $salt) === $encoded_token) {
$blnGoodToken = true;
//echo "Good Token";
}
else {
//echo "Bad Token";
$blnGoodToken = false;
unset($_SESSION);
session_unset();
session_destroy();
session_start();
}
}
else {
$blnDoit = false;
echo "No Token, possible no session";
}
$token = uniqid(rand(), TRUE);
$_SESSION['TOKEN'] = $token;
$form_token = sha1($token + $salt);
...
...
?>
...
...
<form action="request.php?doit=y" method="post">
<input type="text" name="TOKEN" id="TOKEN" value="<?=$form_token?>" />
<!--
form stuff
-->
<input type="reset" value="Clear" />
<input type="submit" value="Submit" />
</form>
Since I don't use sessions anywhere else on the site, I don't think we are exposed much to session hijacking. The token changes each load, and to get the token to match the session you would have to know
I am using SHA. An easy guess to
make on my php code
I keep it in the session. I suppose
the session is gettable
My salt. I think this is a good
secret. If they know my salt they already
owned my server