views:

374

answers:

6

Hi All,

Is there a "clever" way of stopping direct page calls in ASP.NET? (Page functionality, not the page itself)

By clever, I mean not having to add in hashes between pages to stop AJAX pages being called directly. In a nutshell, this is stopping users from accessing the Ajax pages without it coming from one of your websites pages in a legitimate way. I understand that nothing is impossible to break, I am simply interested in seeing what other interesting methods there are.

If not, is there any way that one could do it without using sessions/cookies?

Thanks,

Kyle

+2  A: 

You can check the Request headers to see if the call is initiated by AJAX Usually, you should find that x-requested-with has the value XMLHttpRequest. Or in the case of ASP.NET AJAX, check to see if ScriptMAnager.IsInAsyncPostBack == true. However, I'm not sure about preventing the request in the first place.

MikeB
Would you not be able to spoof that header?
Kyle Rozendo
Yes. http://stackoverflow.com/questions/623299/can-the-x-requested-with-http-header-be-spoofed
MikeB
Thought so, hehe. Thanks for the answer though.
Kyle Rozendo
+1 For the initial answer, I accepted catchdave's for the example code.
Kyle Rozendo
A: 

I don't think there is a way to do it without using a session. Even if you use an Http header, it is trivial for someone to create a request with the exact same headers.

Using session with ASP.NET Ajax requests is easy. You may run into some problems, like session expiration, but you should be able to find a solution.

With sessions you will be able to guarantee that only logged-in users can access the Ajax services. When servicing an Ajax request simply test that there is a valid session associated with it. Of course a logged-in user will be able to access the service directly. There is nothing you can do to avoid this.

If you are concerned that a logged-in user may try to contact the service directly in order to steal data, you can add a time limit to the service. For example do not allow the users to access the service more often than one minute at a time (or whatever rate else is needed for the application to work properly).

See what Google and Amazon are doing for their web services. They allow you to contact them directly (even providing APIs to do this), but they impose limits on how many requests you can make.

kgiannakakis
Alright, but then do you have a good method for doing it with a session?
Kyle Rozendo
See my edited answer.
kgiannakakis
A: 

Have you looked into header authentication? If you only want your app to be able to make ajax calls to certain pages, you can require authentication for those pages...not sure if that helps you or not?

Basic Access Authentication

or the more secure

Digest Access Authentication

Another option would be to append some sort of identifier to your URL query string in your application before requesting the page, and have some sort of authentication method on the server side.

jaywon
A: 

I do this in PHP by declaring a variable in a file that's included everywhere, and then check if that variable is set in the ajax call file.

This way, you can't directly call the file ever because that variable will never have been defined.

iddqd
I think you have mis-understood the question.What you suggested stops someone from directly browsing directly to a file that is visible via HTTP but that which you only want processed when included (as an aside - a better method is simply to put "included" files outside the scope of the web server all together).The question here is asking how to stop someone from looking at a page via the standard method in a browser - as opposed to - requesting the same URL via an AJAX call (ie: XmlHttpRequest, etc).
catchdave
That's what I'm talking about too. You cannot view a file that checks for a variable that was declared in an included file directly. Try it. Make an index, declare variable. Include another file. Check for that variable's existence in the file you included.
iddqd
Of course not (assuming register_globals is off). But in that case, that same file would not be able to be called directly via AJAX either (which is what the questioner wants to be able to do).
catchdave
+4  A: 

Have a look at this question: http://stackoverflow.com/questions/216173/differentiating-between-an-ajax-call-browser-request

The best answer from the above question is to check for a requested-by or custom header.

Ultimately, your web server is receiving requests (including headers) of what the client sends you - all data that can be spoofed. If a user is determined, then any request can look like an AJAX request.

I can't think of an elegant method to prevent this (there are inelegant and probably non-perfect methods whereby you provide a hash of some sort of request counter between ajax and non-ajax requests).

Can I ask why your application is so sensitive to "ajax" pages being called directly? Could you design around this?

catchdave
Thanks catchdave. The reason why I accepted this over MikeB's is for showing exactly how this is done. Seems there are not very many ways of stopping people from doing this, which I suspected, but this is at least another deterrent.
Kyle Rozendo
A: 

This is the "non-trivial" way, hence it's not too elegant.

The only real idea I can think of is to keep track of every link. (as in everything does a postback and then a response.redirect). In this way you could keep a static List<> or something of IP addresses(and possible browser ID and such) that say which pages are allowed to be accessed at the moment from that visitor.. along with a time out for them and such to keep them from going straight to a page 3 days from now.

I recommend rethinking your design to be sure that this is really needed though. And also note IPs and such can be spoofed.

Also if you follow this route be sure to read up about when static variables get disposed and such. You wouldn't want one of those annoying "your session has expired" messages when they have been using the site for 10 minutes.

Earlz