Preventing scripted POST in ASP.NET MVC - asp.net

In my ASP.NET MVC project, user can save a form on screen which makes HTTP POST request to server.
How can I prevent client to send automated HTTP POST's to server. Is there any builtin way on IIS or web.config to block unusal request rates?
For example a setting like, "based on Session ID, request count in 1 minute cannot exceed 30" could be helpful.
Captcha control is not a good option for me. Because there are many save options on screen, setting captcha for each of them will be useless.

Not quite what you asked for, but you can use session variables to limit a form from being posted unless the form is first requested, and protect against being submitted multiple times.
On your form page, generate a random number:
Random rnd = new Random();
int key = rnd.Next(100000, 999999);
Create a session variable with this number as the name, something like this:
Session["key_"+ key.ToString()] = true;
In your form add a hidden field with this number:
<input name="key" type="hidden" value="#key" />
Upon form post get the hidden field value and check that the session variable exists. Then remove the session variable so the form cannot be resubmitted:
int key = 0;
int.TryParse(Request.Form["key"] ?? string.Empty, out key);
if (Session["key_" + key.ToString()] == null)
{
//invalid post, take some action
//best to return the user to the form and give them another chance
//in case it was legitimate, eg. session timed out
}
else
{
Session.Contents.Remove("key_" + key.ToString());
}

You can use a mvc attribute called AntiForgeryToken on your post action method, It generates a encrypted value and a salt used to verify if your post is authentic.
See this link
https://msdn.microsoft.com/en-us/library/dd470175(v=vs.118).aspx

Related

Not able to add more than 2 values in cookies

Hi I am new to java servlets. I was trying to implement simple shopping cart problem using cookies. In my web page I ask user to input a product name that she can add to her cart.
Web page:
Simple text input (product name)
and a Button (add to cart)
Upon clicking the button, the web page displays the cart values.
I am experiencing a strange problem. It works fine for less than 3 values. When I try to add third value, it's only displaying the most recently added two values. For example if I add products a, b and c respectively. It displays b and c only.
Cart Servlet code:
String name = request.getParameter("productname");
Cookie cookie = new Cookie("product", name);
cookie.setMaxAge(100 * 60);
response.addCookie(cookie);
Cookie[] cookies = request.getCookies();
List<String> names = new ArrayList<String>();
names.add(name);
if (cookies != null) {
for (Cookie c: cookies) {
if (c.getName().equals("product")) {
names.add(c.getValue());
}
}
}
PrintWriter writer = response.getWriter();
for (String item: names) {
writer.println("<h4>" + item + "</h4>");
}
index.jsp:
<form method="post" action="Cart">
<input type="text" name="productname" value="Product name">
<input type="submit" value="AddToCart">
</form>
I have spent so many hours to figure out what's wrong in it. but I couldn't find any mistake to explain this strange behavior. Please help.
The behavior came from the way how your client (browser) and server handle cookies with the same name.
"Several cookies might have the same name but different path
attributes."
https://docs.oracle.com/javaee/7/api/javax/servlet/http/Cookie.html
So in your case it is basically the same cookie (based on name and path) which is updated constantly.
So what happens in your case: Basically, the browser returns cookies to the servlet by adding fields to HTTP request headers. Assuming that your first product was named a and you are sending your second product with the name b, your cookie-header looks like
Cookie:JSESSIONID=BCC7050AE82AEA1A4B9BED1174424A92; product=a
and your form-data
productname:b
The server receives the request and a new Cookie is created and added to the HttpResponse cookie list. The list containing two cookies named product is correctly printed in your response. Since the servlet sends cookies to the browser by using HTTP response headers and your cookies are the same, only an update takes place.
Set-Cookie:product=b; Expires=Sat, 23-Dec-2017 11:23:53 GMT
As a consequence the next request only contains the information regarding product b and product a disappears.
I found that following piece in web.xml doesn't invalidate session even after closing the browser. Thanks to fI12 for suggesting the link of Session Lost when closing the browser.
<session-config>
<session-timeout>11520</session-timeout>
<cookie-config>
<max-age>11520</max-age>
</cookie-config>
</session-config>
Using cookies for shopping cart is not a scalable solution. Sessions are the way for this.

Classic ASP HTTP Post from another server

I am litte confused, i want to protect one page in classic asp from being accessed by Get Method.
Is it possible that someone can post data from another server to my page?
If Yes, how to detect that and allow only post from my server.
Thanks for help.
If you are currently using Request("ParameterName") to retrieve parameters then you should change to Request.Form("ParameterName") which will only get the parameter if it was POSTed.
Alternatively you can lookup the method used to access the page from the Request.ServerVariables collection and end the script if it is not POST. Here's an example:
If Request.ServerVariables("REQUEST_METHOD") <> "POST" Then Response.End
I noticed that you also said that you want to accept posts only from your server. The above changes will still allow another webpage to be set up to POST to your page. If you want to ensure that only your web page can post then you will need to add some more protection. Here's one way of doing it.
1) When you render your form create a random numbers and create a session variable named by the random number with a value to check for later.
Randomize
strVarName = Int((999999 - 100000 + 1) * Rnd() + 100000)
Session(strVarName) = "Authorised"
2) In your form add a hidden field with the value of the random number.
<input type="hidden" name="varname" value="<%= strVarName %>" />
3) In the script that processes the posted form get the value of the hidden field.
strVarName = Request.Form("varname")
4) Check that the session variable is set and has a value of True.
If Session(strVarName) <> "Authorised" Then
'Failed! Either show the user an error message or stop processing
Response.End
End If
5) Remove the session variable so that the same form cannot be resubmitted.
Session.Items.Remove(strVarName)
You don't need the random number but using it means that the same user can have multiple forms open in different windows/tabs and each one will work.

