I'm making a PHP app to allow our customers to retrieve information from our database, using pre-defined functions. Perhaps PHP isn't the best choice for this, but the same page is also used as a backend for a flash app, and we don't have the time to rewrite it in another language (still, if we did have that time, I'm open to suggestions).
They will access the page via a URL, something like:
http://myurl.com/test.php?function=getUser&username=John
This will call the function getUser($username) and pass the value John as the $username parameter. Here's the twist: this page will be called from an application that the customer creates, not from a browser.
They are allowed to get info about some users, but not others. To enforce this, I require them to provide login information. I'm not sure how I can keep that user logged in so that they don't have to pass their login information every time they call a function, which can be multiple times per second.
I don't think I can use sessions or cookies, since they are not calling the page from a browser. So how can I keep that user logged in?
You can look into setting up something like a SOAP API on your end. Then, you can provide them with a token that goes back and forth (and possibly changes) between each request they make.
Have a read over SOAP and see if it gives you any inspiration at the very least. As far as implementing it, your options are many. Maybe consider using a framework?
You've hit the stateless wall :D .
You will either need to create a session aware browser client object with some library or some token exchange. But as long as you are using a separate session between calls you will need to hit the database again to authorize the user; token or not.
Simple answer: You can't, since HTTP is stateless.
But: You can use the same principle as cookies do, which is "send some authentification info along with the request without transmitting the secret". Have a look into OAuth and if it fits into your scenario. You can even use ready-made libraries for PHP.
Related
I want to use post to update a database and don't want people doing it manually, i.e., it should only be possible through AJAX in a client. Is there some well known cryptographic trick to use in this scenario?
Say I'm issuing a GET request to insert a new user into my database at site.com/adduser/<userid>. Someone could overpopulate my database by issuing fake requests.
There is no way to avoid forged requests in this case, as the client browser already has everything necessary to make the request; it is only a matter of some debugging for a malicious user to figure out how to make arbitrary requests to your backend, and probably even using your own code to make it easier. You don't need "cryptographic tricks", you need only obfuscation, and that will only make forging a bit inconvenient, but still not impossible.
It can be achieved.
Whenever you render a page which is supposed to make such request. Generate a random token and store it in session (for authenticated user) or database (in case this request is publicly allowed).
and instead of calling site.com/adduser/<userid> call site.com/adduser/<userid>/<token>
whenever you receive such request if the token is valid or not (from session or database)
In case token is correct, process the request and remove used token from session / db
In case token is incorrect, reject the request.
I don't really need to restrict access to the server (although that would be great), I'm looking for a cryptographic trick that would allow the server to know when things are coming from the app and not forged by the user using a sniffed token.
You cannot do this. It's almost one of the fundamental problems with client/server applications. Here's why it doesn't work: Say you had a way for your client app to authenticate itself to the server - whether it's a secret password or some other method. The information that the app needs is necessarily accessible to the app (the password is hidden in there somewhere, or whatever). But because it runs on the user's computer, that means they also have access to this information: All they need is to look at the source, or the binary, or the network traffic between your app and the server, and eventually they will figure out the mechanism by which your app authenticates, and replicate it. Maybe they'll even copy it. Maybe they'll write a clever hack to make your app do the heavy lifting (You can always just send fake user input to the app). But no matter how, they've got all the information required, and there is no way to stop them from having it that wouldn't also stop your app from having it.
Prevent Direct Access To File Called By ajax Function seems to address the question.
You can (among other solutions, I'm sure)...
use session management (log in to create a session);
send a unique key to the client which needs to be returned before it expires (can't
be re-used, and can't be stored for use later on);
and/or set headers as in the linked answer.
But anything can be spoofed if people try hard enough. The only completely secure system is one which no-one can access at all.
This is the same problem as CSRF - and the solution is the same: use a token in the AJAX request which you've perviously stored eslewhere (or can regenerate, e.g. by encrypting the parameters using the sessin id as a key). Chriss Shiflett has some sensible notes on this, and there's an OWASP project for detecting CSRF with PHP
This is some authorization issue: only authorized requests should result in the creation of a new user. So when receiving such a request, your sever needs to check whether it’s from a client that is authorized to create new users.
Now the main issue is how to decide what request is authorized. In most cases, this is done via user roles and/or some ticketing system. With user roles, you’ll have additional problems to solve like user identification and user authentication. But if that is already solved, you can easily map the users onto roles like Alice is an admin and Bob is a regular user and only admins are authorized to create new users.
It works like any other web page: login authentication, check the referrer.
The solution is adding the bold line to ajax requests. Also you should look to basic authentication, this will not be the only protector. You can catch the incomes with these code from your ajax page
Ajax Call
function callit()
{
if(window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();}else{xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}
xmlhttp.onreadystatechange=function(){if(xmlhttp.readyState==4&&xmlhttp.status==200){document.getElementById('alp').innerHTML=xmlhttp.responseText;}}
xmlhttp.open("get", "call.asp", true);
**xmlhttp.setRequestHeader("X-Requested-With","XMLHttpRequest");**
xmlhttp.send();
}
PHP/ASP Requested Page Answer
ASP
If Request.ServerVariables("HTTP_X-Requested-With") = "XMLHttpRequest" Then
'Do stuff
Else
'Kill it
End If
PHP
if( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ) )
{
//Do stuff
} else {
//Kill it
}
I have a file, caller.php, which takes a GET URI that specifies a value to search the database for. The data is then returned in JSON format using php.
I want to protect caller.php so that it is only accessible from another page, get.php, using an AJAX call.
What is the best way to go about this?
I want to protect caller.php so that it is only accessible from another page, get.php, using an AJAX call.
You can't. An AJAX call can be easily faked, as can its origin.
There is no reliable way for you on server side to tell whether a call is an Ajax one or not, nor where it came from.
You need to secure your Ajax resource the same way you would secure a normal page - e.g. through an authorization system like a user login, etcetera.
Without such an authorization system in place, you have to assume that everyone can access the URL.
You could check the session to see if the call is authorized or not. AJAX requests will send you the PHP session cookie. This assumes that caller.php is secured by some kind of user login system that uses sessions
From a security standpoint, can someone give me a step-by-step (but very simple) path to securing an ajax call when logged in to PHP?
Example:
on the php page, there is a session id given to the logged in user.
the session id is placed dynamically into the javascript before pushing the page to the client.
the client clicks a "submit" button which sends the data (including the session id) back to the php processing page.
the php processing page confirms the session id, performs the task, and sends back data
I'm stuck on how (and whether) the session data should be secured before sending it through an ajax request. I'm not building a bank here, but i'm concerned about so many ajax calls going to "open-ended" php pages that can just accept requests from anywhere (given that sources can be spoofed).
PHP can get the session data without you having to send a session ID via javascript. Just use the $_SESSION variable. If you want to check if a session exists you can just do
if(isset($_SESSION['some_val'))
//do work son.
You'll need to use JavaScript to asynchronously pass user input back to the server, but not to keep track of a session.
Don't send your session data with javascript.
You don't need to (in most cases).
Just post the data with javascript and let PHP retrieve the session data from... the session.
Depends on how you setup your session data.
One simple example would be you have a session called username.
When PHP gets the request from javascript you can do: $_SESSION['username'] to retrieve the sessiondata.
This is a very simple example just to show how it can be done.
As noted above, you don't need to send any session identifiers out with your javascript, to the server an AJAX request is the same as any other request and it will know your session just fine. So basically, just don't worry about it, it's already taken care of.
It's another part of your question that worries me.
i'm concerned about so many ajax calls going to "open-ended" php pages that can just accept requests from anywhere
It worries me too; you shouldn't have any "open-ended" PHP pages hanging around at all. Every public .php script should have authentication and authorisation done. The easiest and most maintainable way to achieve this, IMHO, is to have a single controller script (e.g. index.php) that does authentication and authorisation then sends the request to an appropriate controller. Aside from this controller, all other scripts should be outside the document root so that they cannot be called directly.
This means that you only ever have to worry about authentication and authorisation in one place; if you need to change it, it only changes in one place. It means you don't need to worry about accidentally leaving some executable stuff in some library PHP file that's not meant to be called directly. It means you don't need to shag around with mod_rewrite rules trying to protect .php files that shouldn't be in the doc root at all.
Almost everything is in the title :
Here's what I'd like to do :
A nice html page with a php authentication process (http first then https & so on)
Launch a flex app which knows (I don't know how (this is the actual question !)) the user has already been authenticated and display his/her stuff he/she has to do for the day (or whatever...).
Of course if someone try to call directly the flex app I would display an "authentication error" message and then redirect to the authentication page.
I'm sorry for my English which is perfectible.
I was thinking about the session cookie : first authenticate then ass a variable on the server side, something like :
$_SESSION['authenticate']=true
Then, on the flex side, just send the cookie and ask if the user is properly authenticated, something like calling a php web page like :
https://is_authenticated.php?php_session=xxxx
Thank you
Olivier
What are you using on the server side? Remember that you shouldn't do anything in the flex application other then send the SESSION ID along with any requests. Any time where the client checks security, you have a bug. The server must validate the session and determine if the request is allowed.
It sounded in your last comment that you are worried about people manually calling a web page. Each page must check to see if the user is authenticated. I don't know your specific application, but you may try looking at AMFPHP and see how they do session authentication. Good luck!
Your on the right track!
You could use session-authentication, these links might help you out:
http://www.zend.com/zend/spotlight/sessionauth7may.php
http://www.tizag.com/phpT/phpsessions.php
There is also the possibility to use http-authentication
http://se2.php.net/features.http-auth
however http-authentication is not as flexible as session-authentication, and also means some more configuration on the serverside.I would therefore recommend you to stick with sessions.
This is exactly what I would do.. A few things to consider from a security standpoint:
If your php service (from flex) gets an unknown session token, always generate a new one. This also applies to your PHP application and is often overlooked.
I would generate the swf with javascript, and manually insert the session cookie using javascript. This way people won't download and safe (or cache) your php pages with sessions that are invalid in the future.
Even better would be to use a separate token other than the session, and on the server figure out what the session id was based on this flex token.
I am using a simple Zend_Auth setup to authenticate users for one of my applications, using a check in the preDispatch() method in a controller plugin. When anonymous users navigate to
/users/view/id/6
for example, they should be redirected to the above URI after authentication.
What is the best way to do this? I'd prefer not to store $_SERVER['REQUEST_URI'] in the session. Personally, I'd find storing the entire Zend Request object to cleanest solution, but I am not sure if this is sensible and if this is the approach I should be taking.
Any thoughts?
Well redirecting or forwarding to the LoginController might not be the optimal way to bring an un-authenticated user to the login page. Instead at preDispatch you can grab the $request object and alter it by doing the following.
$request->setActionName('someaction');
$request->setControllerName('somecontroller');
At this point your original request in maintained yet the page is displaying the login page. Then you can alter your login controller to check to see if the current request location is the login controller or if it something else. If it is something else (the original request) on a successful login send them to that page.
We had the same problem and actually did store request URI in session variable.
If you don't put any specific, unserializable object into Zend Request, I think it also will be ok to persist it.
However it depends on what throughput you're expecting. Serializing objects like Zend Request may not be the best idea if you have a high traffic website.