views:

88

answers:

2

My iPhone app accesses a server through a REST-ish API. I use sessions that are linked to the client's IP address in order to help prevent session hijacking. But I've noticed some strange sequences of requests in my server logs from certain client devices. What happens is different URLs on my server are being requested by the same client from different IP addresses. A typical sequence looks something like this:

ipaddr1: POST /users/foo/login -- grants a session linked to ipaddr1
ipaddr2: GET /users/foo/resource -- 401 Not Authorized (IP address mismatch in session)
ipaddr1: POST /users/foo/login -- grants a session linked to ipaddr1
ipaddr2: GET /users/foo/resource -- 401 Not Authorized (IP address mismatch in session)
ipaddr1: POST /users/foo/login -- grants a session linked to ipaddr1
ipaddr2: GET /users/foo/resource -- 401 Not Authorized (IP address mismatch in session)
...

and so on, where these requests are coming in about 3 seconds apart. Sometimes there are even up to 4 ip addresses in play at once!

On the client side I'm just using a normal NSURLConnection to request each resource, so I don't think it's anything I'm doing in my code.

Has anybody seen anything like this before? Could it be some kind of weird proxying thing?

+1  A: 

You can't expect requests to come from the same IP address. The iPhone can cycle through sending requests via a number of WiFi networks, 3G, EDGE and GPRS. If session highjacking is an issue, use SSL.

That being said, the behaviour you are seeing is not typical; the iPhone should only switch off of WiFi onto 3G if the WiFi network goes down (and the same for 3G vs EDGE and EDGE vs GPRS)

rpetrich
Thanks for the response. I don't expect requests to come from the same IP address, and the app does handle simple IP address changes gracefully. What it can't handle is multiple simultaneous IP addresses.
n8gray
+2  A: 

I was under the impression that most networks used simple NAT; proxying has gone out of fashion since most data can't be cached anymore (our university is in the process of turning off its proxy; last I checked they turned off caching because most bandwidth is for stuff like YouTube anyway).

On the other hand, a couple of years ago it was still fairly commonplace for mobile networks to use "transcoding" proxies (see "Cache-Control: no-transform"). This exists solely to increase mobile internet usage on devices with crap browsers, which otherwise couldn't render "popular" sites. A while back, I tested HTTPS over various operators and found one where an HTTP CONNECT set up some sort of NAT (presumably to reduce proxying overheads), but did it in a broken way such that the connection wasn't established. Disabling proxying made things work.

Perhaps it's a proxy which uses one box for GETs and another for POSTs? Or it hashes the request/connection endpoints/etc to find out which IP to send it from?

If you want to find out what's going on, try contacting the users involved, or do a whois lookup on the IPs involved.


In general, it's unadvisable to tie sessions to IPs. I know a few sites do (Atlassian Crowd "SSO" tokens are supposedly bound to IP addresses); the better ones make it an option (Livejournal comes to mind). The best ones just use HTTPS.

HTTPS additionally stops attackers from stealing users' passwords (and users will reuse passwords, so even if your site isn't security-critical, you should never transmit passwords unencrypted.

I'd just switch to HTTPS entirely; it's not difficult, and SSL certificates aren't expensive (StartCom's free "StartSSL" certs might be sufficient for your purposes).

If HTTPS is really too much work, assuming you're using custom session-management code, it's not too difficult to return a random MAC key on login and sign future requests using the key (and a sequence number to prevent replays). There are still real-time eavesdropping and MITM attacks.

If you're using HTTPS for login but not other requests, then the problem is likely that HTTP is proxied but HTTPS isn't (since proxying doesn't benefit HTTPS at all).

tc.
It's true that login happens over HTTPS and other requests go over HTTP. Your last paragraph sounds quite plausible as the cause of the problem.I could perhaps switch to HTTPS completely, but my service is just a casual game and passwords are already handled pretty securely AFAIK. (Required to include punctuation, never sent in the clear, stored as salted hashes.) Even linking the IP address to the session was more of a "sure, why not" kind of defense than a response to any real anticipated threat. I'll probably just disable that aspect of session validation.Thanks for the response.
n8gray
HTTPS costs approximately nothing — if you're already using HTTPS for session startup, then there's a connection waiting to be reused. In the EU, it's also a good idea if you're worried about complying with various "data protection" laws (e.g. if you ask for someone's "real name").
tc.