avoid sql inject by query string in asp.net - asp.net

I programed an application with asp.net and use "respons.redirect" in some pages, like this:
Response.Redirect(string.Format("~/*****/****.aspx?ID={0}", ID));
as user execute this cod he will redirect to correct page and every thing is fine .he can see this redirect link in his browser address :
http://localhost:1852/Jornal/Editor/ReviewerEmail.aspx?ID=1030
Now if he changes the ID manually and the ID is correct he can access the other data without any permission. how can i avoid this problem?(I wont use session)
please help me

If the ID needs to be public and no access control can solve the problem.
then i would suggest that you add a second parameter that is a hash of that Id.
Tampering with the ID parameter will cause a missmatch between ID and hash
http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256.aspx
you cold also change your ID parameter to a less 'guessable' id, like a GUID

You need to use access control.
Whenever you display any data, you need to check whether the currently-logged-in user has access to that data.
Obviously, you also need to track the currently-logged-in user, in a way that will prevent attackers from being able to claim they are someone else..
To do that, use ASP.Net's built-in membership system.

Related

MVC - how can I store a variable for the duration that a user is logged in

I have a project in MVC. I would like to save a variable and have it accessible as long as the user is logged in, to get it or set it.
The reason for this is that the application uses the information I would put in there, to get data. I now need to add admin functions so an admin can see more then only his own results, and therefore I would need to change this ID, depending on what result he wants to see.
I have tried using a session, but the problem I have with that is that when the user closes the website, and at a later time returns, he is still logged in, but the session variable is null.
I also tried to add a property to my base class. I was able to set it, but when I tried to get it in a different controller, the property was null as well.
What is the best/fastest/correct way to do this? I would prefer to not use the database for this, if possible.
What you are looking for is a "Session". On login you can just do
Session["Key"] = "Value";
And on logout you can empty the field
Session["Key"] = String.Empty;
You can read more about sessions here: https://msdn.microsoft.com/en-us/library/ms178581.aspx

Security Issue with ASP.NET and SQL Server

A problem appears when two users are logged on to our service system at the same time and looking at the service list gridview. If user1 does a search to filter the gridview and user2 happens to click to another page user2 sees the results from the search performed by user1. That means one company can see another company's data.
It's an ASP.NET application that was developed in house with C#/ASP.NET 3.5. The data is stored in a SQL 2000 database and relies very heavily on stored procedures to update, select, and delete data. There are multiple user types that are restricted to what data they can see. For example, we have a company use that can only see data relavant to that company.
From what I've seen, the security is handled through If statements in the front end. Example, if userlevel = 1 then do this, if userlevel = 2 do this. These statments are used to show or hide columns in a grid, run queries to return data, and any other restrictions needed. For a company user the code behind gets the companyid assigned to the user and uses that in a query to return the results of all the data associated with that companyid (services, ships, etc).
Any recommendations for fixing this will be highly appreciated.
It's hard to say without seeing any implementation details, but on the surface it appears that there maybe some company level caching. Check for OutputCache settings, DataSource caching, explicit caching with Page.Cache, etc.
This article is a little dated, but at a glance it looks like most information is still relevant in ASP.NET 4.0.
ASP.NET Caching: Techniques and Best Practices
In addition to jrummerll's answer, check the Data Acces Layer of our app and make sure that you don't have any static variables defined. Having a static variable defined could cause this sort of issue too, since 2 contending requests may overwrite the value of the CompanyID, for example.
You basic model should work. What you've told us is not enough to diagnose the problem. But, I've got a few guesses. Most likely your code is confusing UserID or CompanyID values.
Are you mistakenly storing the CompanyID in the Cache, rather than the session?
Is the CompanyID stored in a static variable? A common (and disastrous!) pitfall in web applications is that a value stored in a static variable will remain the same for all users! In general, don't use static variables in asp.net apps.
Maybe your db caching or output caching doesn't vary properly by session or other variables. So, a 2nd user will see what was created for the previous user. Stop any caching that's happening and see if that fixes it, but debug from there.
Other variations on the above themes: maybe the query is stored in a static variable. Maybe these user-related values are stored in the cache or db, but the key for that record (UserID?) is stored in a static variable?
You can put that if statements in a thread. Threading provides you the option that only 1 user can access the application or gridview in your case.
See this link: http://msdn.microsoft.com/en-us/library/ms173179.aspx
Here is some sample code that is throughout the entire application that is used for filtering results. What is the best way to fix this so that when one user logs on, the other user doesn't see those results?
protected void PopulategvServiceRequestListing(string _whereclause)
{
_dsGlobalDatasource = new TelemarServiceRequestListing().GetServiceRequestListingDatasource(_whereclause);
if(_dsGlobalDatasource.Tables[0].Rows.Count!=0)
{
gv_ServiceRequest.DataSource = _dsGlobalDatasource;
gv_ServiceRequest.DataBind();
}
else
{
gv_ServiceRequest.DataSource=new TelemarServiceRequestListing().DummyDataset();
gv_ServiceRequest.DataBind();
gv_ServiceRequest.Rows[0].Visible = false;
gv_ServiceRequest.HeaderStyle.Font.Bold = true;
}
}

