I have an ASP.NET page running in SSL and the checking happens in the code-behind.
I've done the following to prevent sql injection:
Included RegEx to filter out unnecessary/hazardous characters (basically, it now only allows 0-9, a-z, and A-Z).
Using queries which would look something like "SELECT * FROM table WHERE username = #Username...".
I've also added account lockout so you only have a limited tries available.
After the IBM AppScan to test the vulnerabilities, it seems I've only fixed the Blind SQL Injection and not the Authenticated Bypass.
Is there anything that I've missed that's causing me to fail the vulnerability test?
UPDATE:
...
bool bUser = FilterInput(txtUsername.Text);
bool bPass = FilterInput(txtPassword.Text);
// check for restricted characters
if (bUser && bPass)
Response.Redirect("Login.aspx");
...
public static bool FilterInput(string text)
{
// check if string contains only letters and numbers
return (Regex.IsMatch(text, #"^[a-zA-Z0-9]+$"));
}
anything not within the a-zA-Z0-9 characters should throw a 'false' and would cause the page to redirect/refresh the login page.
The DB queries are all using parameterized queries and the login works correctly. no problem about that part.
Drop the first thing that you did and just use SqlCommand.Parameters as explained below:
SQL Injection vs. Lethal Injection / Protection Against SQL Injection
I always use multiple Connection Strings in order to access a database and each of them has different roles: reading, writing, execution. When you do that, you make sure that if the attack is being made successfully on a read action, the attacker cannot do someting other than reading (which is still bad but better than modifying)
Apparently there were 2 DB queries on the code the wasn't updated into parameterized queries.
Parameterized queries were enough to prevent SQL injection so the other steps/features are a bit of an overkill.
Related
I'll use a select in asp.net page which i.e:
string name=TexBox1.Text;
string pas=TextBox2.Text;
string c="select * from users where name='"+name+"' and password ='"+pas+"'";
İs there any methods to preventing sql injections.
First, you must validate the input data in your code and then use it like parameters..
because if occurs an unhandled exception and you are returning sensitive data like "connection strings" you are giving usefull information like "Column" and "Table"names and that is dangerous.
Second, add a "Data Access Layer" to handle your code not in "Code Behind". You can use "Store Procedures" and call them from your code, using this way you hide the query of the programming logic and only pass parameters to the store preocedure and he do the job and you only return the error in the case that a exception occurs.
This preventions are the basics in a small application but exists many others way to avoid SQL Injections.
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;
}
}
heys guys,
i have a website, which contains lots of db work to display data on page, so i have created a VB class which is public, under App_Code.
Now i have all the methods and functions under that class are Shared(Static), also i have a connection variable which is also static.
Client complains, that sometime there appears an error on the page, one of those error is Field Name does not belong to table Table, i dont understand, about this, as this is very rare, if there is no field with name, then this should occur everytime, one of my colleague says that there should not be Shared methods or functions... is this correct..
There is no "security" problem with a static method. Your colleague is confused. Whether or not the code you wrote should be static or instance methods depends on what exactly it does. But having them as static methods is not "dangerous."
I suggest you track down the query that is causing the problem because the method being static is certainly not the issue.
As far as your connection goes, I would not recommend keeping it as a static variable. I assume this is a SqlConnection, or something similar. In that case, if you keep it as a static variable, it is possible for the following to occur:
Your connection is never closed, even after you're done using it.
You will have issues if you have multiple queries trying to use the connection at the same time.
So I recommend you use the following pattern to ensure your connections are only kept open as long as they are in use.
public void DoSomething()
{
//Doing some work that doesn't need a connection.
//Now ready to submit or fetch data from the database.
using (SqlConnection connection = new SqlConnection(...))
{
using (SqlCommand command = new SqlCommand(..., connection))
{
//Now, working with the connection and command.
}
}
//Done with the connection, doing more work now.
}
The using statement works with anything that is IDisposable. Your connection variable here will be automatically closed and destroyed at the closing bracket of the using statement. I recommend you use it for anything that you can. Streams, SqlConnections, Fonts, etc.
It sounds to me like you have a infrequently-used SQL statement that refers to a column that does not exist on a table.
For example - suppose you had SQL like so
SELECT Col4 FROM Table2
and Col4 was not a member of Table2. You would get the error you describe.
If you're building SQL dynamically (which is dodgey) you might run into this.
But I don't think it has anything to do with your method 'security.'
I'm writing a webcontrol in asp.net which has to go and fetch information from an API. It's not critical to be up-to-date, and retrieving the information is quite slow, so I'd rather cache the information and update it every 5 minutes.
It strikes me as potentially risky to use the Context.Cache as potentially someone could use the same name, but I can't find another way to do caching within a control.
Does anyone have any other ideas?
(using asp.net 2.0).
It sounds like the Context.Cache is exactly what you need to store this kind of information. The cache object is localized to your application so it would only be changeable by other code in your application.
You can always give your cache key a very long and presumably useless name etc and store that key within your class...
Private const CacheKey as String = "e92a627b-3a9f-46da-a182-d73b44fe87ad" ' A random guid
Cache.Item(CacheKey) = TheRefreshedData ' etc
As I was writing this answer I realised maybe you were talking about your conntrol being re-used within someone else's application...as in your control is redistributed or provided for download. In this case, you could always prefix the cache key with your control to be "sensibly" unique...
Private const CacheKey As String = "MyCompany.MyControl.MyData"
Cache.Item(CacheKey) = TheRefreshedData ' etc
Either way, you should be able to come up with some fairly length string that has zero chance of being reused...
To protect a web application from query string manipulation, I was considering adding a query string parameter to every url which stores a SHA1 hash of all the other query string parameters & values, then validating against the hash on every request.
Does this method provide strong protection against user manipulation of query string values? Are there any other downsides/side-effects to doing this?
I am not particularly concerned about the 'ugly' urls for this private web application. Url's will still be 'bookmarkable' as the hash will always be the same for the same query string arguments.
This is an ASP.NET application.
I'm not sure this provides any sort of security. If a man-in-the-middle attacker wants to change the parameters, all they must do is change the query string and recompute the SHA-1 hash and send that request along to the server.
For example, the URL sent by the browser might be:
http://www.example.com/addUser.html?parameterA=foo&hash=SHA1("parameterA=foo")
If an attacker intercepts this, they can edit it in this way:
http://www.example.com/adduser.html?parameterA=bar&hash=SHA1("parameterA=bar")
Really, this boils down to the fact you can trust the hash only as much as the parameters themselves.
One way you could fix this would be if the user has a password that only they and the server knows, then it would be impossible for the attacker to recompute the hash if they change the parameters. For example:
http://www.example.com/addUser.html?parameterA=foo&hash=SHA1("parameterA=foo"+"theuserpassword")
But don't put the password as one of the parameters in the URL :)
It is important to note that this isn't the state of the art for verifying the integrity of messages passed between two parties. What is used today is a form of the Hash-based Message Authentication Code (HMAC) algorithm, which is pretty well described in HMAC, and definitively in RFC2104 and FIPS Pub 198-1.
My solution to prevent query string manipulation with no hash:
In the global.asax file
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// I take the url referer host. (manipulating the query string this value is null or your local address)
string strRefererHost = Request.UrlReferrer == null ? string.Empty : Request.UrlReferrer.Host;
// This is the host name of your application
string strUrlHost = Request.Url.Host;
// I read the query string parameters
string strQSPars = Request.Url.Query ?? string.Empty;
// If the referer is not the application host (... someone manipulated the qs)...
// and there is a query string parameter (be sure of this otherwise nobody can access the default page of your site
// because this page has always a local referer...)
if (strRefererHost != strUrlHost && strQSPars != string.Empty)
Response.Redirect("~/WrongReferer.aspx"); // your error page
}
You might consider using this little open source library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It uses a unique key for each client computer and comes with many other goodies.
I think is a good idea to add a parameter with a hash of all the other parameters. It prevents radically the querystring manipulation, but you have to think about the problem that means use those URLs in other pages of your application, send those URLs to the public or use them in any printed way. You need to have a very good way to order and to have them at hand speccially if those pages are not dynamically created, or if you just need to add those URLs by hand.
I don't see any other problem about it. Some one may tell you that the hash can be calculated, but you can play with the order of the parameters obtaining different hashes and making very difficult to guess.
One major problem with this is that javascript would have to do client-side SHA calculations just to link to pages, this of course depends on how much you use JS but it shouldn't be unresonable to think that a get argument might include pageNo=1, and to have a 'jump to page' input box, this would be made difficult if you add a hash. You could store in a session (server side) anything that you really don't want manipulated.