Android(ios) to PHP API Security - php

I am doing a RESTful API design for android using php. Because of this, I am creating PHP API's which will go into my Database and serve specific data based on the method/function called.
but after reading some tutorials,I encounter some quetions and I can’t find a good way to solve my problem.my question is as following:
1.how can I maintain the session between my API and android.In other words,if the user login the system through android,how can I maintain the session?some use PHPSESSID and others use userid(returned by the api),which is better?
2.how can I protect my API from misuse?I find many use apikey
3.how can I protect malicious user tamper the data?this is related to my first question,if I use the userid to maintain the session between my API and android,based this,even if i use apikey, malicious user also can tamper his userid to other’s,so he will get other’s infomation .
I am stucked so much,so please help me?

I recommend you to read About HMAC authentication.
You will don't maintain the session... every request to server will send some token data in the request header.
You can work on it, thinking in ways to protect your server. The most important think is to follow the best practices and when your software are in production check your logs often.
Use the HMAC or some similar method.
You need to change your mind to don't store sessions, and follow the API best practices. I good idea are read the instagram, facebook, g+ and gdrive docs to see how they do.

Related

How to secure a php based webservice

I'm developing one android application and I'm creating a php based webservice to retrieve the information from the database.
The thing is that I really don't know how to secure this service.
For example, if my android application needs to retrieve some information from the server it will call http://mywebservice.com/service.php, and it will send several POST parameters as the user and password to login, or something like, for example, one user id to retrieve his data.
Of course, anybody with the knowledge enough will be able to retrieve that data too. And this is what I don't want to happen.
Anybody who know the parameters to send to my server will be able to retrieve information from it.
How can I secure this?
I've been reading about OAuth, OAuth2, two legged and three legged implementations of it, https..
But at the moment, I really don't know how to secure this.
I want that the webservice only answer to my application and not to anybody else.
PS: Even there is something like http://myservice.com/get_information.php that you send an id and you can retrieve a lot of information. Of course, I control that in my application, only logged and authorized people can do that calling, but it's a problem anyway. What's the best way to do this kind of things?
Some concepts to secure a webservice(might be forgetting some notions):
Protocols: HTTPS in the current case so data are not transfered in a clear format.
The Sessions: A session has a lifetime, a unique identifier(session token/id/whatever) and contains an error code. When a user will call your webservice, a session will be created and its token answered back. At every call of the webservice you'll test if the session is still alive. You can add complexity to the expected inputs, outputs and exchanges. The error_code will be used for logging(errors can come from an attack or a bug of your webservice).
Data Encryption: Use asymetric functions like password_hash() or crypt() for authentication issues. Use symetric algorithms like AES 128(10 rounds) or 256 (14 rounds) for sensitive data you'll need to retrieve.
Testing inputs: If you find yourself inserting given arguments in a query, try to prevent SQL injection. Some bad-minded people can also try to send arguments which would make your webservice fail.
Go for standards: As Çagatay said, try to implement for example oAuth2 because standard is most of the time much better than what we'll build :S
Hope it helps.
edit: The REST security sheet is good also.
Always use SSL to prevent some man-in-the-middle attack. Otherwise someone that sniffs the connection (in case of connecting via public wi-fi or company networks it's a huge risk) can see the username and password.
Do not send username and password on each request, instead implement oAuth2, your client in this case will have to send the username and password only once and then for the other requests you'll have to send only the auth key. Good documentation for implementing a oauth server: http://www.sitepoint.com/creating-a-php-oauth-server/
Look at this document: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
I ended using OAuth. More especifically this library https://bshaffer.github.io/oauth2-server-php-docs/
If you follow the instructions it's really easy to use and it works very well. I think it's a really good way to start working with OAuth.

Session integration, is this approach secure?

A user logs in using default Laravel authentication, which puts an encrypted cookie in the browser, and saves the session in the database.
The user moves to a classic asp page, where I check the cookie value, get the hash, and call the laravel app back passing the session id hash.
Then I use that in laravel to see if there's an active session for that id, and if so I return true, so the user can be logged in, in classic asp.
On each page request in the classic app, I check the last_updated_time in the db and update it on each page. All logging in and out is done in laravel, and classic relies on the database to see if a session is active.
I would also call a public url to get sessions variables and add session variables using laravel, since it's all encrypted and using classic asp for this would be hard.
The only risk I see is session highjacking, but I don't think it's a higher risk than usual.
Is it important to lockdown the laravel URL I call to check if it's a valid session?
Am I missing a security hole here?
Is this method secure?
From what you've stated you probably haven't opened up any security holes. The session cookie is not itself encrypted on the users machine, but you are making sure it is encrypted between their machines and yours, as well as between each of your machines. You should make sure you've set the Secure Flag to help prevent the cookie being accidentally sent over traditional unencrypted transport (HTTP), but as stated, this doesn't effect storing the cookie itself.
That being said, you are essentially hijacking your own users sessions. While a hole might not be introduced now, you are potentially weakening the overall system, which could lead to hole in the future.
Is there a better way to do it?
This might well be a dumb question, but are you sure you need the session? If you're juggling credentials between servers, it sounds more like you want to use Access Tokens and scrap the session.
Using Access Tokens is similar to using sessions, but you need to make your services stateless. This means your no longer storing information about the logged in user any specific machine so you'll need to pull anything you need from the database every time they hit a server requiring that information.
This is a good thing in the long run as it's much easier to scale your services when you don't need to worry so much about where the session is and what's inside it.
OAuth 2.0 is widely used standard (Facebook, Twitter, Google), and was specifically designed to be easy to use. The RFC is complex, but there's a log of good guides out there don't worry.
The one slight down side (if you can call it that) to OAuth 2, is that it MUST happen over an encrypted connection. If your use case can not guarantee encryption over SSL or (preferably) TLS, then you should use OAuth 1.0 (WITH revision A) instead.
This is due to the fact that OAuth 2.0 exposes it's "secret" token in requests, where as OAuth 1.0 only ever uses it to provide a signature hash. If you take this route it's advisable to use someone else's library as the hash is very, specific.
Further Improvement
(Note: This section added after the answer was accepted)
One system I've been exploring recently is Json Web Tokens. These store information about the user to save each machine repeatedly looking it up in a database. Because the token is hashed with a secret, you can be sure that, so long as your secret isn't exposed, a valid token represents a successfully logged in user, without having to touch the database.
You should avoid putting anything too personal in the tokens if possible. If you must store private or secret information in the token, you can encrypt it, or you can use a reverse caching proxy to exchange the JWT for a traditional security token. This may initially seem to defeat the purpose, but it means some of your services may not need database access at all.
I'm no security expert but I don't see an issue with this. The packaged Laravel database session handler works the same way. The cookie contains a hash that references a record in the database. The session data is base64 encoded but that's neither here nor there. I think you could actually avoid rolling your own and just use Laravel's DatabaseSessionHandler.
Illuminate/Session/DatabaseSessionHandler
... I just read a little deeper into your question and noticed the part about the public URL to set and retrieve session data. I think this is a really bad idea. Mostly because it will provide an open door to the end user allowing them to read and write session data. This can only end badly.
Like I said above, the data is only base64 encoded so I believe you'll be able to parse, read and write that to your hearts content within asp.
Edit
Ok... I think this is the last edit. The data is php serialized and then base64 encoded. This question looks like it may help you to that end. If it doesn't and an API endpoint is the only way, find some way to block the end user from accessing it.
Aside from session-hijacking, no. This is the standard way applications interact on a internal basis. Of course there might be a better way to get at the data if you choose a different type of session store other than your database, Memcached for instance.
There are couple of things that can be done.
Make the channel HTTPS. It will make almost impossible to sniff on your transport layer.
Rather than making interactions with your cookie, you could use a JWT to get this task done. Which will help you to use the existing functionality in your system while connecting with ASP system as well. You can write a small REST web service which allows ASP to connect. You could use this lib. You can refer this article which will give you an idea how it should be done.
Please let me know if you need more information.

PHP cookies and member security

I've created a forum which uses a PHP session when logged in to determine the user id, and cookies for log-term login.
I suppose I have two questions:
Is this the best/securest method?
Cookies can be added manually via the address bar with javascript, which is a huge security risk. Is there any way around this?
Thanks!
First, make sure you are using https and not http. This will keep your traffic from getting sniffed and exploited.
Secondly, generate as random a value as possible to use as a token in the cookie. This is how many of the big sites do their user tracking. Have a map of token to user on the server side that tracks the identities. Remember: Anything that comes from the client is untrusted and could be tampered with.
Third, use an HMAC to make tampering much more difficult. You don't want users being able to brute force other tokens.
EDIT:
You may find these other SO questions/answers helpful as you build this system:
Long details about creating and using tokens (doesn't necessarily have to be a REST service to be applicable): REST Web Service authentication token implementation
Creating good tokens (don't use microtime): Is using microtime() to generate password-reset tokens bad practice

Logging in users with CodeIgniter

I have written the registration page in my CodeIgniter application. Everything works fine, and it's using the PHPass library for password hashing.
Now, I want to write the login part of the system, and was wondering how exactly I'd go about doing this with CodeIgniter. I'm mostly confused about the correct (and best practice) way of doing it. Do I just accept the users login credentials, determine if they're correct and if so, set up a session for that user? Do they need a cookie? Does that cookie need to be encrypted? Do I need to track the user in my database (CodeIgniter can do this for me) and watch for IP address changes or hostname changes?
There are many many auth libraries but since you are a beginner I strongly believe that it's better to make something on your own (unless you are on a very strict time frame). Because, as my colleague once told me, without making a mistake you won't understand why better solution is actually better.
Back to your actual question.
Do I just accept the users login credentials, determine if they're correct and if so, set up a session for that user?
Well, yes. There is no other reasonable way to do it, is there? :)
Do they need a cookie?
Session ID is stored automatically in a cookie. You can store other options in a cookie, but have in mind that cookies can be stolen (so it's NOT a good idea to save username/cookie). Plus people use more than one device (e.g. tablet and desktop) more and more so be sensible about using cookies.
Does that cookie need to be encrypted?
I believe I answered that already.
You should probably start here with this: http://codeigniter.com/wiki/Category:Libraries::Authentication and http://codeigniter.com/wiki/Category:Libraries::Authorization
From CI Wiki: Authentication is different from Authorization.
Authentication answers the question “is this user who they claim to
be?” Authorization answers the question “given this user, are they
authorized to perform this action?”
Why don't you use one of the many CI auth libraries?
How should I choose an authentication library for CodeIgniter?
You can just have a look at the CI wiki for all the particular details you are after:
http://codeigniter.com/wiki/auth

How do I authenticate users with a site API?

I want to build an API for users to build applications that easily interact with a site, and I was wondering what the best way to authenticate users would be.
Taking a look at other API's a lot of them have the user send the username and password as a GET parameter over a HTTPS connection. Is this the best way to go about it? Or are there other methods that I should look into or consider?
I've seen OAuth been tossed around and it looks like a good solution, but just for a simple API is it overkill?
You can use API key's. Generate a unique hash tied to an account upon request. Then check that the key is a valid key. As long as the API doesn't have any major security issues with someone using someone else's key then Authorization isn't needed. If there is a problem with someone using someone else's key then Authentication would be justified.
This is usually achieved with cookies.
The client sends their username and password with a POST request to your API (do not use GET, that's insecure). If the credentials are acceptable, then generate a random, unique session key, store it on your side and send it in a cookie back to the client (see setcookie()).
When the client now makes further requests, they send the session key cookie with the request. Check $_COOKIE for the session key if it matches a stored key on your side; if yes, that means the user authenticated.
Take note that this minimal example is vulnerable to brute-force attacks trying to guess valid session keys. You need to log invalid keys that clients send in their cookies and block their IP address for some period of time to prevent this.
Username / password in a GET isn't a great way to do this because you're potentially exposing the whole user account for hijacking even if the API has more limited functionality than logging into the site. So it's good practice to separate concerns between Web-site login and API access.
I'm not sure which case you're in but:
If the users are business customers of somekind who are embedding some type of widget or code in another website then it's probably best to use an API key which is scoped to the referrer domain (much like Google Maps does).
If they are end-users who won't know anything about the API but are going to be using Apps built by third parties then oAuth is likely to be your best bet, otherwise your users might literally be giving their usernames/passwords to unknown third parties. It's more complex but likely to be worth it in the long run.
To get a bunch of this stuff out of the box you can use something like 3scale (http://www.3scale.net) and it'll handle most of it for you (disclaimer, I work there so adjust for bias!) or there are open source libraries for oAuth in most languages (in PHP Zend-OAuth component might do the job for you).

Categories