one of my php page returns data like this:
<?php
//...
echo "json string";
?>
but someone else use file_get_contents() to get my data and use in other website.
can anybody tell me what can i do to prevent such thing happen.
i consider if i can get the request's domain name to echo something else.but i dont know
the function to get request's domain name.and if the request is sent by a server,that
will be unhelpful. My English is poor, to express doubts, please bear with.
you can also use sessions. if somewhere in your application, before the user gets the json data, you start a session, then in this page where you are outputting json data, you can check for the session variable. this way only users that have passed the session generator page, can view your output.
suppose you have page A.php that generates the session. use this code before outputting anything in this page.
session_start();
$_SESSION['approvedForJson'] = true;
then in your page where you are outputting json data, before outputting anything, call session_start() again. the beginning of your PHP code is a good place to call it.
then before outputting the json data, check if the session variable for approved users exists, or not.
if ( isset($_SESSION['approvedForJson']) && $_SESSION['approvedForJson'] ) {
echo "json data";
} else {
// bad request
}
You can use $_SERVER['REMOTE_ADDR'] to get the address of the client address. You can also check $_SERVER['HTTP_REFERER'] and block external requests that way, but it's less reliable. There's probably a few other techniques involving $_SERVER that you can try.
Your fighting an uphill battle here. I am assuming your serverside process that responds in json is being consumed via javascript in your users browsers... so there is no easy way to encrypt it. You might try some of the techniques used to prevent xspf (see http://en.wikipedia.org/wiki/Cross-site_request_forgery ). If you developed the client to pass along some session token that is uniq per client you could reduce some of the problem. But, chances are whoever is stealing your data is gonna figure out whatever mechanism you put in place ... assuming this is some sort of ajax type thing. If its a server-server thing then as sli mentions, setting up some restrictions based on the remote ip would help, plus setting up some sort of API authentication tokens would help even more (see oauth for some pointers)
You could also using .htaccess with apache block every external request to the page if it get's called internally or block every request that is not from your domain:
Google search thingie
EDIT
You could also use some php file which includes the file which can not be read. So for example you have file.php:
<?php
$allowedFiles[] = 'somefile.php';
$allowedFiles[] = 'someotherFile.php';
$allowedFiles[] = 'jsonReturnFile.php';
if(in_array($_GET['file'], $allowedFiles)){
include( "include/".$_GET['file'] );
}
?>
Then you can allow file_ get _contents() on that file and write a rewriteRule in your .htacces to disallow any request to the include/ folder.
RewriteRule include* - [F,NC]
That will return a 403 forbidden error for a request to that directory or any file in the directory.
Then you can do you JSON request to something like: file.php?file=jsonReturnFile.php&someothherParamReadByJsonFile=1
And when someone tries to get the file contents for the JSON file they will get the forbidden error, and getting the file contents for the include.php won't return anything usefull.
Related
I'm working on a small Restful API, which will show users current weather conditions in their location in the header of the page. There will be a GET query sent to the server via Ajax to a link similar to this:
https://test.com/weather/{required location}
Test.com represents my link which further queries either the database or external APIs. It responds with JSON and they will see the weather for their location. The problem that I have is if that link is accessed directly, it just prints the output, so potentially it could get farmed.
The question I have is how can I implement some sort of logic where if the the page is accessed via ajax from test.com, the output is JSON as needed. Any other ways to access that link will display a blank or custom page with JSON hidden?
Also, as I am new to API and Ajax work, are there any other security means I need to be aware of?
I'm using jQuery, php and mysql.
Thanks
I just found a partial solution myself, using Dontfeedthecode's idea of utilising $_Server varialbes. The one that is suitable is $_SERVER['HTTP_X_REQUESTED_WITH'].
if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
echo 'JSON RESPONSE HERE';
} else {
echo 'ALTERNATIVE PAGE HERE';
}
Found out that when Ajax query is sent with 'X-Requested-With: XMLHttpRequest' header according to this. So if we look for the header, we can find out how to treat it. However, from my understanding this will not prevent potential farming.
I will further investigate Dontfeedthecode's response to see if I can get it to work against farming.
You can check $_SERVER['HTTP_HOST'] against allowed domain names.
Taken from: PHP $_SERVER['HTTP_HOST'] vs. $_SERVER['SERVER_NAME'], am I understanding the man pages correctly?
$allowed_hosts = array('foo.example.com', 'bar.example.com');
if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts)) {
header($_SERVER['SERVER_PROTOCOL'].' 400 Bad Request');
exit;
}
This may be a duplicate of:
Prevent Direct Access To File Called By ajax Function
I am having issues with the code to access a remote website server2 from another website server1. The code I use from inside the server2 to log in is the following code:
require_once("http://server2.com/access/models/config.php");
if (!securePage($_SERVER['PHP_SELF'])){die();}
//Prevent the user visiting the logged in page if he/she is already logged in
if(isUserLoggedIn()) { header("Location: http://server2.com/access/account.php"); die(); }
On server2 it looks like I can not use require_once() because the page does not pass and when I use include() then prevent the user visiting does not pass. I think I am missing a code like cURL or path. Can anybody post the code to call my server2 from a another remote server1?
You can't include/require PHP pages from another server because those php-files are getting parsed. You will end up getting the parsed HTML code or non at all if your config.php meets minimum safety standards. You'd have to open it differently but be aware that if you can open config.php in an easy way remotely, everyone else can too...
I suggest not to use include at all but try a different approach: for example via a php script on that second server that returns you plain text like:
login|logout
ok|error
id_Paul23
pwHash_asdf02302afbd33
the second items after the | represent an alternative response if you have an erroneus login attempt. Your user sends the login-data to your script on server 1 which attempts a login-try on that special script on server 2 which returns the result above and you can then do whatever you want on server 1.
Or better: send/receive the data in a standardized format like JSON. You already have functions in PHP for that: json_encode() and json_decode() to parse your data.
Here is an example on how you could do this on a larger scale: http://www.jasny.net/articles/simple-single-sign-on-for-php/
This article will help you send the request to server2: How do I send a POST request with PHP?
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 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"]);
I'm developing a website, and due to user-input or by other reason, I need to show some error messages.
For this, I have a page named error.php, and I get the error number using $_GET. All error messages are stored in a array.
Example:
header( 'Location: error.php?n=11' );
But I don't want the users to the enter the error code in the URL and see all the other error messages.
For preventing that, I thought I could whitelist the referer page, and only show the error message if the referer is found in my whitelist.
It should be fair similar to this (haven't tested yet ;) )
$accept = false;
$allowedReferer = array (0=>'page1.php', 'page2.php');
if (in_array($_SERVER['HTTP_REFERER'], $allowedReferer )) {$accept = true;}
if ($accept) { $n=$_GET['n'];echo "Error: " . $errorList[$n];}
Is this method good enough to avoid the spy-users?
I'm doing this with PHP5
Thanks
No, it isn't remotely secure: the HTTP Referer header is trivial to spoof, and is not a required header either. I suggest you read this article for an example of exploiting code (written in PHP), or download this add-on for Firefox to do it yourself from the comfort of your own browser.
In addition, your $allowedReferer array should contain full URL's, not just the script name, otherwise the code will also be exploitable from remote referrals, e.g. from
http://www.example.org/page1.php
To summarise: you cannot restrict access to any public network resource without requiring authentication.
Rather than redirect, you could simply display the error "in place" - e.g. something as simple as adapting your present code with something like
if ($error_condition)
{
$_GET['n']=11;
include "/path/to/error.php";
exit;
}
In practice it might be a little more sophisticated, but the idea is the same - the user is presented with an error message without redirecting. Make sure you output some kind of error header, e.g. header("HTTP/1.0 401 Bad Request") to tell the browser that it's not really seeing the requested page.
If you do want to redirect, then you could create a "tamperproof" URL by including a hash of the error number with a salt known only to your code, e.g.
$n=11;
$secret="foobar";
$hash=md5($n.$secret);
$url="http://{$_SERVER['HTTP_HOST']}/error.php?n={$n}&hash={$hash}";
Now your error.php can check whether the supplied hash was correctly created. If it was, then in all likelihood it was created by your code, and not the user.
You shouldn't use an external redirect to get to an error page. How I structure my PHP is like this:
I have a common file that's included in every page, with common functions: handle login/logout, set up constants and the like. Have an error() function there you can pass error information to that will show an error page and exit. An alternative is to use the index.php?include=pagename.php idiom to achieve common functionality but I find this far more flaky and error prone.
If you externally redirect the client (which you obviously need to do sometimes) never rely on the information passed via that mechanism. Like all user input it's inherently untrustworthy and should be sanitized and treated with extreme caution. Don't use cookies either (same problem). Use sessions if you need to persist information between requests.
HTTP_REFERER can be spoofed trivially by those with enough incentives (telnet is the tool of choice there), and shouldn't be trusted.
Error messages should never reveal anything critical anyhow, so I'd suggest you to design your error messages in such a way that they can be showed to anyone.
That, or use random hashes to identify errors (instead of 11, use 98d1ud109j2, etc), that would be stored in a central place in an associative array somewhere:
$errors[A_VERY_FATAL_ERROR] => "308dj10ijd"
Why don’t you just include the error message script? And to get rid of previous output data, use the output control to buffer it and clear it on error:
if ($error) {
ob_clear();
$errorCode = 11;
include 'error.php';
exit;
}
Instead of redirecting to an error page why not include an error page. You can restrict access to a directory containing the php files that contain the error content with .htaccess:
RedirectMatch 404 ^error-pages/*$
and inside the error-pages you can have include-able pages which display errors.
With this method you can be sure that no one can directly access the pages in the error-pages directory yet you can still include them within scripts that are publicly accessible.
If you handle errors before sending headers, you can easily create a function that outputs a basic html page with content, and exit right after it. That way there is no specific need for any other page (apart from the functions page, I guess).
It's as simple as checking if there's a problem, and if there is a problem, just call the function.
I use a function like this that even writes data away when it is called, so I have my own error logs...