I am developing a mobile application using PhoneGap which will communicate with a server(PHP) via ajax requests.
On the server side(PHP)
Something like https://example.com/retrieveData.php
will get the user id via $_POST['user_id'] and return some sensitive information about the user as JSON.
And on the client side(PhoneGap-Javascript)
that JSON output will be parsed and will be used in the application.
My concern is that if someone steals this url ( https://example.com/retrieveData.php ), he can manually send fake post requests and can steal the returned user information?
How can I secure this communication?
My concern is that if someone steals this url ( https://example.com/retrieveData.php ), he can manually send fake post requests and can steal the returned user information?
You are right to be concerned. Anybody can send a message to that URL, and get the result unless you check some part of the request that authorizes the request.
For example, you could authenticate to check that the request comes from the user and then authorize the request based on the idea that the user should have access to that info.
Alternatively, you can authorize based on something that only a valid requestor would know via a shared secret and rely on the https part of that URL to prevent shared secrets from becoming public. You give out the secret to trusted partners, and when you generate a web form via PHP (also protected via HTTPS), you include a hidden input containing the shared secret. This is how XSRF protection typically works.
You should think about the following:
Who should legitimately be able to reach this page? Logged-in users interacting via your phone app, partners who can protect a secret, web API users?
What credentials do they have for using other parts of your server? Log-in cookies? XSRF tokens? Partner tokens?
What parts of your app are sent only over secure channels like https?
If all of (1) is satisfied by some subset of credentials in (2) and those credentials are only ever sent over (3) then you just need to check (2) in your page. Otherwise, you need to rework your application architecture until that is true.
OWASP has a Guide to Authorization that might come in handy and they also have a number of pages on reviewing authorization code but most of the examples are not PHP specific.
Of course he can send any post request he wants. The only possible way to get around this is with authentication that the server knows about, i.e. the client has to send you something hard to guess and that starts a session in the server.
As other answers suggests, following is the strategy to make your webapp more secure :-
The most basic rule, use secured protocol(https)
Authenticate
your user through username and password
Most of the
features/operations of your app primarily must require user to be get
authenticated.
Apart from authentication, Maintain Access Control
List for your app, which decides authorities each user role
have(Assuming that you divides your users into different roles).
Prior to performing any operation on behalf of user, check if user is
authorized to do so.
Don't rely only on client-side validation.
Perform validation at server side also.
Send csrf_tokens along
with your response, along with session cookies.
Never send any
confidential information in cookies.
Hope it helps.
Related
So I set up this login system without using any authorization headers. Instead, I just transfer data via the body of the HTTP request, confirm said data, and then grant the user access to their personal account. The idea was to create an AJAX friendly API that could be accessed on mobile.
Am I doing anything wrong by not providing authentication via the header?
I see a possible problem with this approach.
Let's imagine that you have an XSS vulnerability in your website. If you had an authentication cookie with the session id, you could just flag it as HTTP Only and attackers will not be able to grab that session id via javascript. But since you're storing that information in your HTML body, it's completely accessible by an attacker. He just needs to grab that info from the body, send it to his evil server, and done, now he can impersonate users.
If you did it like that avoid creating cookies, mainly because you'll not have cookies in a mobile native application, you should take a look at OAuth. This will allow you to authenticate your users via tokens that you'll generate, and you'll have full-control about their life-span. And now your API consumers will only need to request a token, and after that they'll only need to send that token with their requests to be authenticated (until that token expires and then, they'll need to request a new one).
I am using a token based authentication for accessing a few crude web APIs I have designed for my site. At login, the username and password are posted to the login API, and it generates a token with a unique secret key, and the key is stored on the database. At each subsequent call, the token is sent with the request and verified on the server with the secret key.
I am using a web app to consume this API service and deliver a front end to the users. The web application is designed using HTML/Bootstrap/JQuery and the backend is written on php.
I have successfully tested my app and the token based authentication works. However, I have one concern. I find that the user id and token are displayed directly, only using url encoding on the address bar of the browser.
http://hasconpanel.ckoysolutions.com/hasconpanel.php?inputs={%20%22username%22%20:%20%22Debopam%20Parua%22%20,%20%22uid%22%20:%20%2220170520193421DP%22%20,%20%22token%22%20:%20%22Sa2pHyooWPoI79vfvJzLlw7UO%252B2p5hOpBttkEq7LQ%252BjAGm9XEmxfhLAcnJoLbqrsXCp75%252BG1M7nEUoCgsDVbIQ%253D%253D%22%20,%20%22list_of_devices%22%20:%20[{%22device_code%22:%22b8:27:eb:f1:b3:0f%22,%22device_name%22:%22First-Pi%22}]%20}
Now, if this address is copied, or suppose the browser is made to resume the previous session, no matter who tries to access it, they get an entry. Especially in case of public computer centers, if anyone accesses my web app with their credentials, and forgets to logout before killing the browser, the token system seems to fail miserably. Is there anyway to secure the token like encrypting it? Or someway for the app to not store the parameters in case of a browser/browser-tab close or at least not display it on the address bar? I have thought of making a fresh token at each request, but it slows the system drastically, so I want to avoid it.
Please suggest some way to solve this problem.
Thanks in advance.
Edit:
Explaining how the system works now:
The api system is hosted on the main domain of a shared server, and the app is hosted in a sub-domain. The main domain also hosts several webservices that are being called from a few raspberry pis installed at home.
This is how it works, the login is made from the primary website and on successful login, the web app is called with a get call with the user id, the token and a list of working devices for the user. Check is provided to prevent the app page being accessed without any of these three parameters. On fresh load, the user gets the choice to select a device from a drop-down menu. Now, each of these working devices can have three separate systems running. So, on selecting the device, a get call is again being made to the app, with the selected device added as a parameter along with the three previous parameters. This shows the token and the uid on the address-bar.
Token based authentication is very standard in the web world. The details vary, but what you are trying to do certainly isn't crazy. However, your security concerns are valid, and there are a number of potential solutions:
Use HTTPS exclusively. This will protect your token from being easily readable by everyone in between the user and you. Actually, do this regardless of anything else. HTTPS should be considered the default for security purposes these days: just pretend that HTTP is deprecated.
Move the token into the header of the request instead of the URL. As long as you are using HTTPS this doesn't actually change anything from a security standpoint, but it is fairly standard for the industry. It will also keep the token out of the browser history.
It is strange that you have a URL showing up in the browser address bar. I would expect a client-side application to make requests exclusively via ajax, which means there should't ever be anything in the address bar. You might need to clarify more on how exactly this application is working. I suspect you need to refactor so that none of your application URLs ever end up in the address bar, and instead operate via AJAX requests exclusively.
Still, HTTPS is the most important part. Your entire transaction after DNS lookup will be transmitted securely, so the token cannot be stolen by a man-in-the-middle. This is the most important step you have to take to secure it. If you don't use HTTPS, you might as well broadcast it to the world. Of course, if you are making non-ajax requests to a URL with the token in the query parameters then the token will be visible in the browser's address bar and history. Again, avoid that by using ajax requests only and put the cookie in the header.
Once you have HTTPS in place with ajax-only requests, the chances of having a token stolen are much smaller. Still, it can happen (in particular via an XSS attack), so become familiar with the principle of "defense in depth". Also, there are steps you can take to try to detect a stolen token an invalidate it. Things like:
Invalidate a token (for the user to log back in) if the IP Address changes (although this can impact mobile users, which probably isn't desirable)
Invalidate a token if the user agent changes (although that can be spoofed)
Enforce a server-side maximum session length
Make sure and require the user to re-authenticate if they want to change email/password.
Those are just a few suggestions off the top of my head. Again though, this is a pretty standard problem, so google will be your friend.
I'm working on a Single-Page-Webapp (SPA) with angularjs (JavaScript) in the frontend and a php rest api in the backend.
I do a lot of ajax calls to the server for example to submit a new story. There the security question came up. The server needs to identify the request. Since it's an SPA only one client (the frontend) should be have the permission to do this request.
I've been googleing for days to find a way to identify the client. I saw that i could send a clientid in the header of the ajax call but that would not be secure since the frontend is in JS and all the JS code can be seen by the user.
Example:
$http.post("some/url", somedata, {
headers: {
"ClientId":"someidforthisclient"
}
});
a hacker could look into the JS code and copy the ClientId. With that he could make ajax calls and the server would think this request is valid.
So my question is:
How can i identfiy the client in the server but with the guarantee that the ClientId (or a security token etc.) can not be seen by the user?
How can i identfiy the client in the server but with the guarantee that the ClientId (or a security token etc.) can not be seen by the user?
You cannot. It is absolutely impossible. For all intents and purposes, as far as the server is concerned, the client application and the user of it are one entity.
You have to trust your users, not their software.
All you need to do is expose the api of login and registration to the users. For any other api access, first you need to authenticate if user is logged in/active.
For authentication you can store user credential in session :
Now user credential will be sent to the api on each request and you will be able to authenticate before processing the request.
You should at the same time encrypt user credential being saved in session so that no one can read that from browser console.
This is more of a procedure question question than a code fault one so please be kind if I have posted in the wrong place.
I have successfully authenticated a gplus user client-side so the browser is holding the google id ready for me to use. I now want to post some data to my website with that id as the user id but i want to protect it meaning I don't want just anyone with someone else's gplus id to be able to post to my web app (it has to be the authenticated user at that time).
Should I install the php serverside sdk and use that? If so how do i merge the client-side data with that?
Thanks
You're absolutely right about wanting to get the ID in a secure manner to make it hard to impersonate. There are two main options, both properties of the authResult object that comes back to the sign in callback:
Send the 'code' to the server. This is part of the OAuth 2.0 flow, and can be exchanged on the server side for an access token. From that you can make API calls as the user, and retrieve the user ID and other details. You can be confident who the user is, as only Google could have generated that code. This would involve using one of the client libraries to handle the token exchange.
Use the id_token. This is a base64 encoded blob of JSON which includes the user ID (and email address if you requested the 'email' scope). What makes it secure is that it includes a cryptographic signature, which the server can verify, so it cannot be created by someone other than Google. The id token can be used to get the user ID, and so can be used for looking up the user on the server, but doesn't give access to make API calls. The benefit is that it only requires up to date certificates for verification which don't change that often, so most calls require no further network traffic from the server to verify the user.
Which you use is up to you, but both will require some code on the server. In general, if you don't need to call any Google APIs from the server, or are concerned about maximum login performance then use the id_token. There's a bit more about that sort of architecture here: http://www.riskcompletefailure.com/2013/11/client-server-authentication-with-id.html
You can even combine the two. The first time a user signs in (when they see the consent screen) the code exchange will return not just an access token (for making calls), but also a long-lived refresh token, which you can store securely in a database. If you store that, you can use the id_token to look up the user quickly, but still use the refresh token to help with API access.
I'm writing a RESTful Webservice with the Slim Microframework and use GET for reading data from a mysql database (select query) and also POST/PUT/DELETE for insert/update/delete rows in the database.
My question is now, is this not a big security issue if everybody is able to write or delete data in the database? But how could I prevent this, I thought the ST in REST stands for state transfer (so the webservice is stateless), which is a contradiction to a state like being logged in or not. And if I would pass some login data with the client which is allowed to write in the database, couldn't a bad guy catch the logindata and fake requests with it and for example delete all entries?
So, whats the normal way to go with this, the only Slim Framework examples I had found always show the route examples, but not how to secure it.
Are there also some opportunities in the Slim Framework to implement this what I need? It should be as easy as possible and the request should be responded nearly as quick as without an authentification or similar. There are no sensitive data like passwords, for me it would be enough that not everybody with a cURL commandline tool can delete all rows or things like that.
Would be great if anybody could explain me what to do and/or give some examples. I also need to know, what I maybe will need to change at the clients which are allowed to send the requests.
Lots of thanks.
Each request has to be authenticated and authorised.
People often get tied up with the word 'stateless'. This really just means that from one request to the next, the RESTful service has no prior knowledge of the users state.
BUT, the service is obviously allowed to be aware of the authenticated user that has just made a request, else how would it decide if it should allow access?
Therefore, you can 'store' the authenticated user in some variable during each request. Then it's up to you how you use this information to authorize the request.
I like to keep it simple and have all my users as a resource in my URI chain. They make requests like users/{username}/someresource.
I authenticate using http basic authentication (over SSL) and authorise based on the URI. If the request failed authentication, its a 401 Unauthorized Request. If the URI {username} and authenticated {username} do not match, the request is a 403 forbidden. If it is authenticated and authorized, the request is allowed (http code dependant on http verb)
Now that's the web service covered, now on to the web service client. This of course HAS to store state, otherwise your user would have to log in every time they make a request.
You simply store the users session in the application (as per normal session management) with the addition that you store the username and password (encrypted of course) in the session. Now every time a request is made, your web service client needs to retrieve the username and password, and send it with the request to your web service.
It will be stateless, in the sense that there won't be a session or a cookie, really. You'd normally issue out a key that would be required for INSERT/UPDATE/DELETE.
It is then up to you to pass the key with each request and to determine when a key should expire.
It would be as safe as normal http authenticated sessions. These use a cookie etc to authenticate the connected user to the stored session state.
A stateless service would be no different - the token is passed to the service just as a token is stored in a cookie for normal http. If you are worried about sniffing (IE man in the middle attacks) you would secure the link via SSL.
The authentication token generated by the service would be encrypted and would include a salt which is also verified on the server for each request. You could also limit the session time to suit your paranoia, and also check changes in source IP, user agent etc and expire the user's token if these change.
I recently ran into similar problem. As recommended by people here, I have decided to go with OAuth Authentication.
I am using HybridAuth A php wrapper for OAuth and out of the box sign in solution for Facebook, Twitter, Google, LinkedIn, etc.