crwork Posted September 30, 2012 Share Posted September 30, 2012 I'm working on my first PHP REST service and have read many good tutorials online, but there are a few issues I'm having trouble with being a REST newb. Any thoughts on any of these appreciated! 1) Sending a user id securely for a GET request: The REST service is going to be invoked via jQuery AJAX and use JSON as input and output. One function we have is to retrieve some user preferences for a given user id. For testing, I've just been sending an integer user_id as part of the JSON input object. But is this not secure? Should the raw user id be sent as part of the URI request, e.g. http://testing.com/myservice/4234 ? Should encryption be used on the user id before invoking the service? 2) URL mapping: As of now I'm using the filename has part of the URL when calling the REST service from AJAX, e.g. http://testing.com/m...user_prefs.php. However, in most examples online, I see there is no filename, e.g. http://testing.com/myservice. Is the purpose for this security? The server I'm working on is lighttpd, not Apache, so it does not support .htaccess to re-route a URL. It uses the Zend framework (which I am brand new to) so I don't know if that makes it any harder or easier. Thanks for any thoughts... Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/ Share on other sites More sharing options...
Adam Posted October 1, 2012 Share Posted October 1, 2012 (edited) 1) Does the server verify the user based on their session before returning their preferences? If not, that's not secure. You won't secure it by trying to pass the ID differently or encrypting it though. Given the client-side code would need to know the encryption algorithm, and be capable of doing it, the attacker can just work out how it's done and then they can mock the request still. 2) Web services don't always map to a specific file. Quite often the request URI is parsed and routed within a framework to some form of controller. There's not really anything to gain security-wise by hiding the file extension, except letting the user know the site is PHP-based. An attacker can work that out in various other ways though. Generally extensions are only hidden to make the URLs look cleaner, which with web services aesthetics can be important. Edited October 1, 2012 by Adam Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1382145 Share on other sites More sharing options...
crwork Posted October 2, 2012 Author Share Posted October 2, 2012 Thanks Adam. Helpful stuff. The server doesn't verify the user based on session. As far as passing a user id to the web service goes, are you saying there's no great way to do that without some sort of exposure? Thanks for clarifying the URL issue. I couldn't find very much info on that so it's good to know it's not a security issue. For right now, I'd just like to get the communication working, then figure out the URL mapping issue. Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1382323 Share on other sites More sharing options...
Adam Posted October 2, 2012 Share Posted October 2, 2012 SSL encryption can be used to prevent people observing the response and request, while sensitive data is sent backwards and forwards. However that doesn't stop malicious users faking a request to gain that data anyway. There's no point trying to hide the user's ID, they're generic. You know that if you're user 123, you know at least 122 other IDs. Malicious users could simply swap the ID sent in their own request and would receive another user's details. The server should validate the user before returning anything, that's how to secure it. Just to also add about the URLs, it's easy to strip extensions with a simple RewriteRule. In the future that allows you to change the back-end implementation without having to change the web service end-points. Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1382340 Share on other sites More sharing options...
crwork Posted October 15, 2012 Author Share Posted October 15, 2012 SSL encryption can be used to prevent people observing the response and request, while sensitive data is sent backwards and forwards. However that doesn't stop malicious users faking a request to gain that data anyway. There's no point trying to hide the user's ID, they're generic. You know that if you're user 123, you know at least 122 other IDs. Malicious users could simply swap the ID sent in their own request and would receive another user's details. The server should validate the user before returning anything, that's how to secure it. Adam, just wanted to follow-up on your comment regarding security of REST services. I was reading up on security in the book "Pro PHP Security." There's an interesting chapter on REST with good code examples. However, it doesn't say much with regard to how to validate the user before returning anything. This is what I'm a bit confused on. Let's say I'm calling a REST service with userid as a POST parameter. As it stands now, the service will create a database row if the userid does not already exist, and update the row if it does. If a malicious user were to switch their userid with someone else's, how would the server know who is whom? Via session variables? If so, should a session variable be set when the user logs on to match the userid being sent to the REST service? Sorry if I'm being dense. Just want to make sure I have all my ducks in a row here... Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385346 Share on other sites More sharing options...
DavidAM Posted October 15, 2012 Share Posted October 15, 2012 ... If so, should a session variable be set when the user logs on to match the userid being sent to the REST service? Exactly! Session variables are created and stored server-side. The client has no access to them. The server sends a token (usually a cookie) that contains the session id. The client sends this back with each request. So, when the login is successful, you store the user's ID in the session. Then when a request is made, you can check the client-provided user id with the session-stored user id. Actually, there is little reason to have the client provide their own ID. Since it is stored in the session, the server already knows it. A Session ID is usually a hash or some other "random" string. So, a malicious user cannot just subtract 1 from the session id and get another valid session id. Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385385 Share on other sites More sharing options...
crwork Posted October 15, 2012 Author Share Posted October 15, 2012 Ok, that helps, but I have some confusion there. Let's take the following scenario: 1) user logs into site with email address and password 2) code retrieves the associated user id from DB (5 digit integer) and stores in a session variable Now let's stop here for a sec. Since the session variable is a hash of some sort, would the hash need to include the user ID as part of it? Or is the session variable just the 5-digit user id itself? If we compare a hashed session id of the user, how would this prevent a user from getting a REST response if the GET user id has nothing to do with the hash? I swear I'm not trying to be difficult... just trying to wrap my head around it. We thank you for your patience... Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385393 Share on other sites More sharing options...
xylex Posted October 15, 2012 Share Posted October 15, 2012 Little different direction than some of the above suggestions, but was just at this presentation that was one of the better explanations of how to properly setup a REST service and what to put where - Longer talk, but the general idea is maximize the use of what HTTP offers and architect your protocol give you long term maintainability and backwards compatibility. Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385405 Share on other sites More sharing options...
kicken Posted October 16, 2012 Share Posted October 16, 2012 Now let's stop here for a sec. Since the session variable is a hash of some sort, would the hash need to include the user ID as part of it? Or is the session variable just the 5-digit user id itself? The session varaible is just the ID, no hashing or anything like that is taking place on it. The session itself has another ID that is generated by PHP when you begin the session. This ID is what you need to ensure gets passed between the client and the server on each request. Generally this is done by setting it as a cookie (which PHP does for you typically). Using that session ID you can lookup all the data associated with it. One of the data items associated with that session would be the User ID of whoever logged in. Then you can just compare that User ID to whatever User ID is sent in the client's request to make sure they match before allowing them to do anything. As mentioned though you generally don't need to be passing around the user id at all in the service request, just pull it out of the session when it is needed. So for example if you want to have the user make updates to their profile you might send a POST request to the URI http://www.example.com/profile with the new data. In the code that handles that request you would: 1) Start the session and lookup the associated user id 2) If the user ID could not be found, deny the request with an error that they have to login first 3) If the ID does exist, run your UPDATE query using the posted data and the ID from the session. That way the end user doesn't have any means of altering the user id at all since it is managed server-side the whole time. Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385418 Share on other sites More sharing options...
crwork Posted October 16, 2012 Author Share Posted October 16, 2012 The session varaible is just the ID, no hashing or anything like that is taking place on it. The session itself has another ID that is generated by PHP when you begin the session. This ID is what you need to ensure gets passed between the client and the server on each request. Generally this is done by setting it as a cookie (which PHP does for you typically). Using that session ID you can lookup all the data associated with it. One of the data items associated with that session would be the User ID of whoever logged in. Then you can just compare that User ID to whatever User ID is sent in the client's request to make sure they match before allowing them to do anything. As mentioned though you generally don't need to be passing around the user id at all in the service request, just pull it out of the session when it is needed. So for example if you want to have the user make updates to their profile you might send a POST request to the URI http://www.example.com/profile with the new data. In the code that handles that request you would: 1) Start the session and lookup the associated user id 2) If the user ID could not be found, deny the request with an error that they have to login first 3) If the ID does exist, run your UPDATE query using the posted data and the ID from the session. That way the end user doesn't have any means of altering the user id at all since it is managed server-side the whole time. Ok, it is coming together for me. If a user logs on to the site, and session variables are built, it makes sense to use the session as input to the REST service GET process. However, if I don't pass around the userid and just use the PHP session value assigned to that userid, does that mean that I couldn't test the REST service with something external like cREST or RESTclient? As of now, with RESTClient, I'm supplying the userid as part of the URL parameter, e.g. mysite.com/user_prefs/user_prefs.php?userid=11111 to test with, then in the service loading the GET parms. Also, looking at this site code (which I've inherited) it is not setting any session variables per se. If I do a dump on $_SESSION there's nothing there. When a userID is first created, the app code sets a hashed variable it calls a "sessionid". It writes this to a cookie called "sessionid" and also updates a DB "sessionid" column for that user. Oddly, the hashed sessionid for the userid does not change in the DB with each logon. It stays the same in the DB no matter how many times you log out and log on. Is this weird or no? One question above on this statement: "Generally this is done by setting [the PHP session variable] as a cookie (which PHP does for you typically)." Do you mean that PHP does this for you if you initiate session_start? Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385638 Share on other sites More sharing options...
kicken Posted October 17, 2012 Share Posted October 17, 2012 However, if I don't pass around the userid and just use the PHP session value assigned to that userid, does that mean that I couldn't test the REST service with something external like cREST or RESTclient? All you'd need to do is be able to pass the session ID as a cookie header. I am not familiar with those tools so I do not know whether that is possible with them or not. It stays the same in the DB no matter how many times you log out and log on. Is this weird or no? It sounds like how an API Key/Access Token might be implemented more so than a Session ID. A session id is typically random and different each time. An API Key would be a random value generated one-time, and then used for all the requests. Do you mean that PHP does this for you if you initiate session_start? Yes, that is what I mean. When you call session_start() PHP will set a cookie with the current Session ID. If one hasn't already been established one will be generated for you automatically. Quote Link to comment https://forums.phpfreaks.com/topic/268945-a-few-general-php-rest-questions/#findComment-1385696 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.