I have an have an ASP.Net page which contains a button. This Page contains a ServerSide Paypal button.
When pushed my server does various clever things on the back end and then rewrites the response as a form and some javascript which posts this form to paypal..
This all works great.
However, if the user then elects to click back, they will arrive at my generated self-posting form and that will forward them again to Paypal.
I thought if I could find a way to have my generated form page not exist in the history, then this will solve my problem. but I have no idea how to correct this.
How can I remove my page from the history or just have it never appear?
Update: Thanks to all... Those are some great answers. Upvoted all good ones but went with splattne on account of clever use of hidden field rather than cookies for basis of decision.
window.location.replace(URL);
window.location:
replace(url)
Replace the current document with the
one at the provided URL. The
difference from the assign() method is
that after using replace() the current
page will not be saved in session
history, meaning the user won't be
able to use the Back button to
navigate to it.
I'm not sure if that can be done. But here is an idea how you could prevent that resubmit of the form.
You could insert a hidden input in your form which at the beginning would be empty. On submit you'll write a value in that field and make sure you check on every submit attempt if this field is empty.
If it is not empty on submit you know that the form was previously sent and you could warn the user.
As a web application, you'll never have full control of the user's browser. Even if there was a way to instruct the browser to not store the page in history, which I doubt, you can't be sure it'll work. For example, a clever user could tweak an open-source browser to store every page in history, no matter what.
I think you should try to approach the problem from another angle. You could, for example, detect that it's the same form which is being forwarded and not send it to paypal the second time. The important thing is to do it server-side.
Perhaps you could set a cookie before submitting the form.
When the page is loaded, check for the existence of that cookie (meaning the form was already submitted). If found, instead of automatically submitting the form, automatically go back (window.history.back()) again.
I'm not sure if you can do this easily with PayPal integration, but the
"Post / Redirect / Get" pattern can be used to address this problem
A useful Hint for some might be this...
window.history.go(-2);
particularly in the advent of a load failure warning popup.
You could simply programme your page not to submit, or to do something / navigate somewhere else, if window.referer is the Paypal page you are trying to avoid invoking a second time.
protected void Page_Load(object sender, EventArgs e)
{
Page.RegisterClientScriptBlock("", "<script>if(history.length>0)history.go(+1);</script>");
}
Related
Is there a trusted way to disable the direct access to an special web page? I mean I want to open it only by clicking on a Button for example. I know I can access to the webpage by using this code but It can not prevent accessing to the web page directly (Pasting the url or typing it):
Response.Redirect("~/Code.aspx")
Thanks
This is a long shot because I don't have the time to test this now (I can see some downvotes coming already!), but...
In the "Code.aspx" page, check for Session["allowed"]. If the value is not there, end the response.
Next, make another page (from where Code.aspx can be accessed). In this page, set Session["allowed"] and then do a Server.Transfer() to Code.aspx, which will then run OK.
Finally, at the end of processing Code.aspx., remember to clear the Session["allowed"] variable again.
Hope this makes even vague sense :)
You may be able to write a piece of code on page load that checks the contents of HttpContext.Current.Request.ServerVariables("HTTP_REFERER") - if it's blank, a user has navigated to the page directly and you can handle it that way.
On the source page create a token into a hiddenfield. To your button add PostBackUrl property and let it point to your destination page.
On the destination page you can validate that the request was made from your allowed source page. And you dont need to use session and all its drawback.
Check this Link for detailed information about how to use the mentioned property.
This is not a cross-site attack because it happens on the same website.
Before we render to the browser, we figure out in server-side whether to render a button or not based on whether the user has sufficient credit in their account (example case). So, if they have insufficient credit, the check out button doesn't even make it to the page on page load.
Here's what they did:
Go to a purchase product page when they have sufficient credit. The check out button shows.
They look at Inspector (FireFox) or any other in-browser developer tool and copy the html input element that submits the form.
They purchase as normal. Now, they have insufficient credit.
They go to another purchase product page, and of course, the check out button will no longer show (because it didn't even make it on page load in the first place).
They open up their in-browser developer tool and paste the input element copied from the other previous page when they had sufficient credit. The button shows up on the rendered page. They click it, then they proceed as if they had sufficient credit.
The problem is, the submit button's event handler in code behind is unaware of the existence or non-existence of that submit button, and will execute if called, and that we give it a hard-coded id.
The obvious solution would be to do a credit vs. price check [again] on the click event handler. From inside the event handler, is there a way to determine whether the control existed on page load? I figure that the sender parameter would not be null if they pasted a control in-browser, so there's not much help there.
Any solutions on this?
The only safe solution to this is to check if the user has sufficient credits ON THE SERVER after the postback occurs.
protected void OnSubmit(object sender, eventargs e)
{
if (product.Price > User.Credits) {
throw new Exception();
}
purchase();
}
If you use the check the button approach then they can still use the JavaScript console to call __doPostBack
Never rely on the client side for authorization
You could store in ViewState whether the button was rendered or not; this is encrypted and cannot be changed on the client. If you set it as ViewState["ButtonRendered"] = true;, then you can check this to see if it's true or false, and act accordingly.
Because of the nature of the user opening up multiple browsers, and other tricks, I would 100% recommend you do another database query to make sure they have sufficient credit, and if not, display an error to the user. That would be the absolute best way of handling it. What would keep them from opening up firefox and chrome, and trying to attempt to simultaneously purchase two different items?
Apparently I am not familiar with the Life Cycle of a page in ASP.NET. This became apparent when I wanted to dispose of a Session variable after I left the page. I did what made the most sense:
protected void Page_Unload(object sender, EventArgs e)
{
Session.Remove("ServiceSearch");
}
What I didn't know is that this would be called when I go from AND to the page. What I am wanting to do is dispose of that Session variable whenever the user leaves the page. How do I do this?
Page_Unload refers to unloading the Page object right before it is disposed after parsing and creating the page. It has nothing to do with leaving the page. Like #Nick says, there is really no good way to tell that, except to control every exit path. And you can't, because you can't control when the user hits back, or goes to google.com and then pastes in the url they were just at into the browser, etc.
If you want to remove the Session variable just so it doesn't get re-used unintentionally, a better solution is to overwrite the Session variable every time you enter the page, and just let it be disposed with the session on its own time when the session expires.
Session data is useful for storing data beyond the lifetime of a page. If you don't want to store it beyond the life of a page then Session data is not for you here.
If the user leaves the page via a link you could possibly create a link button that is hooked up to a method on the same page. That method would remove the session and do the redirect.
I would hope there is a better solution though. Although, from my understand, there is no page event to use in your case because the page would have to reload to execute the remove session code. When the user leaves via some link the page is not reloaded.
You may possibly be able to handle it via javascript. I've been in situations where I wanted to leave and I got a popup box about some bs. You could probably use the same technique to fire AJAX to remove the session.
I faced a similar situation on php login- a logged-in user could use the arrow back and forth to login page. So, I simply add :
session_start();
session_unset();
session_destroy();
above the html script of the login page so that if the logged-in user arrowed back, the session is both unset and destroyed. Any attempt to arrow forward will only lead to the login page-requesting user login credentials-essentially, the user is logged out any time they arrow back!
Hope this helps!
Alfred
I have a webservice that I need called, the result of which determines whether or not the user is allowed to submit the form.
Since this call is from javascript and not from code behind is it not reliable? Is there any way the user can get around the check -- by either going in with firebug and enabling the submit button, somehow making the method give a different result than was actually returned by the webservice, any other ways of being able to get around it?
Basically is there any way to call a webservice from javascript and have it's result determine whether or not a form can be submitted, and actually prevent the user from submitting the form at all? -- whether or not they have firebug, etc...
No, not possible.
Just to name a few possible reasons:
what if javascript is disabled?
what if the user submits the raw POST (using libcurl, for example)?
what if the browser, that the user is using interprets javascript in a way, different from your expectations (think, portable devices)?
Javascript validation is there for your users' convenience only and should never ever be used as a means of providing security.
You can never prevent the user from making an HTTP request that mimics submission of the form. While disabling the form via Javascript prevents submission for 95% of the users who both have Javascript enabled and don't want to circumvent your access control, anyone who understands HTTP can make the call and you are correct in showing that anyone with Firebug can do it in a matter of seconds.
Javascript isn't reliable for preventing anything. It shouldn't be seen as a security-wall, as it's too easily disassembled with things like firebug, iedevelopertoolbar, and many other browser toys.
Even if you could prevent them from submitting your form on your page, nothing stops them from creating a brand new form, on their own page, and point it toward the action of your form. Thus they're removing themselves from your "secure" environment, and instead chosing to play in their own.
Your suspicion is correct; the user can easily get around any possible Javascript validation.
You will need to use server-side code.
No, it is not reliable. Try disabling Javascript in your browser to see for yourself how easily you can get around it.
The user could simply disable javascript in their browser, or use something like NoScript. The best you could do is to try setting the form action itself in the return from the Ajax request, that way the form, as loaded, won't submit (except to itself). This will probably stop casual users but would be no impediment to a slightly more determined (or just bored and tech savvy) user. You will need to check on the server side whatever you do.
In general, no. You can make the form hard to submit without going through Javascript. Make the submit button not an actual submit button (<input type="submit">), but a pushbutton (<input type="button">) that submits the form in its onClick handler.
As everyone else said, no you can't do it. The only real solution is to have the web service return some dynamic value which the Javascript inserts in a hidden form input. Then whatever server-side code processes the form submission should reject the request if that value is not present.
I want to redirect the user to another page to fill out a captcha but i would like to keep the post data, and if the captcha pass to send it 'back' and complete the previous page action.
When/if the user succeeds i like to add an captchaPass=true and would like access the post data and continue processing. Right now i am using redirects but ATM i am not required to use it.
Is it possible to carry the post data? keep in mind i may the user access multiple pages so separating data and not having a mixup is necessary.
One idea is to get and save all posted data [1] on the captcha page, and then recreate a middle white page with this form data and automatically make a new post to the previous page.
Can this work with out any issues with hash checks and security ?
Is there a better idea with out this white redirect page ?
[1] One other issue here, how to send this posted data with the redirect ? and not change the url - or make it too big to accept it. Keep in mine that a server transfer may not good idea because is complicate the thinks on captach post back.
Update 1
The basic idea here is how some one capture the full post back of a page, show a different one page and then send the post back data to the original first one.
The reason is to stop a bad user, or an attacker bot program that try to bring down the pages/server by making many post back from different pages in short time. All that happens with out javascript, and most attackers use custom made programs that just make post of data to all page together try to bring down the system.
For example, if a page have a search box, is very easy for most of the the site to bring them down by start making hundred of random search with wildcard (called and Dos Attacks using SQL wildcards) and make the sql server and the computer spend his time and cpu to search and search thinks. So to prevent an attack like this you need to recognize multiple post backs from the same computer, and then the next step is to redirect him to a captcha page to block him out in case that is a computer program.
Other example, many page have email submit, very easy you can submit hundred times the email of his and full his mail box in no time with hundred of emails, or on a store to place all items on the cart again and again and full the database with stuff like that.
So ajax and javascript is not working in this case, and we need a way to redirect him after the post back to a page that can check if is a real user or an attacker and stop him - but if is a real user must return back to his normal action.
Update 2
This all must be done in a general way, eg on BasePage, or on Global.asax or somewhere that is independed from the content of any page. Because we try to prevent a DoS attack, or multiple submit anywhere on any random place of any random page.
Yes I know how you can place a captcha on the contact page, but this is not what this question was first asked for - this questions asked how can carry post data to one different page, keep them there and then resend them back to the original one.
The obvious solution is to read all post back, and save them on the form, and then read them back and make on fly a form only with that data and make the post back. Here I am asking if there are any other better than this solution.
Other Applications
There is also the case that a user is inside a page that request authentication, but the authentication ticket has expired, and the user make post back. In this case we need to keep somewhere all the posted back data, to proceed with the login page, and resend them back to the first page that request the authentication.
Sure, just write the form data out to the captcha page in hidden elements with the additional captcha fields added to the form. Have your submit action post the whole thing back to the original. Using ASP.NET it's probably easier to have the captcha written to the same page with the form fields hidden, but you can do cross-page postbacks as I've described above.
Cross Page Posting might help you.
Why not implement the CAPTCHA with AJAX? Load the captcha object and form with Javascript in a div perhaps displayed lightbox style, accept the user input and post it to your server for validation, hence continue with the users post request or keep them there until they get it right (or cancel).
A more specific situation example:
Give the form submittal button an onClientClick value of some Javascript function. This function decides if this particular form needs a CAPTCHA. If it does it loads an interface for taking the CAPTCHA (which you'd need to do with some server-side code) and inserts the CAPTCHA's input element to the form that the user clicked to submit.
Once the user has entered the CAPTCHA input and clicks some button whose click event is bound to return to your first JS function, the Javascript intercepts this action and posts the full form, all the data from the original form and the CAPTCHA for validation. Your server script can now process all this at once!
This is the best solution I can think of that works similar to how you've asked, but I can't imagine why you want to perform the CAPTCHA on a different page.
Server.Transfer with MultiViews, Panels like control is fine with you? In this way, no need to bother about the Data Maintenance and Postbacks. You can do the validations in javascript.
You can keep both functionality in the same page to avoid moving data from one page to another page/Bring the data back to original page. You can utilize Session for this intermediate operation. Set it back to associated controls across Postback. You can create a class, Instantiate it and Initialize the control values in this class object. Save class object in Session. On Postback, You can reassign the values to the associated controls. This will definitely keep the things simple and without much complexity.
Doubts ?