In my CMS, I have a page which loads lots of mini-interfaces into a panel using AJAX. Those interfaces come from various PHP files in a /ajax directory.
Would it be possible somehow to only allow access to those files using ajax, and not just by browsing to them?
My concern is, of course, that someone finds out about the /ajax directory, and gets access to the core functionality of the CMS without even having to login. Of course I could import my user class and authenticate each of the AJAX files individually, but would it be possible to only allow access through AJAX?
Would it be possible somehow to only allow access to those files using ajax, and not just by browsing to them?
No.
You could add extra HTTP headers, or modify existing ones (such as Accept) when you make the request from JavaScript … but since you are trying to do this for security reasons, that would be insufficient.
Of course I could import my user class and authenticate each of the AJAX files individually
Do that. Ajax requests are not special. They are just HTTP requests. End points created for Ajax should be secured with authentication/authorization just like any other HTTP request end point.
No. A hacker could just fake Ajax requests, anyway. You need to authenticate everywhere or you'll get screwed.
From outside a browser, it's possible for anybody to initiate HTTP requests to any public URL on your site. There's nothing special about AJAX requests other than headers, and those can be spoofed easily.
Now what can't be easily spoofed is a secure session mechanism. If you're requiring people to log in, then you should be doing that anyway.
Simple answer, "no".
Your ajax files should also validate the user is logged in the same way as the front end of your system does.
AJAX is almost same request as Standart request you can check header but this is not secure way. So short you can't do this. Authetificate on server side what you have proposed.
Authenticate your AJAX files. If there are lots of them, create a class and extend it in each individual AJAX file.
/ajax/abstract.php:
<?php
abstract class AjaxHandler {
public function __construct() {
// import authentication handler
if ($authenticated) {
$this->display();
}
else {
header('HTTP/1.1 401 Unauthorized');
exit;
}
}
}
Then in each file, i.e. /ajax/get_user_profile.php:
<?php
class GetUserProfile extends AjaxHandler {
public function display() {
// do your routine
}
}
Well, an alternative option you could have is to use post method to get the content from the php, and in your php you should set a key for the post method. And then system wide remove cross origin access. :)
Related
I have a massive of scripts that my core application
include('JS/gramp.php');
include('JS/est.php');
include('JS/curest.php');
include('JS/memomarker.php');
include('JS/local----------.php');
include('JS/poirel.php');
include('JS/maplayers.php');
include('JS/trafficinc.php');
include('JS/plannedtraffic.php');
include('JS/transportissues.php');
include('JS/cams_traff.php');
include('JS/places2.php');
Now these are all being moved to a on the fly loading, to reduce the size of the application on load
if(button_case_curtime==true){
$(".jsstm").load("<?php echo $core_dir; ?>JS/curresttime.php?la=<?php echo $caseset['iplat']; ?>&lo=<?php echo $caseset['iplong']; ?>&h=<?php echo $days_h; ?>");
rendermap = true;
}
issue! the application requires these files to be secure, the data involved requires that no one can access.
The ONLY file that will ever request these files will be index.php
Any input or idears would be fantastic!
There is no way to provide a file to the browser without also providing it to a user.
You could configure your server to only supply the files given an extra HTTP header (which you could add with JS), but nothing would stop people from sending that header manually or just digging the source out of the browser's debugging tools.
Any user you give the files to will have access to the files. If you want to limit which users have access to them, then you have to use auth/authz (which you'll want to apply to the index.php file as well so that unauthorised users don't just get JS errors or silent failure states).
No. What you are trying to do is not possible. Ajax requests are not special. They are just HTTP requests. End points created for Ajax should be secured with authentication/authorization just like any other HTTP request end point.
This is a trivial solution that will solve your problem half-way. Request them via a POST request, like so:
$.post('JS/maplayers.php', {'ajax':true}, function(){});
Notice the POST variable 'ajax'. In the file maplayers.php, add to the beginning the following code:
if((!isset($_POST['ajax']))) {
die('Invalid request, only ajax requests are permitted');
}
I'm using a jquery script that uploads files with ajax and PHP. It sends a request to upload_a_file.php which then uploads files.
Is there a way that I can make sure upload_a_file.php is not loaded directly in a browser?
I tried putting upload_a_file.php above my public_html folder. But can't seem to get javascript to load upload_a_file.php.
Here is the url format I use in the javascript to request upload_a_file.php:
../upload_a_file.php
Is it even possible to access files above public_html with javascript?
JS cannot access anything on a server that you yourself as a user cannot. If a file is outside of the site's document root, it is NOT accessible by a user, or by JS. Imagine the fun place the web would be if JS could magically bypass access restrictions on a server and grab any more. "Aww, I was going to grab this bank's accounts list, but it's not in the document root. Good thing I've got Javascript, it can do everything!"
It'd be like every episode of 24, where "patching into the subnet" can magically bypass any firewall and get data from machines which aren't even online or (better yet) not even powered up. Amazing things, those subnets.
You can check the HTTP header X_REQUESTED_WITH is present and has a value of XMLHttpRequest. This is not non-standard header but most JavaScript frameworks, including jQuery, Prototype, and mootools follow this convention.
In PHP you can access it $_SERVER['HTTP_X_REQUESTED_WITH'];
for example:
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
// do something
}
The javascript is running in the browser. It makes its requests through the browser. So, No, there's no way to access a page through ajax but not directly from the browser.
No, not directly. You can call other script (PHP or whatever) that will either "call" your script with include or e.g. with fopen or curl.
Nothing can access files above public_html, because the web server will not serve them. Doing so would have obvious security vulnerabilities, like being able to view any file on your filesystem.
If you want to restrict the file to only being able to be loaded via your javascript, I would think you'd want to look at the $_SERVER['HTTP_REFERER'] variable in php. This should be set to the page the javascript is located on when it is being accessed properly. If it is anything else or empty, the user is accessing it in some other manner.
Using this method shouldn't be relied on for security however, because the referer can be spoofed with the right tools.
Since direct browser access to a page is a GET request by PHP, here is a very basic access control method to keep someone from inadvertently going directly to upload_a_file.php:
In your jquery script, use an ajax request with type "POST":
$.ajax({
url: "../upload_a_file.php",
dataType: "json",
type: "POST"
});
and use this in your upload_a_file.php:
if ($_SERVER['REQUEST_METHOD'] == "POST") {
// upload a file
} else {
header("Location: http://example.com/myPublicUploadPage.php");
die();
}
For example let's say I have a controller called News. Methods of News include Create, Edit, Delete, etc. So let's say for users with javascript enabled, we can use AJAX to deal with these things and use the controllers if not. For example, going to /news we can create news, edit, or delete without leaving this page...with AJAX. Without javascript, we would have to go to /news/create, /news/edit/1, /news/delete/1, etc.
So then what way is more efficient to deal with AJAX requests? On each controller should I just have a conditional to check whether the request was sent with AJAX, something like:
if(isset($_POST['ajax'])) {
// serve ajax request
} else {
// serve regular request
}
Or should I create additional methods such as ajaxCreate, ajaxEdit, ajaxDelete, etc?
Shouldn't your AJAX requests be almost the same as your regular requests, except the regular requests have an additional layer (rendering a page) on top?
Your conditional check should simply regulate whether you respond with something like a JSON response, or a full page - in effect, what view you invoke (assuming an MVC-style setup).
Never use /news/delete/1 to delete news!
use POST /news/delete and pass a news id
With that said, both ajax request and regular requests should be made to the same URL. the difference is that regular requests will return an html response and an ajax request will return xml/json/etc
Page: /news/create/
// create new news item code goes here
// most newer javascript libraries set this header so you know the page
// was requested via ajax
if ( isset( $_SERVER['X-Requested-With'] && $_SERVER['X-Requested-With'] == 'XMLHttpRequest' ) {
//output status code or new news item
exit;
}
// not an ajax request load a view
require( 'views/news_create.php' );
I prefer to pull this functionality into an API. For example, I can have a folder structure like the following:
web
- api
- 1.0
- news
create.php
news.php
Then your page is accessible at the 'news.php' URL. Inside this file you consume your own api. The AJAX would also directly access the API at the 'api/1.0/news/create.php' URL for instance.
This leads to less API code in the controllers/views.
Bob
I have a web app where most of the functionality is within a javascript file, and I am about to introduce a pro version of the app in which registered users would get access to more functionality.
Again the extra functionalities are just extra functions in a javascript file.
What I am planning to do is:
- link pro_script.js if user is logged in,
- or link to normal_script.js if user is not logged in,
at the header of the page via user authentication with php.
I was wondering if this is the best way to approach this situation?
I have concerns that the pro_script.js is residing accessible under the javascripts folder, and it would be possible to write a script or plugin that loads the pro_script.js instead of normal_script.js.
You can have your HTML to call my_script.php instead of my_script.js. This PHP file would simply output your JS depending on the state if the user is logged on or not.
You can hide pro_script.js behind PHP script - it will check user's account and if user is "premium" then it outputs content of pro_script.js, otherwise - empty string. Don't forget to setup correct headers (content-type and caching)
This is acually #Adnan's idea, but my response was far to complex for a comment.
Your my_script.php should look something like this:
<?php
session_start();
header("Content-type: application/x-javascript";);
if (!empty($_SESSION['PRO_USER'])) {
echo file_get_contents("js/pro_script.js");
} else {
echo file_get_contents("js/normal_script.js");
}
exit;
?>
I have several pages inside an AJAX directory. I don't want these pages accessible directly so you cannot just type in the URL of the page within the AJAX directory and access it. I "solved" this by using a PHP session on the page that calls it as follows:
Main page:
<?php
session_start();
$_SESSION['download']='ok';
?>
and on the ajax page I have this:
<?php
session_start();
if($_SESSION['download']!=='ok'){
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit;}
?>
The only problem is that if a user goes through the correct process once, the cookie is stored and they can now access the page directly. How do I kill the session once they leave the parent page?
thx
why use session ?
if i understood what you want:
<?php /// Is ajax request var ?
if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])=="xmlhttprequest") {
// do your ajax code
} else {
// redirect user to index.php since we do not allow direct script access, unless its ajax called
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit();
}
} ?>
A really simple solution is to open up each of the files you want to protect from direct URL entry & add the following to the top:
<?php if (isset($_GET['ajax']) != true) die();?>
Now get rid of your redirect script since it's useless now. You don't need to use sessions for this. Every time you request a page, use it's direct URL, just add ?ajax=1 to the end of it.
By adding the ?ajax=1, PHP will set a key of 'ajax' to the $_GET global variable with the value of 1. If ?ajax=1 is omitted from the URL then PHP will not set a key of 'ajax' in $_GET and thus when you check if it's set with isset() it will return false, thus the script will die and not output anything. Essentially the page will only output data if ?ajax=1 is at the end of the URL.
Someone could still "spoof" the URL and add '?ajax=1' themselves, but that is not the default behavior for people or web browsers. If you absolutely need to prevent this then it will be much more complicated, e.g. using templates outside of a publicly available folder. Most other "simple" solutions will have the same "spoofing" potential.
There's really no way to accomplish this with a 100% certainty - the problem is, both AJAX and regular web browser calls to your web site are using the same underlying protocol: HTTP. If the integrity and security of your site depends on keeping HTTP clients from requesting a specific URL then your design is wrong.
so how do you prevent people from directly accessing files inside certain directories while still letting the site use them??
Create a controller file. Send all AJAX requests to this controller.
ajax-control.php
<?php
$is_ajax = true;
include "ajaxincludes/test.php";
// ... use the ajax classes/functions ...
ajaxincludes/test.php
<?php
if (!isset($is_ajax) || !$is_ajax)) {
exit("Hey you're not AJAX!");
}
// ... continue with internal ajax logic ...
If clients try to access the file directly at http://mysite/ajaxincludes/test.php they'll get the error message. Accessing http://mysite/ajax-control.php will include the desired file.
I don't think there is a surefire way to do what you are asking, since HTTP request headers can be faked. However, you can use $_SERVER['HTTP_REFERER'] to see if the request appears to be coming from another page on your site.
If the rest of the security on your site is good, the failure of this method would not grant the user access to anything they were not already able to access.
I've never tried this but maybe you could do something with jQuery's .unload() and then call a PHP page to unset() the session.
Why not (on Ajax page):
session_start();
if($_SESSION['download']!=='ok'){
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit;
}
// do whatever you want with "access granted" user
// remove the download flag for this session
unset($_SESSION["download"]);