I'm currently writing an Android app at the moment, that accesses a PHP file on my server and displays JSON data provided by my MYSQL database.
Everything works great and I love the simplicity of it, but I'm not too comfortable with the fact that someone could just type in the URL of this PHP file and be presented with a page full of potentially sensitive data.
What advice would you give me to prevent access to this PHP file from anyone except those using my android app?
Thanks very much for any information.
The keyword is authentication. HTTP-Authentication is designed just for that purpose!
There are 2 forms of HTTP-auth:
Basic: easy to setup, less secure
Digest: harder to setup, more
secure
Here is the php manual.
And this is what you can do in your android app.
There isn't really a fool-proof way to do this. However you can require the user agent to match that of your application. You can also hide a private key in your application that is passed as POST data to your PHP file. Now, neither of these will stop someone who is determined to get at the raw output, but it will slow down the people who are just screwing around killing a little time seeing what they can accomplish.
Why not only enable a valid response if the request is sent with the following header:
Content-Type=application/json
If the request doesn't pass it as the Content-Type, then you just terminate the script (as regular browsers usually want to get text/html or similar things). It's not really worth locking everything tight shut, as if your app can get the data from your server, any user would have the opportunity too.
Related
I am new to the world of programming and I have learnt enough about basic CRUD-type web applications using HTML-AJAX-PHP-MySQL. I have been learning to code as a hobby and as a result have only been using a WAMP/XAMP setup (localhost). I now want to venture into using a VPS and learning to set it up and eventually open up a new project for public use.
I notice that whenever I send form data to my PHP file using AJAX or even a regular POST, if I open the Chrome debugger, and go to "Network", I can see the data being sent, and also to which backend PHP file it is sending the data to.
If a user can see this, can they intercept this data, modify it, and send it to the same backend PHP file? If they create their own simple HTML page and send the POST data to my PHP backend file, will it work?
If so, how can I avoid this? I have been reading up on using HTTPS but I am still confused. Would using HTTPS mean I would have to alter my code in any way?
The browser is obviously going to know what data it is sending, and it is going to show it in the debugger. HTTPS encrypts that data in transit and the remote server will decrypt it upon receipt; i.e. it protects against any 3rd parties in the middle being able to read or manipulate the data.
This may come as a shock to you (or perhaps not), but communication with your server happens exclusively over HTTP(S). That is a simple text protocol. Anyone can send arbitrary HTTP requests to your server at any time from anywhere. HTTPS encrypted or not. If you're concerned about somebody manipulating the data being sent through the browsers debugger tools… your concerns are entirely misdirected. There are many simpler ways to send any arbitrary crafted HTTP request to your server without even going to your site.
Your server can only rely on the data it receives and must strictly validate the given data on its own merits. Trying to lock down the client side in any way is futile.
This is even simpler than that.
Whether you are using GET or POST to transmit parameters, the HTTP request is sent to your server by the user's client, whether it's a web browser, telnet or anything else. The user can know what these POST parameters are simply because it's the user who sends them - regardless of the user's personal involvement in the process.
You are taking the problem from the wrong end.
One of the most important rules of programming is :
Never trust user entries is a basic rule of programming ! Users can and will make mistakes, and some of them will try to damage you or steal from you.
Welcome into the club.
Therefore, you must not allow your code to perform any operation that could damage you in any way if the POST or GET parameters you receive aren't what you expect, be it by mistake or from malicious intents. If your code, by the way it's designed, renders you vulnerable to harm simply by sending specific POST values to one of your pages, then your design is at fault and you should redo it taking that problematic into account.
That problematic being a major issue while designing programs, you will find plenty of documentation, tutorials and tips regarding how to prevent your code to turn against you.
Don't worry, that's not that hard to handle, and the fact that you came up with that concern by yourself show how good you are at figuring things out and how commited you are to produce good code, there is no reason why you should fail.
Feel free to post another question if you are stuck regarding a particular matter while taking on your security update.
HTTPS encrypts in-transit, so won't address this issue.
You cannot trust anything client-side. Any data sent via a webform can be set to whatever the client wants. They don't even have to intercept it. They can just modify the HTML on the page.
There is no way around this. You can, and should, do client side validation. But, since this is typically just JavaScript, it can be modified/disabled.
Therefore, you must validate all data server side when it is received. Digits should be digits, strip any backslashes or invalid special characters, etc.
Everyone can send whatever they want to your application. HTTPS just means that they can't see and manipulate what others send to your application. But you always have to work under the assumption that what is sent to your application as POST, GET, COOKIE or whatever is evil.
In HTTPS, the TLS channel is established before and HTTP data is transfered so, from that point of view, there is no difference between GET and POST requests.
It is encrypted but that is only supposed to protects against mitm attacks.
your php backend has no idea where the data it receives comes from which is why you have to assume any data it receives comes straight from a hacker.
Since you can't protect against unsavoury data being sent you have to ensure that you handle all data received safely. Some steps to take involve ensuring that any files uploaded can't be executed (i.e. if someone uploads a php file instead of an image), ensuring that data received never directly interacts with the database (i.e. https://xkcd.com/327/), & ensuring you don't trust someone just because they say they are logged in as a user.
To protect further do some research into whatever you are doing with the received post data and look up the best practices for whatever it is.
It's rare, but I have to pay MS a compliment: the ASP.NET WebMethod (AJAX) authorization is a dream, regarding my desire for security and laziness.
Encosia's ASP.NET page methods are only as secure as you make them absolutely fits those needs. ASP.NET is actually workable for me now. Free at last! (From the noble but disastrous AJAXControlToolkit).
Anyways, the problem is, that's for work. I'm not buying the MS architecture when LAMP's out there for free. I'm new to AJAX, and I can't seem to find a clear answer on how to authorize AJAX calls to PHP in the same way as Encosia above.
Can anyone suggest the PHP equivalent of what Encosia does in the link above?
Thanks in advance!
More Details
OK, let me be more specific. Encosia's solution above gives 401 denied to anyone not logged in trying to access a webmethod. Neat, clean, easy. Before, I tried to user session data to give access, but it, unknowingly to me, forced synchronous mode. Nono.
I need both, for my site. I need to be able to give 401 denieds on certain pages if a user isn't logged in. I need to be able to allow anyone to call other phps via ajax regardless of login.
Clarity
Bottom line: I don't want anyone accessing certain AJAX PHPs unless if they are logged in. I don't care what the response or any other details as long as its' still AJAX. How to?
Not really clear from the question, but if you want to only allow access to your AJAX server side listening scripts (maybe XML or JSON output) to users that have either authed or are on the related page,then how about adding a session identifier to your JS AJAX requests? In the server side script you can check that identifier against maybe a DB table holding your current sessions.
For extra security, you could check against IP, a cookie etc. These are all values that you can set when the session is started.
The main thing you need to ask yourself is this:
If a user is either logged in or browsing, what kind of access to the database do you really want / need to give? Each application will have its own needs. If you are going to have AJAX listeners on your server, then all that's needed is a quick look at Firebug (example) to see where your scripts are and the format of the requests. This could allow a potential security hole to be found. Make sure all your incoming requests are correctly treated so as to remove the possibility of injection attacks.
I am designing a website, and I really want it to be as secure as possible.
I have a private folder that cannot be accessed (.htaccess) which contains all my php classes (and similar structures), and a public folder that has my Javascript, CSS and a PHP file for the Javascript(via AJAX) to interface with, which in turn accesses the classes in the private folder.
Now here is my issue, and for the life of me I just cannot seem to get my head around this one:
If someone was to look at the js code they would see the commands / data being sent to the publicly available PHP Script (as described above), therefore getting an idea of what commands to use interface with that script and potentially gain access to stored data etc.
now I know that ajax wont work remotely etc but as long as you got the commands from the ajax script you could interface directly with it, so i thought i would do a referrer check on the interface script and that worked perfectly until I realized how easy it was to spoof your referrer header!
does anyone have any ideas on how to secure this. if this just sounds like complete garbage tell me and I'll try and break it down further.
AJAX and JS are client-based - everything they do, any user can do. If you expose an API method to AJAX, you expose it to the user - there's nothing you can do about that. That's your design choice. You could of course obfuscate your API calls, but that doesn't really do anything other than make it less user-friendly.
The bottom line: don't trust any user input, regardless of whether it came from your AJAX code or somewhere else.
Well, someone scripting your site directly would only be able to access the same stuff he already can in UI, right?
If you have an script function doAdminStuff(), you would check server side if the user is logged in AND is an admin, before taking any actions
Relax, dude.
This is SPARTA! WEB.
Every site in the world is "exposed" like this. That's the way the web works, Ajax or non-ajax based.
You can't help it, yet there is no harm in this. There is nothing to secure.
Here are my recommendations:
Use SSL if you are not already.
Use a (software) token for all requests that you want to protect.
To discourage others from reading your javascript files, you can obfuscate them. Dean Edward's packer is a famous one.
Write a script that sniffs logs and data for potentially bad activity. If you are not logging all the activity you need to (like if the apache logs are not enough) consider writing activity to your own log.
don't be paranoid, just filter input params, maybe you should switch on SSL so you ajax requests content will be hard to sniff, etc.
Are you using the ajax-thing only for security-reasons or for any other reason? Because you can build up an architecture like this (a PHP-file as "gateway" and all other PHP-files in access-restricted folder) without using ajax as well. If you want to check out, you could take a look at the default folder structure of Zend Framework. This structure has the advantage that there is no logic visible for your users at all.
Also important is that IE (at least IE 6 & 7 I think) does not send a referrer at all by default so this probably wouldn't work anyway.
I have created an iPhone application which fetches data held on a server in an XML file. How do I check that the request for the data is coming from my app and not from some other source such as another iPhone app or a desktop browser since currently you could just trace the iPhone request on your LAN with Wireshark and then use the captured URL to load the data in a desktop browser. I'm thinking I'm going to need to serve the file via PHP or something and use some sort of User Agent validation or a challenge-response sequence. If someone could provide a code sample I'd appreciate it.
Short answer: You can't. But you can indeed make it harder.
Whatever you do, it will be possible to circumvent it - user agent validation is extremely easy to circumvent; challenge-response will require disassembling of your app, but it's still possible.
However, all your nice protections won't help against network sniffing. Unless you also encrypt the transfer someone can simply sniff the plaintext data instead of breaking your "protection".
IMO the main question shouldn't be "How do I protect it" but rather "Why would somebody want to get the raw data? Why shouldn't he get it?"
I have a web application that pulls data from my newly created JSON API.
My static HTML pages dynamically calls the JSON API via JavaScript from the static HTML page.
How do I restrict access to my JSON API so that only I (my website) can call from it?
In case it helps, my API is something like: http://example.com/json/?var1=x&var2=y&var3=z... which generates the appropriate JSON based on the query.
I'm using PHP to generate my JSON results ... can restricting access to the JSON API be as simple as checking the $_SERVER['HTTP_REFERER'] to ensure that the API is only being called from my domain and not a remote user?
I think you might be misunderstanding the part where the JSON request is initiated from the user's browser rather than from your own server. The static HTML page is delivered to the user's browser, then it turns around and executes the Javascript code on the page. This code opens a new connection back to your server to obtain the JSON data. From your PHP script's point of view, the JSON request comes from somewhere in the outside world.
Given the above mechanism, there isn't much you can do to prevent anybody from calling the JSON API outside the context of your HTML page.
The usual method for restricting access to your domain is prepend the content with something that runs infinitely.
For example:
while(1);{"json": "here"} // google uses this method
for (;;);{"json": "here"} // facebook uses this method
So when you fetch this via XMLHttpRequest or any other method that is restricted solely to your domain, you know that you need to parse out the infinite loop. But if it is fetched via script node:
<script src="http://some.server/secret_api?..."></script>
It will fail because the script will never get beyond the first statement.
In my opinion, you can't restrict the access, only make it harder. It's a bit like access-restriction by obscurity. Referrers can be easily forged, and even with the short-lived key a script can get the responses by constantly refreshing the key.
So, what can we do?
Identify the weakness here:
http://www.example.com/json/getUserInfo.php?id=443
The attacker now can easily request all user info from 1 to 1.000.000 in a loop. The weak point of auto_increment IDs is their linearity and that they're easy to guess.
Solution: use non-numeric unique identifiers for your data.
http://www.example.com/json/getUserInfo.php?userid=XijjP4ow
You can't loop over those. True, you can still parse the HTML pages for keys for all kinds of keys, but this type of attack is different (and more easily avoidable) problem.
Downside: of course you can't use this method to restrict queries that aren't key-dependent, e.g. search.
Any solution here is going to be imperfect if your static pages that use the API need to be on the public Internet. Since you need to be able to have the client's browser send the request and have it be honored, it's possibly for just about anyone to see exactly how you are forming that URL.
You can have the app behind your API check the http referrer, but that is easy to fake if somebody wants to.
If it's not a requirement for the pages to be static, you could try something where you have a short-lived "key" generated by the API and included in the HTML response of the first page which gets passed along as a parameter back to the API. This would add overhead to your API though as you would have to have the server on that end maintain a list of "keys" that are valid, how long they are valid for, etc.
So, you can take some steps which won't cost a lot but aren't hard to get around if someone really wants to, or you can spend more time to make it a tiny bit harder, but there is no perfect way to do this if your API has to be publically-accessible.
The short answer is: anyone who can access the pages of your website will also be able to access your API.
You can attempt to make using your API more difficult by encrypting it in various ways, but since you'll have to include JavaScript code for decrypting the output of your API, you're just going to be setting yourself up for an arms race with anyone who decides they want to use your API through other means. Even if you use short-lived keys, a determined "attacker" could always just scrape your HTML (along with the current key) just before using the API.
If all you want to do is prevent other websites from using your API on their web pages then you could use Referrer headers but keep in mind that not all browsers send Referrers (and some proxies strip them too!). This means you'd want to allow all requests missing a referrer, and this would only give you partial protection. Also, Referrers can be easily forged, so if some other website really wants to use your API they can always just spoof a browser and access your API from their servers.
Are you, or can you use a cookie based authentication? My experience is based on ASP.NET forms authentication, but the same approach should be viable with PHP with a little code.
The basic idea is, when the user authenticates through the web app, a cookie that has an encrypted value is returned to the client browser. The json api would then use that cookie to validate the identity of the caller.
This approach obviously requires the use of cookies, so that may or may not be a problem for you.
Sorry, maybe I'm wrong but... can it be made using HTTPS?
You can (?) have your API accessible via https://example.com/json/?var1=x&var2=y, thus only authenticated consumer can get your data...
Sorry, there's no DRM on the web :-)
You can not treat HTML as a trusted client. It's a plain text script interpreted on other people's computers as they see fit. Whatever you allow your "own" JavaScript code do you allow anyone. You can't even define how long it's "yours" with Greasemonkey and Firebug in the wild.
You must duplicate all access control and business logic restrictions in the server as if none of it were present in your JavaScript client.
Include the service in your SSO, restrict the URLs each user has access to, design the service keeping wget as the client in mind, not your well behaved JavaScript code.