Monday, March 26, 2012

PageMethods static, ASMX and security

Hi,

I just tried out the PageMethods approach and at first, i got this weird "PageMethods not defined", then I found out that's because my codebhind method needs to be static. Why is that? Should I use asmx instead cuz i just feel weird to declare static methods everywhere in my codebehind.

If i use asmx for my ajax methods.. what if people start to hit my asmx directly outside of my website? I want to prevent ppl from directly accessing my webmethods. (I'm not that good with webservcies, but my understanding it of it is any .asmx page is accessible to the public?)

Please give me some of your insight into this matter. Thanks a lot.

Hi,

I'm not sure about what I'm going to say but it seems you can use Sessions to verify that a user is authenticated on your web site. By adding the EnableSession attribute to a WebMethod, you can access all the session data like in a normal aspx page. I tried that with an AutoCompleteExtender and a WebMethod, and the WebMethod doesn't return anything if the user isn't authenticated.

Hope this helps.

Laurent


Hi Laurent,

That's some good information. Do you know how can I enable the default membership authentication with it? like some types of attribute [authenticated=true] type of things?
Thanks a lot. That clears up some of my confusion.

There's no attribute for that that I'm aware of, but doing something like:

[WebMethod(EnableSession=true)]
public string HandsOffMyStuff()
{
if(!User.IsAuthenticated)
throw new Exception("hands off, jerky!");

/// Do cool stuff
}

will solve your issue for you.


Ah, coolbeans. thanks a lot. Strange that this wasn't documented anywhere, i'd imagine by NOT doing this, most of the ajax implementation are exposing themselves unnecessarily. Security aside, your bandwidth is exposed for usage. hm..

I just read by decorating <scriptservice> attribute will solve security issue, but I wasn't sure what they are talking about exactly. I'll have to test it out quickly.

Here is a blog talking about it.

http://portal.spidynamics.com/blogs/developersecurity/archive/2006/10/31/Web-service-security-improvement-in-ASP.NET-AJAX-beta-1.aspx

not much explaination.

Thanks though, I'll go with User.IsAuthenticated and EnableSession check


I don't believe you need "the EnableSession=true".

This is just regular ASP.NET authentication. .asmx files, just like .aspx files or .html files, are public to the world by default unless you restrict access via authentication. That's probably why you didn't find any ASP.NET AJAX-specific documentation about this.

The blog post you pointed to was just saying that in early prerelease versions of "Atlas", all the web services in your project became accessible to script, but now you need to put a [ScriptService] attribute on the ones you want to call from script, and the rest are only callable via SOAP. This is basically an attack surface reduction.


That depends on how you're doing authentication, though. If you're doing Forms authentication, for example, you don't want to put your web services in a restricted folder, b/c the redirect to login page is not desireable behavior w/ a web service. So instead what you can do is leave it in an 'open' folder but then check authentication on the Session object as described above.


okay. just to clarify, what happens if it's a public site which allows anonymous access, and all i want to do is grant access to the asmx services from javscript calls WITHIN my own website (by decorating it with <scriptservices> attribute right? Because I don't want anybody excpet me to use my backend service.

Deos this prevents other people from referencing my web services?, u know, visual studio->add web reference? (again, I've only done limited amount of work on webservices, such asking these questions...) I'll have to do some tests to clarify all these.

Fundamentally, if you allow unauthenticated users to access your web services from the browser, you can't prevent them from doing so from some other application. Even if you disable the SOAP protocols on your web service, someone could still write their own code to use JSON to talk to your service, or even simpler, they could do a File/Save As... in the browser to download a copy of your web page and just load it in the browser (possibly changing it to call your web service 30 times a second).


hm..ic and that's what i'm worried about... espeically some of my asmx services accepts input data (write to database) like membership regirstration...(good thing that I used an email confirmation mechnism and password is generated randomly on the backend) this way, i can prevent myself from spammers.

Okay... I'll have to research some more on this before I launch my public ajax enabled website, i just need to make myself comfortable first..

Thanks a lot guys.

Okay, just to follow up on my own thread... i did a few tests.

1. calling local ajax webservices from javascript within my own website.

With [ScriptServices] attribute, my javascript is able to call the webmethods of the .asmx file. [Success]
Without [ScriptServices], it fails. [Failed]

Remote Ajax .asmx services WITHOUT forms authentication
-----------------------------
2. calling a remote ajax .asmx services from my javascript (without forms authentication) [To Test]

3. calling a remote ajax .asmx services from my codebehind (without forms authentication) [Success]

Remote Ajax .asmx services WITH forms authentication
---------------------------
4. calling a remote ajax .asmx services from my javascript (with forms authentication) [To Test]

5. calling a remote ajax .asmx services from my codebehind (with forms authentication) [Failed]

So it confirms what everyone said above. By looking at #5 and #3), my conclusion this far is, if we have forms authentication enabled, my webservices is safe. But if my site allows anonymous access, such as a public site, we need to be careful.

For example, my public site's member registration page use an ajax method to register a new member of my website. By having this ajax method available, I'm able to call the method from another site, and automatically register new members. It's dangerous because if I loop 1000 times, I'm able to create 1000 members. This is an invite for spammers. If you go through my web page, at least I can prevent spammers by using CAPCHA image or whatever, through webservices, there is no protection from direct access.

Again, it's a good thing that I created users based on email confirmation.. but still, remote direct access will leave a lot of temporary data in my database.

So now, I will remove all "Write" ajax methods from my public website, at least I can prevent useless data. But my "read" .asmx servcies methods of the public site are still all open to everyone, everybody can call my webservices whenever they want from within their own application. I can see it'll cause unnecessary bandwidth.... then again, spammer could simply hit my webpages and it'll eat up my monthly bandwidth as well. Just feel like I opened up another door for them that's all.

*headache*


Oh yeah, another way is to use PageMethods.. this looks safe from remote access, but the question remains... if i have 100 ajax methods, they are all static, twhat's the "cost" on my webserver? 100 static methods for ajax??

Hi!

I think you are a bit pessimistic on this matter. Even on a public website, you have access to a user context, which includes a session. This way, there's always a workaround, like initiating a session object in your MasterPage and looking for this object in all your webmethods. I think that would prevent from most of the possible attacks, because a malicious user would have to create a much more complex program than including a web reference.

Anyway, this same malicious user would always be able to call your web service, even if the call fail. It's like downloading an image, by default it's always possible if you know the address. If your webmethods send data which cost a lot of bandwidth, you can create a monitoring system, which will verify that a same user doesn't call your webservice more than x times a second/minute, but that would be quite heavy...

Hope this helps,

Laurent

No comments:

Post a Comment