Is it possible to have a secure piece of Javascript code in a web application? By secure I mean that we can do things like query the server for permissions, and do operations that cannot be altered by the client?
Example:
var flag = 0;
$.ajax({
async: false,
url: "/check_permission_script.php",
success: function(data){
flag = parseInt(data);
}
});
if (flag != 1){
display_normal_content();
}else{
display_secure_content();
}
Here I want to make a query to the server to check if the user has permission to see the secure content. If they have the permissions, then we use display_secure_content() to show them the secure content, if not, we use display_normal_content() to display normal content. The problem is, that via a debugging terminal, it is easy to set the flag variable == 1 on the client computer, or just call the display_secure_content() function directly.
My motivation for doing things this way is to have nice web app that uses ajax to get new content, without having to reload the page. I like this instead of having to reload the page.
So the question is, can we have JS scripts that are secure against client manipulation? Or is this simply impossible by the nature of the web infrastructure?
Thanks!!
By the very nature of JavaScript, this is not possible.
Anything you want to not be seen by the client cannot be sent to the client at all. All authentication/authorization should happen server-side.
You can still use AJAX for loading data in your interface, but make sure the checks are in place server-side to keep sensitive data from leaking out.
Short answer, no - not with JavaScript alone. JavaScript executes on the client-side, so anything you put in it is accessible and by extension modifiable by the client.
Several tools exist to help with "security through obscurity" such as obfuscating the code, but this will not help you for your end goal.
What could help, given your current setup, is through Ajax you contact a server-side PHP page that handles all security/validation and returns what content to display. Doing this, the client-facing JavaScript only has the ability to "request", not to validate or choose what to display.
You could query the session id against your internal database and return a secure public/private key encrypted token which contains a key for decrypting a blob of data. Then use this as a parameter of the javascript function, which uses this returned key to decrypt the blob.
This solution does not require reloading the page, and whilst it works in theory, you would have to return the page with the secure content encrypted with a different key each time. I wouldn't recommend actually trying this.
The server should know what the user can and can not see. If the flag is changed on the client, the server should not trust it, it should do a validation when it gets the request. Security 101 stuff
JavaScript is a client side scripting language. It's meant to be this way.
If you need a secure script, use PHP.
Related
I asked a similar question before, and the answer was simply:
if JavaScript can do it, then any client can do it.
But I still want to find out a way do restrict AJAX calls to JavaScript.
The reason is :
I'm building a web application, when a user clicks on an image, tagged like this:
<img src='src.jpg' data-id='42'/>
JavaScript calls a PHP page like this:
$.ajax("action.php?action=click&id=42");
then action.php inserts rows in database.
But I'm afraid that some users can automate entries that "clicks" all the id's and such, by calling necessary url's, since they are visible in the source code.
How can I prevent such a thing, and make sure it works only on click, and not by calling the url from a browser tab?
p.s.
I think a possible solution would be using encryption, like generate a key on user visit, and call the action page with that key, or hash/md5sum/whatever of it. But I think it can be done without transforming it into a security problem. Am I right ? Moreover, I'm not sure this method is a solution, since I don't know anything about this kind of security, or it's implementation.
I'm not sure there is a 100% secure answer. A combination of a server generated token that is inserted into a hidden form element and anti-automation techniques like limiting the number of requests over a certain time period is the best thing I can come up with.
[EDIT]
Actually a good solution would be to use CAPTCHAS
Your question isn't really "How can I tell AJAX from non-AJAX?" It's "How do I stop someone inflating a score by repeated clicks and ballot stuffing?"
In answer to the question you asked, the answer you quoted was essentially right. There is no reliable way to determine whether a request is being made by AJAX, a particular browser, a CURL session or a guy typing raw HTTP commands into a telnet session. We might see a browser or a script or an app, but all PHP sees is:
GET /resource.html HTTP/1.1
host:www.example.com
If there's some convenience reason for wanting to know whether a request was AJAX, some javascript libraries such as jQuery add an additional HTTP header to AJAX requests that you can look for, or you could manually add a header or include a field to your payload such as AJAX=1. Then you can check for those server side and take whatever action you think should be made for an AJAX request.
Of course there's nothing stopping me using CURL to make the same request with the right headers set to make the server think it's an AJAX request. You should therefore only use such tricks where whether or not the request was AJAX is of interest so you can format the response properly (send a HTML page if it's not AJAX, or JSON if it is). The security of your application can't rely on such tricks, and if the design of your application requires the ability to tell AJAX from non-AJAX for security or reliability reasons then you need to rethink the design of your application.
In answer to what you're actually trying to achieve, there are a couple of approaches. None are completely reliable, though. The first approach is to deposit a cookie on the user's machine on first click, and to ignore any subsequent requests from that user agent if the cookie is in any subsequent requests. It's a fairly simple, lightweight approach, but it's also easily defeated by simply deleting the cookie, or refusing to accept it in the first place.
Alternatively, when the user makes the AJAX request, you can record some information about the requesting user agent along with the fact that a click was submitted. You can, for example store a hash (stored with something stronger than MD5!) of the client's IP and user agent string, along with a timestamp for the click. If you see a lot of the same hash, along with closely grouped timestamps, then there's possibly abuse being attempted. Again, this trick isn't 100% reliable because user agents can see any string they want as their user agent string.
Use post method instead of get.Read the documentation here http://api.jquery.com/jQuery.post/ to learn how to use post method in jquery
You could, for example, implement a check if the request is really done with AJAX, and not by just calling the URL.
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// Yay, it is ajax!
} else {
// no AJAX, man..
}
This solution may need more reflexion but might do the trick
You could use tokens as stated in Slicedpan's answer. When serving your page, you would generate uuids for each images and store them in session / database.
Then serve your html as
<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>
Your ajax request would become
$.ajax("action.php?action=click&uuid=uuidgenerated");
Then on php side, check for the uuid in your memory/database, and allow or not the transaction. (You can also check for custom headers sent on ajax as stated in other responses)
You would also need to purge uuids, on token lifetime, on window unload, on session expired...
This method won't allow you to know if the request comes from an xhr but you'll be able to limit their number.
I am working on a live weather data page. Our weather module outputs the data in CSV and stores it on my webserver. I then use a PHP script to translate the CSV into an array and then i encode it in JSON and output it so that my jQuery Ajax script can call it every so often to get the latest data and update the page. This is working great so far.
My question is, how can i prevent the URL used to retrieve the JSON (the URL of the aforementioned PHP script) to be opened and viewed in a browser? I tried adjusting the permissions, but to no success.
Thanks in advance to any who are willing to help.
There's no real way of doing that, since the Ajax call also comes from the browser. There's no real difference between a proper browser call and an Ajax call. A GET call is a GET call.
EDIT
As per #Adeneo's suggestion, implementing a pseudo-security, through some kind of key, would be a good way of making it harder for people to view the page, even though there's no way of literally blocking the call.
Also, adding a header to your Ajax call and verifying the presence of that header in your backend script makes it a bit harder to spoof.
Another idea would be that, if that service would be called only once per page view, you could setup a key in your javascript, provided by your server, to append to your ajax call. When the server gets called, the key provided becomes invalid after use, preventing someone from calling the service with the same key twice.
There is no way of (reliably) identifying a browser as anything that is not some form of "Authentication-Token" can be faked. The server relies on the client to be honest.
You can detect if a request is an ajax request tho. Here is a link to one way of doing it:
http://davidwalsh.name/detect-ajax
This is how he does it:
/* AJAX check */
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
/* special ajax here */
die($content);
}
You will want to reverse the statements in the if since it die()s when the request IS ajax.
There are other ways of detecting ajax, none of which are 100% secure, including you setting a GET variable that helps you identify an ajax call (but that get variable can also be sent via the browser via the address line so well... you get the picture)
Short answer: you cannot.
Long answer: you could implement a simple Browser Sniffing. Or search for far more advanced methods.
$browser = get_browser(null, true);
if ($browser[parent] == "whatever-identifies-clients-that-have-access") {
//Code to output jSon here.
}
else {
header('HTTP/1.1 403 Forbidden');
}
But note that this is not security. At the very most, it throws up a barrier; but preventing is impossible.
Edit This assumes the client is not a browser, I wrongly assumed a (mobile) client of some sorts was accessing the JSON. When it is a browser, you cannot deny access. At all. AJAX comes from that browser too.
I am working on a web application that will be hosted on a server that is "on the internet", not a LAN.
The app uses quite a bit of AJAX calls and has about 12 ajax handler files for the functions.
My question is instead of asking anybody here to write a tutorial on AJAX security, does anybody know of any good resources (website, book, whatever) that can help me with securing these files.
Right now, as long as you know the variable name its looking for you can freely get data from the database.
I was thinking maybe session validation, or something along those lines for the logged in user.
Anyways if you have any good resources I'll do the homework myself.
Thanks
AJAX calls are generally used to access web services, which is what it seems you are using them for here. If that is the case then what you need to be concerned about is the security layer that you have provided in the server-side scripting language you are using (looks like you are using PHP as per your question's tags).
The same way that you do authentication and protection for other pages on your site that aren't accessed via AJAX calls you can implement for your web services. For instance, if you require authentication for your application then you can store the user's ID in $_SESSION. From there you can check to make sure the user is logged in via $_SESSION whenever one of your web services is requested.
I've often seen AJAX calls that check the X-REQUESTED-WITH HTTP header to "verify" that the request originated from AJAX. Depending on how you're sending your AJAX calls (with XmlHttpRequest or a JS library), you can either use the standard value for this header, or set it to a custom value. That way, you can do something similar to this in PHP to check if the page was requested with AJAX:
http://davidwalsh.name/detect-ajax
if( !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
It is important to note that since it's an HTTP header, it can be spoofed, so it is by no means full-proof.
Here is a good resource. Securing Ajax Applications: Ensuring the Safety of the Dynamic Web
However a very simple method is to use a MD5 hash with a private key. e.g. USER_NAME+PRIVATE_KEY. If you know the users name on the website/login you can provide that key in an MD5 hash set to a javascript variable. Then simply pass the users name in your AJAX request and the REST service can just take the same private key plus the users name and compare the two hashes. You're simply sending across a hash, and the user name then. It's simple and effective. Virtually impossible to reverse too unless you have a simple private key.
So in your javascript you might have this set:
var user='username';
var hash='925c35bae29a5d18124ead6fd0771756'
Then, when you send your request you send something like this:
myService.php?user=username&hash=925c35bae29a5d18124ead6fd0771756&morerequests=goodthings
When you check it, in the service you would do something like this
<?php
if(md5($_REQUEST['user']."_privatekey")==$_REQUEST['hash']){
echo 'passed validation';
}else{
echo 'sorry charlie';
}?>
Obviously you would need to use PHP or something else to generate the hash with the private key, but I think you get the general idea. _privatekey should be something complex in the event you do have a troll that tries to hack it.
I'm building a browser game and im using a heavy amount of ajax instead of page refreshs. I'm using php and javascript. After alot of work i noticed that ajax isnt exactly secure. The threats im worried about is say someone wants to look up someones information on my SQL server they'd just need to key in right information to my .php file associated with my ajax calls. I was using GET style ajax calls which was a bad idea. Anyways after alot of research i have the following security measures in place. I switched to POST (which isnt really any more secure but its a minor deterent). I have a referred in place as well which again can be faked but again its another deterrent.
The final measure i have in place and is the focus of this question, when my website is loaded i have a 80 char hex key generated and saved in the session, and when im sending the ajax call i am also sending the challenge key in the form of
challenge= <?php $_SESSION["challenge"]; ?>
now when the ajax php file reads this it checks to see if the sent challenge matchs the session challenge. Now this by itself wouldnt do much because you can simply open up firebug and see what challenge is being sent easily. So what I'm having it do is once that challenge is used it generates a new one in the session.
So my question is how secure is this from where im standing it looks one could only see what the challenge key was after it was sent and then it renews and they couldnt see it again until it is sent, making it not possible to send a faked request from another source. So does anyone see any loop hole to this security method or have any addition thoughts or ideas.
Your definition of "secure" is vague. You seem less interested in preventing data from being intercepted, and more interested in keeping people from submitting custom requests to your server. That isn't security, that is just good application design - your program shouldn't accept requests which cause the internal state to break.There is absolutely nothing you can do to prevent people from submitting whatever data they want to. The solution is to validate the data they're submitting server-side, not to try to prevent them from submitting the data client-side, which will always fail.
I switched to POST
You shouldn't bother; that has nothing to do with security. Use whichever HTTP verb is appropriate for the request. Are you querying information? Use a get request. Are you updating/inserting/deleting information? Use post.
say someone wants to look up someones information on my SQL server they'd just need to key in right information to my .php file associated
You should be authenticating all requests to make sure they have access to the data they're querying. SSL will help you perform the authentication securely.
when my website is loaded i have a 80 char hex key generated and saved in the session, and when im sending the ajax call i am also sending the challenge key
This isn't going to help. The entire premise of your question seems to be that the user has Firebug or a similar HTTP debugging tool installed. If they do, your session key is rendered useless.
See the answer by 'meagar'.
I'd like to mention:
By passing around an identifier in Session, you're doing what the Session is already doing. There's usually a cookie with a unique identifier similar to the one you're generating, which is telling your application, essentially, who that person is. This is how PHP sessions work, in general.
What you would need to do, in this case, is check that for a given request - POST or GET - that the particular user (whose unique user ID, or similar, is stored in the Session) has permission to add/change/delete/whatever with that particular request.
So for a "search" request, you would only return results that User X has permission to view. That way, you don't worry about what they send - if the user doesn't have permission to do something, the system knows not to let them do it.
Hence "you should be authenticating all requests".
Someone feel free to add to this.
function mysqlRequest(type,server,name,value,sync){
$.ajax({
type: 'POST',
url: 'sql.php',
data: "server=s"+server+"&type="+type+"&name="+name+"&value="+value+"&challenge=<?php echo $_SESSION['challenge']; ?>",
cache: false,
dataType: 'json',
async: sync,
success: function(data){
},
complete: function(){}
I want to know what is the safe method to send php data to js. I found by search to start php tags in js and pass data by this way.
var jsVar = "<"+"?php echo $phpVar;"+"?"+">";
But it seems a dangerous way to pass data exposing threats. I want to know whats alternative way to do same that is safe.
I'm not entirely sure what you mean by "safe", but if I understand your question correctly, you can inject data from PHP directly into your JavaScript using json_encode:
var jsVar = <?php echo json_encode($phpVar) ?>;
If all you want to do is to inject actual PHP source code into your script, then just print it as a string:
var jsVar = "<?php echo '<?php echo $phpVar ?>' ?>";
I can't imagine this is what you mean though, as I can't think of a reason for wanting to do this :)
I want to know whats alternative way to do same that is safe.
I'm not sure what you mean by "safe", but you have to assume that any data you send to the client's browser can and will be viewed by a sufficiently-motivated user. You can secure the data from prying eyes in transit (by using SSL, e.g., https), but the client user's browser needs to be able to read the data, which means the client user can too.
You can raise the bar slightly (for instance, by obfuscating the data you embed in the page, by supplying it only in response to an Ajax call, etc.), but with today's 'net and web tools (which are increasingly just embedded in browsers) a sufficiently-motivated user will get around the precautions you take (by stepping through your code and looking at the variable you store the de-obfuscated data or the data from the Ajax response in, for instance).
If you want to raise the bar further, you can require a plug-in like Flash or Java and send obfuscated (or even encrypted) data to your flash app / Java applet and de-obfuscate / decrypt it within the app / applet. But that just raises the bar to the level of someone with debugging tools for Flash or Java.
Probably not worth the bother, I bet you have better things to do. :-)
If you don't want the user to see the data in question, don't send it to them, keep it on your server where it's safe and have the browser ask for only the information it's actually allowed to show the user.
json_encode is the best way to sent back.
echo json_encode($phpVar)
If its your data coming from your database this is pretty safe.
The problem occurs when you are storing and re-displaying data entered by the user. In which case you need to ensure that there is no possibility of executabe javascript being embedded in the data. Removing or escaping '"{}();+-/* and thier hex equvalents should do it.
You could use json_encode as suggested in answer this