Best way to prevent parameter tampering and send values with Javascript? - javascript

I am posting a form to the controller and making it asynchronous. I am storing values in input form hidden. When a button is clicked, a javascript function is called. It both fetches the value from an input field, as well as a value from input form hidden. It then sends a json string to the controller to handle this request.
Controller:
[HttpPost, Authorize]
public ActionResult DoSomeStuff (string leagueName, string doSomething) {
var service = new Service(_db);
var league = service.GetLeague(leagueName);
if (league != null) {
// validate doSomething
league.Action = doSomething;
_db.SaveChanges();
}
return new EmptyResult();
}
Javascript:
$(document).on("click", "#submitForm", function () {
var json = {
"leagueName": $("input[name=leagueName]").val(),
"doSomething": $("input[name=doSomething]").val()
};
$.post("/Home/DoSomeStuff/", json, function () {
// async display something
});
}
Html:
<input type="text" name="doSomething">
<button type="submit" id="submitForm"</button>
<input type="hidden" name="leagueName" value="#item.League.LeagueName" />
What is the best way to let javascript fetch a stored value (more secure way then input type hidden)?
How can I prevent some user from altering the value from the input type
hidden field?

How can I prevent some user from altering the value from the input
type hidden field?
You cannot!
What is the best way to let javascript fetch a stored value (more
secure way then input type hidden)?
The general rule is, do not trust data coming from client. You should always validate it on server before doing anything.
If you are worried about a user update the league name field value in the form to some other users league name and post it, What you should be doing is, explicitly checking whether the user has proper permission to do something on the posted league in your server code.
[HttpPost, Authorize]
public ActionResult DoSomeStuff (string leagueName, string doSomething) {
var service = new Service(_db);
var league = service.GetLeague(leagueName);
// Now check whether the current user has access/permission
// to perform some operation on this league.
// Ex : if(!service.IsUserAuthorizedToDoSomething(league))
// {
// return View("NotAuthorized");
// }
//to do: Return something
}

If the value needs to come from the client (and be part of the HTTP request) then there's absolutely nothing you could do to prevent the client from modifying its contents. If the client is not supposed to modify the contents of some fields then those fields have nothing to do in your markup and be part of the postback HTTP requests (be it as hidden fields or whatever markup element comes to your mind). They should safely reside on your server (database?) and be retrieved using some identifier coming from the client. Obviously whether the client can access the information related to this identifier is subject to something called authorization. Basically you should first know who your client is (authentication) and then verify in your data model if this client has access to the corresponding records. It's as simple as that.
[HttpPost]
[Authorize]
public ActionResult DoSomeStuff (string id, string doSomething)
{
var service = new Service(_db);
var league = service.GetLeagueById(id);
if (!HasAccessToLeague(User.Identity.Name, league))
{
// you are not suppose to modify the contents of this league
// throw him a 404 or something
}
else
{
if (league != null)
{
// validate doSomething
league.Action = doSomething;
_db.SaveChanges();
}
}
return new EmptyResult();
}
obviously the implementation of the HasAccessToLeague(string username, string leagueId) method will greatly depend on your data model and how your authorization logic.
Also you used XSS in your question title but here your problem is not about XSS or javascript but rather designing authorization layer in your web application.

of course its possible to do this! After all, your server app manages to track who the currently logged on user is using insecure client storage.
When a user logs on, the server will generate a secret message and store it in an encrypted token that's passed to the client and bak in a cookie (which is just another piece of unsecured client data storage). When you send requests to the server, it gets the cookie, decrypts it, and checks the data inside to tell who the user is.
You can do the same - for the hidden fields, encrypt them, put them in a hidden input (or a cookie if you prefer) and send them back to the server. However, you can only use them in your client javascript if you send them plain text as well, which means you need to still perform some checking on the server, but that checking can be as simple as comparing the encrypted values with the hidden form values, if any do not match, reject the request.
things to bear in mind though, encrypion is slow. It can be quicker to fetch the values from a DB instead, though you might use a cache for these. YMMV.
An alternative option is to generate a javascript file with the values in and ensure that the client browser cannot edit them using security features such as content-security-policy. The disadvantage is an inability to use these values in html (as obviously the user can edit them there) so you'll have to pass data back to the server via js calls.

Related

Set HTML Input invalid on server

I'm using HTML5 form validation to validate my form. So if I validate it using Javascript, I can do something like that:
if (isInvalid())
{
myControl.setCustomValidity("my error message");
}
And it's working fine. My doubt is about server-side validation. The form is posted back to the same page, and if an error is detected, the input control should be considered invalid from the start, something like that:
<input type="text" name="id" invalid error-message="This id is already used" />
I don't want to use AJAX to make this validation, because I would have to 'hijack' and cancel the form submit, make the validation using AJAX, and then submit the form in javascript.
It is always better to iterate over context
You are not using AJAX and are sending form over http page load
One thing to keep in mind is either ways AJAX or otherwise form will only follow course on clicking of submit button. Hence the name form submission.
With in the form we have a field which may be valid or invalid.
If the field is invalid then run error which seems to work or if field is valid then simply glide through to next step in form submission.
On server side detect if field is invalid or not .... and do what ever is dependant on the context.
Issue on server side is it has nothing to do, nor controls and nor wants to control UI, html display in your browser.
All it handles is request i.e. GET, POST, PUT, HEAD etc and responds accordingly.
Browser sends page request to web server - it may pack form data or it may not pack form data dependant on the context.
Web server fetches the page and forwards if there is any packed form data with the request to the page and there is always lot more data getting passed around other then just form e.g. cookies, User agents, IPs etc
once the page is loaded into process stream you little bit of programming tells it to find form data if there is any and processes that for data to make a response out put.
So we are having a conflict of interest between point no 4 and point no 5.
Thing is your form is ultimately just a payload for HTTP (which is just a payload for tcp in turn and so on).
HTTP inherently does not and should not identify data types in payload, it is just an array for HTTP. KEYWORD FOCUS array.
You can select how to represent data in the array
It may look something like this
GET /?say=Hi&to=Mom HTTP/2.0
Host: foo.com
read more here how forms are sent to webserver
So bottom line forms are only going in some form of array format, we know arrays always have key value pair e.g. ['say' => 'hi'] there is key and there is value.
usually java-script does not offer out of the box key value pairing for arrays it has values and uses their index as key e.g. ['hi', 'there'] behind the scene is equivalent to in some hackyway to [0 => 'hi', 1 => 'there'] just keep that in mind java script does not offer multidimensional arrays out of the box.
so how does java script handle arrays or how we define it we it goes like this
var say = ['hi'];
now you may see whats happening around say=Hi in form data. There is massive array of Get with in which are key value pairs separated by &
for php sake it looks something like this
$_GET = [
'say' => 'hi',
'to' => 'mom']
we detect in page through $_GET['say'] which returns the value against it.
This is universal and will remain this for a long time to come.
What you are trying to do it attempting to detect on server from form data wither any of the key value pair has valid value or not.
Well reason why url sending is so fast it happens in less then 2 seconds gone from one part of the planet to another. While response as in downloading the web-page is so slow because inherently do not send html code through url request as show in example above. they send militaristic information understood universally.
This in turn means since there is html going to server then sever cannot detect any attributes they only have key value pair. So out attribute detection is out of window. Through error and trials we developers get the hang of this explicit revelation.
Anyways so how do we deal with this;
Some make cookies some make extra hidden fields
Then trigger on submit event on form to do the magic they need to do
some even run server side validation by running validation function on server e.g.
if($_GET['say' != 'hi'){do this thing something} else { do that thing}
Trust me there are always some kind of function or loop run on server side to make validation. WE have not found default validation way as of yet.
So we use form on submit event
document.getElementById('myform').onsubmit = function() {
var cheking = document.getElementById('myfield').value;
if(cheking != 'what ever you want'){
alert('fail!');
return false; // prevent the form to submit
}
}
This is the general idea dont submit form which is half crooked but incase it does need be sent then slight change of code
document.getElementById('myform').onsubmit = function() {
var cheking = document.getElementById('myfield');
if(cheking.value != 'what ever you want'){
cheking.value = 'invalid';
alert('fail!');
}
}
form will submit and on server side for that key we will have value as invalid so php side would be
if($_GET['myfield' = 'invalid'){stop processing or whatever else } else { keep on processing}
Because this had been going on for so and so and so long it became a standard of its own through input pattern attribute which takes care of all of the above on client side and is pretty much what you have done.
input pattren
bunch of regex to help you along
<!DOCTYPE html>
<html>
<body>
<h1>The input pattern attribute</h1>
<form action="">
<label for="country_code">Country code:</label>
<input type="text" id="country_code" name="country_code" pattern="[A-Za-z]{3}" required oninvalid="runvalidity(this)" oninput="this.setCustomValidity('')"
title="Three letter country code"><br><br>
<input type="submit">
</form>
<script>
function runvalidity(ele){
ele.setCustomValidity('Enter country name please');
ele.value = "invalid";
}
</script>
</body>
</html>
we created a pattern which on on submit event will manage and wont send form the in JavaScript we have run bunch of events on input field where we call custom function which makes UI as you wanted and alters the input value. if for any reason form does go through with invalid value we can then run server side validation as shown above using the same logic.
nevertheless browser will only send count_name=invalid or country_name=usa etc
Hope gist helps you understand whats behind the scene. my suggestion will be develop a UI context then fit in code logic (key word logic) matching both on client and server side.
I personally use pasterns and filet through same conditions on server side. some time client side logic can be tightened up so much there is lesser need to compare on server side. Again it depends how one fits in their code logic.

JS/JQuery: Redirect on the basis of XML response

Is there a way to redirect the user to a certain URL on the basis of what comes out of an XMLHttpRequest()? Here's what I am trying to achieve:
User hits submit, form gets submitted, XMLHttpRequest() fired
Response received from the server, stored in var hr
If hr = abc, show contents of hr
If hr = xyz, redirect user to http://www.something.com
What I am looking for is if there's any predesigned method in either JS or JQ to handle such redirects. I understand redirects can be specified in the <meta> tags in the <header> section of the page but if I did that, how will I be able to add conditions to it? I would have posted a copy of the script I have attempted but can't because right now, I have no idea where to even begin!
In case someone is curious about the scenario, this is a Web-based dictionary/conjugation service. So, on the verb conjugation page, if the user enters a valid verb, the response (i.e. the conjugation tables) is displayed. However, if the user enters a word that's valid but not a verb so it can't be conjugated, I want the user to be automatically redirected to the dictionary page where the entered word's dictionary entry will be displayed. Not sure if I have explained it well enough but please feel free to ask should you have any questions.
Try testing with switch(request.responseText) and call window.location.assign("http://your-url.com"); in the preferred case "xyz"! Alternatively window.open("http://anotherxxxwebsite.com") opens the link in a new browser window.
There's no "predesigned" method, but you can write that logic yourself. Depending on your current API you could either check if the returned value is an URI (or some other designated value instead) an redirect accordingly. Assuming a deferred object returned from jQuery.ajax:
defer.done(function(data, textStatus, jqXHR) {
// assuming a string, but this could really be anthing, e.g.
// an object containing an appropriate attribute, etc.
if (data.indexOf('http') === 0) {
window.open(data);
} else {
// render your stuff
}
});

What is the proper way to validate user input?

I totally understand that JavaScript should be used to enhance a users experience, however I use it sometimes to validate the input for example to check if the password textbox is more than 5 characters or to check if the username entered in the username textbox already exists. As you can imagine if the password is less than 5 characters or the username already exists, the register button is disabled.
However, this can altered from the users browser, so is their any better way of validating the user's input?
I understand I can validate it all through the server just by checking text boxes when the register button is clicked but surely their must be better ways as such that a user cannot alter?
BTW: I'm using Visual Studio C# ASP.NET
Also, am I correct to think that regex expressions can also be altered at the clients side
Validation should be done on both the client and the server. If you choose not to use a framework that has built in validation you can definitely write your own regular expressions to do this.
Client side validation can be bypassed and its main purpose is user experience. See here. Server side validation is tougher to bypass.
Never ever depend on client side validation. There must always be double checks, one on client side and one on server side. Java script, J query and regular expression can do that for you. As a side note, USE PARAMETERISE QUERIES.
It's true that the nature of client-side code is that it is manipulatable. You can get close to preventing alteration of code through the console by using Private and Privileged members of a function.
Within the constructor, privileged methods are assigned this and only call private variables. Take this example from crockford.com,
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
this.service = function () {
return dec() ? that.member : null;
};
}
The service function is priviledged and is able to call the private dec() method, which has access to the private secret variable. service is a privileged method because if directly called, it will return null.service rather than the desired value of the variable it has access to, secret.
You can use this to your advantage when evaluating passwords because server-side code can require specifically structured data that, without proper javascript, will simply not be accepted.

Obfuscating URL parameters to prevent users from changing them?

I am developing a fat client page based on Javascript that will allow users to carry out tasks outwith another web client application (Oracle Siebel).
The way the web page will be called from the browser will be by a simple window.open() call.
When this happens a URL will be passed which contains some parameters at the end which will change the functionality of the fat client page depending on what value they have.
e.g
userlevel=1 //normal user
userlevel=2 //advanced user
In an example full URL would be like so
www.mypage.com/index.htm?id=25215125%userlevel=2%context=full
However a user who wants to change their access only need to figure out that if they change their user level then they can change their access rights on this fat client page.
Yes, I know this is risky and before you ask why I am not using a server supported thin client with controls that cannot be altered by the user. I simply have to do it this way!
This system will be in a "trusted" environment and this users will have at best average IT skills.
So all I need to do is figure out a way to obfuscate/ scramble the URL parameters (if possible) and then decipher them at the fat client.
e.g.
www.mypage.com/index.htm?1sdf908ga90-821098650f8asdg098g0a98
I tested it out on the browser and no complaints so far so I guess I just need to develop a piece of logic to decipher it.
e.g. I could use MD5?
Any examples or ideas?
Thanks
Try Base64 encoding it. https://stackoverflow.com/a/4699739/1088652
That'll shorten it and obfuscate it, so that users can't just throw values in the URL.
Params integrity can be ensured with HMAC. You generate hash using secret key and all the params, you include this hash inside of URL, then at server side you generate hash using same params and compare values.
function generateSignature(array $params, $hmacKey)
{
// sort the array by key using SORT_STRING order
ksort($params, SORT_STRING);
$escapeFunc = function ($val) {
return str_replace(':', '\\:', str_replace('\\', '\\\\', $val));
};
// generate the signing data string
$signData = implode(':', array_map($escapeFunc, array_merge(array_keys($params), array_values($params))));
// base64-encode the binary result of the HMAC computation
$merchantSig = base64_encode(hash_hmac('sha256', $signData, pack("H*", $hmacKey), true));
return $merchantSig;
}

Get values of js generated controls, from server side

Let me explain the case;
On the asp.net page, i have a repeater which generates <tr>s and <td>s.
On clientside, i have a js function which adds or deletes rows into that repeater-generated-table.
The problem is, in this function, i dont only generate a simple row, a textbox (which i have to get its value on server side) is generated too.
Is there any way to get value of client-generated controls ?
You can use AJAX to make the connection between the client side and the server side. You can try THIS or read THIS article.
At first glance, I would say you can write an AJAX request to send to the server the content of your textbox and act accordingly.
Beware though, that it can never interact with the server during a page generation cycle.
For who is interested in this topic, Request.Form solved my problem.
Here is the code
The pattern of the name propery is for example: name="txtReturnCause_56"
Dictionary<int, string> ReturnCauses = new Dictionary<int, string>();
foreach (var key in Request.Form.AllKeys)
if (key.StartsWith("txtReturnCause"))
{
int _key = key.Split(char.Parse("_"))[1].ToInt();
string value = Request.Form[key];
ReturnCauses.Add(_key, value);
}

Categories

Resources