Passing data between different URLs

I need to check where did the incoming request came from before loading a page
ex:
for user to view www.mysite/page1.aspx
request should come through www.othersite/page1.aspx
so on page1 load in mysite i need to check whether the request came from page1 in othersite.
i have tried Page.Request.UrlReferrer but i saw there some posts which tells every browser might not support Page.Request.UrlReferrer.
i can not pass visible parameters on URL.
This is a common issue when you do not want to allow request from arbitrary sites.
What you can do is, create a variable in session and put this variable in the Page1.aspx. When the page posts back, you should get that variable back and it should also match the one stored in the session. If it does not, you can be sure that the request is from some other server.
You can use PostBackUrl on the start page
And access your parameters with PreviousPage in the arrived page
if (this.PreviousPage != null)
{
var control = Page.PreviousPage.FindControl("..."); //Adjust your Id and add cast
}
Nota : This was also created to provide greater security redirection setting.

How to get data from a control into another ASP.net page?

I'm creating a time sheet for work to learn more about asp and making database connections I am also using this time to prepare for my next C# and database design class which start on Wednesday. I'd like to know how I can get data from default.aspx and display it in timesheetdisplay.aspx, and I would also like to know how I can make it so the person doesn't have to enter the full id "100000111" as it appears in the database just the last 3.
<asp:TextBox id="xBadgeTextBox" runat="server" width="100px"></asp:TextBox>
As far as passing data between pages you can pass it via QueryString, Session variables, or by persisting it to some sort of data store such as a Database. In the situation above I would look at passing via Querystring parameter. Be sure that if you do do this that you validate the data on the new page to ensure its safety and validity before using it (think SQL Injection Attack).
How to: Pass Values Between ASP.NET Web Pages
As far as your second question goes I would say that this could be handled on the server side if you are sure that the last 3 digits will always be unique. Or were you looking to prompt the user entering data similar to Google? If so look at the AutoComplete Extender in the AJAX Control Toolkit or look at doing something similar in JQuery.
If you're redirecting from page to page, consider using the Server.Transfer("timesheetdisplay.aspx", true) method when navigating away from your default.aspx page. Note the second parameter, true, which will persist all ViewState and QueryString data across from page to page.
I would generate a unique key, store the value you are transfering in the users session, redirect the user and include the key in the query string, grab the key, and then get the value. Something like this:
//---On Default---
var value = "can be a single string or even a complext object...";
var keyName = Guid.NewGuid().ToString();
HttpContext.Current.Session[keyName] = value;
HttpContext.Current.Response.Redirect("timesheetdisplay.aspx?SID=" + keyName);
//---On TimeSheet---
var getKeyName = HttpContext.Current.Request.QueryString["sid"].ToString();
var myValue = HttpContext.Current.Session[keyName];
To get the id from a partial ID I would do it just like Muhammad Akhtar said:
select * From yourtable where id like '%111'

Redirect to Error page when user clicks the Browser Refresh button

i need to check whether the user clicking the browser Refresh button and redirect to error page. Can we do this in javascript or any server side methods in ASP.net
If you give each link you present a unique ID (e.g. a GUID) in the URL as a parameter, then you can keep track of all the requests you've processed. (You could clear out "old" requests if you don't mind the mechanism not working if someone leaves a browser open for a few days and then hitting refresh.) The first time you see a GUID, write it into the table. If you see it again, redirect to an error page.
It's pretty ugly though, and users could just edit the URL to change the GUID slightly. (You could fix this last flaw by recording the GUID when you generate it, and update the table to indicate when it's been used.)
In general, users expect to be able to refresh the page though - particularly for GET requests (even though most users wouldn't know what that means). Why do you want to do this?
Well, you can use a very famous tecnique called "Syncronizing Token" or something like that =D, mostly used to send forms.
This will work like this:
Create a function to provide a pseudo-random string token.
For every request to you page, check if a variable in Session, ex: Session["synctoken"] if present. If no, then it is the first time, generate a token and store it there.
Every link request, ex: "mypage.aspx" put a get called synctoken with another token, diferent from the one you have stored in the Session, it goes like "mypage.aspx?synctoken=2iO02-3S23d".
Then, comming back to (2), in a request, if a token is present in Session check if the GET is present (Request.QueryString["synctoken"] != null). If no, send Error. If yes check whether the Tokens (Session and GET) are different. If they are different, it is ok, store the GET into your Session (Session["synctoken"] = Request.QueryString["synctoken"]) and go to step (2). If no, then the user refreshed the page, there goes your error.
It goes like:
if (Session["synctoken"] != null) {
if (Request.QueryString["synctoken"] != null) {
if (Request.QueryString["synctoken"].ToString().Equals(Session["synctoken"].ToString())) {
// Refresh! Goto Error!
MyUtil.GotoError();
}
else {
// It is ok, store the token and go on!
Session["synctoken"] = Request.QueryString["synctoken"];
}
}
else {
MyUtil.GotoErrorPage();
}
}
else {
Session["synctoken"] = MyUtil.GenerateToken();
}
Sorry if I could not be more clear.. good luck!
You can do that, but I'm sure you shouldn't. The user is in control of the browser, and if she feels like refreshing, it your job to make sure the page refreshes. Returning an error page is the wrong answer.
you can use client side hidden variable to store a counter or you can put counter in session. Well I would suggest you to expire the page on refresh there are ways you can achieve this disable cache etc [like all banks website do].

Resources