views:

7425

answers:

6

Background:

I'm designing the authentication scheme for a REST web service. This doesn't "really" need to be secure (it's more of a personal project) but I want to make it as secure as possible as an exercise/learning experience. I don't want to use SSL since I don't want the hassle and, mostly, the expense of setting it up.

These SO questions were especially useful to get me started:

I'm thinking of using a simplified version of Amazon S3's authentication (I like OAuth but it seems too complicated for my needs). I'm adding a randomly generated nonce, supplied by the server, to the request, to prevent replay attacks.

To get to the question:

Both S3 and OAuth rely on signing the request URL along with a few selected headers. Neither of them sign the request body for POST or PUT requests. Isn't this vulnerable to a man-in-the-middle attack, which keeps the url and headers and replaces the request body with any data the attacker wants?

It seems like I can guard against this by including a hash of the request body in the string that gets signed. Is this secure?

A: 

Remember that your suggestions makes it difficult for clients to communicate with the server. They need to understand your innovative solution and encrypt the data accordingly, this model is not so good for public API (unless you are amazon\yahoo\google..).

Anyways, if you must encrypt the body content I would suggest you to check out existing standards and solutions like:

XML encryption (W3C standard)

XML Security

LiorH
+1  A: 

If you require the hash of the body as one of the parameters in the URL and that URL is signed via a private key, then a man-in-the-middle attack would only be able to replace the body with content that would generate the same hash. Easy to do with MD5 hash values now at least and when SHA-1 is broken, well, you get the picture.

To secure the body from tampering, you would need to require a signature of the body, which a man-in-the-middle attack would be less likely to be able to break since they wouldn't know the private key that generates the signature.

ZaDDaZ
+1  A: 

Or you could use the known solution to this problem and use SSL. Self-signed certs are free and its a personal project right?

wowest
Self-signed certs are free, but AFAIK you still need a static IP.
dF
+3  A: 

REST means working with the standards of the web, and the standard for "secure" transfer on the web is SSL. Anything else is going to be kind of funky and require extra deployment effort for clients, which will have to have encryption libraries available.

mahemoff
After thinking about this for a while and implementing a first version, I tend to agree....
dF
You could get a GoDaddy ssl certificate for like $30 a year I think. I was shocked to see how much the Verisign SSL certs go for ($600 a year or something if I remember correctly?) But the GoDaddy option is perfectly feasible.
Brian Armstrong
A: 

Seems all like a lot of work, why don't you just use the ASP.NET Membership to secure it? Just add something like the following for each entity, to allow or deny access to it.

[QueryInterceptor("adonet_entity")]
public Expression<Func<adonet_entity, bool>> FilterSecurityOfEntity()
{
    MembershipUser user = Membership.GetUser();
    Guid userGuid = (Guid)user.ProviderUserKey;
    return (c => c.UserId == userGuid);
}

For example, if the user == null, you could also just adjust the query to give back nothing.

erik
I guess I should have mentioned it, but I'm not using ASP.NET or even Windows (Python on mac/unix)
dF