Asp.net, where to store the username of logged in user?

When a user log into my asp.net site I use the following code:
FormsAuthentication.RedirectFromLoginPage(userid, false);
As I often need to use the userid I can then later get the userid by:
string userid = System.Web.HttpContext.Current.User.Identity.Name;
Now I also want to show the logged in username on each page and my questions is therefore where do I place the username best if I need to use it on every page. User.Identity.Name is already taken by the userid so I can't use that one. Another solution would be to get the username from the database on each page, but that seems like a bad solution.
So: Is the best way to use Sessions to store the username?
There are essentially 6 different ways to store information, each with it's own benefits and drawbacks.
Class member variables. These are only good for the life of one page refresh.
HttpContext variables. Like class member variables, only good for one page refresh.
ViewState, these are passed from page to page to keep state, but increase the size of the downloaded data. Also, not good for sensitive information as it can be decoded.
Cookies. Sent on each page request. Also not good for sensitive information, even encrypted.
Session. Not passed to the end user, so good for sensitive information, but it increases the resource usage of the page, so minimizing usage for busy sites is important.
Authentication Cookie User Data - This is like like cookies, but can be decoded with the authentication data and used to create a custom IIdentity provider that implements your desired Identity information, such as Name or other profile information. The size is limited, however.
You can store just about anything in SessionState in asp.net. Just be careful and store the right things in the right places (you can also use ViewState to store variables.
Check this out for how to use SessionState to store and retrieve variables across postbacks.
public string currentUser
{
get { return Session["currentUser"] as string; }
private set { Session["currentUser"] = value; }
}
Using sessions isn't a bad idea but make sure to check for NULL when retrieving the values for when the sessions time out.
Or you could pass the variable through in the URL e.g
/Set
Response.Redirect("Webform2.aspx?Username=" + this.txtUsername.Text);
/Read
this.txtBox1.Text = Request.QueryString["Username"];

How to create a unique web page address in ASP.NET

Is there a standard way to create unique web page address in ASP.NET? I'm sending surveys to customers and will be including a link to the web page. For example:
http://www.mysurveypages.foo/survey/UniqueID
I would then customize the survey based on who I sent it to. I know it can be done by passing in a unique parameter to a page but I curious about doing it this way.
You can use Routing to map your url structure onto a particular page and parameter collection. Essentially, it allows you to convert parts of the url into url parameters for your page. This works in standard WebForms and is the basis upon which MVC chooses the appropriate controller/action signature to invoke.
Yup like dcp said GUID is a reasonable solution http://mywebsite.com/survey.aspx?ID=GUID
Suppose you are going to sent the survey to a list of users.
List<User> users = GetSurveyUsers();
foreach(User u in users)
{
Guid guid = Guid.NewGuid();
//Then store the user-guid pair into DB or XML...
}
The simplest solution would seem to be making UniqueID an incrementing field that can be used to get the appropriate user information out of the database. You could use numbers, or a Guid, or some alpha-numeric value, it really doesn't matter.
If you go with ASP.Net MVC then it is quite easy to map the Url (like the one you specified) to a controller action which gets the ID passed in as a parameter. Otherwise you will probably want to look into some sort of Url rewriting to make sure the Url can be nice and pretty.
A GUID approach is safest, if you're able to store it somewhere. If not you could use some existing unique data (e.g. customer id or email address) either directly (but be careful about leaking sensitive data) or hashed (but need to consider collisions).

What is the best alternative for QueryString

We heard a lot about the vulnerabilities of using QueryStrings and the possible attacks.
Aside from that, yesterday, an error irritated me so much that i just decide to stop using QueryStrings, i was passing something like:
Dim url As String = "pageName.aspx?type=3&st=34&am=87&m=9"
I tried to
Response.Write(url)
in the redirecting page, it printed the "type" as 3, then i tried it in the target page, it printed 3,0....i know this can be easily dealt with, but why? i mean why should i pass 3 and have to check for 3.0 in the next page's load to take my action accordingly???
So what should we use? what is the safest way to pass variables, parameters...etc to the next page?
You could use Cross-Page Postbacks.
Check also this article:
How to: Pass Values Between ASP.NET Web Pages
There are many options you can use, most of them requires you to build a strategy to pass variables between pages.
In most projects I use this strategy, I create a formVariables class to hold currently active items. it has properties which you will need to pass by querystring. and I store this class at session. and in my base page I read it from session. so in every page I get values over this object. the only negative thing about this method is to clean up items when you finished your work on it..
hope this helps.
I would sugest you avoid using Session to pass variables between pages as this breaks the stateless model of the web.
if you have just stored some values in session that relate to a certain page then the user uses their browsers back button to go back to the same page whcih should have a different state then you are not going to know about it.
It leads to the possibility of reading session values that are not relevant to the page the user is currently viewing - Which is potentially very confusing for the end user.
You will also run into issues with session expiration if you rely on it too much.
I personally try to avoid using session where possible in preference of hidden form values + query strings that can be read on postback + navigation.
The best / most secure way to pass info between pages is to use the session.
// On page 1:
this.Session["type"] = 3;
// On Page 2:
int type = (int)this.Session["type"];
You can store any kind of object in the session and it is stored on the server side, so the user can't manipulate it like a query string, viewstate, or hidden field
You said:
it printed 3,0....i know this can be easily dealt with, but why? i mean why should i pass 3 and have to check for 3.0
There's a difference between "3,0" (three comma oh) and "3.0" (three point oh). You also said that you were "passing something like".
In a query string, if you pass multiple values in the same key, they will be seperated with commas.
As all values are passed as strings there's no way that an int "3" is going to magically become decimal "3.0" unless you parse it as such when you request it.
I'd go back and double check what you are passing into your URL, if it ends up as something like:
pageName.aspx?type=3&st=34&am=87&m=9&type=0
Then when you read back
Request.QueryString["type"]
You'll get "3,0" back as the comma seperated list of values in that key.
First, in asp .net you can use several strategys to pass values between pages. You have viewstate too, however the viewstate store the value and the use is in different scenarios , you can use it too. Sessions instead, and of course by post in a form.
If your problem is the security, I recommended you to create 2 users for accesing the data. One user with read only access, this for accessing the pages ( Sql Inyection prevent ) and validate the data throw the querystring. And One with write access for your private zone.
Sorry, for my unreadeable English.
I like to use query string as I like users to be able to bookmark things like common searches and the like. E.g. if a page can work stand-alone then I like to it to be able to work stand-alone.
Using session/cross-page postbacks is cool if you needed to come from another page for the page you're on to make sense, but otherwise I generally find querystrings to be the better solution.
Just remember that query strings are unvalidated input and treat them with the caution you would treat any unvalidated input.
If you do proper security checks on each page load then the querystring is fine and most flexible IMHO.
They provide the most flexibility as the entry poitn to a page is not dependant on the sender as in some other options. You can call a page from any point within your own app or externally if needed via querystrings. They can also be bookmarked and manually modified for testing or direct manipulation.
Again the key is adding proper security and validation to the querystring, and not processing it blindly. Keep in mind that the seucirty goes beyond having edit or read access, depending on the data and user, they may not have access to the data with thos paranters at all, in cases where data is owned and private to specific users.
We have tried various methods, in an attempt to hide the querystring but in the end have gone back to it, as it is easier to do, debug, and manage.

Resources