I have a ajax form that goes to a php file, i dont want users to be able to directly enter the php file into the URL bar so how would i be able to redirect them if they enter that php file, i cant simply add a header("location:index.html") or the form wouldnt work.
<?php
$Reg['E'] = 'Test';
echo json_encode($Reg);
?>
There's no way to be 100% certain because there's nothing technically special about an ajax request vs. any other request. If you're using jQuery, you can do a check on the X-Requested-With header:
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' )
...otherwise redirect. You can also put a token in the form such as a random md5 hash and check whether that token is submitted along with the request (compared to a value stored session). This at least requires that the form page be visited first to generate the token, and "normal" users will not be able to get the token.
Related
Is it possible to check that the $_GET or $_POST values are submitted from specific page?
For example, there is an ajax in page1 submitted value to page2.php?q=abc, and the page2 only accept the q when it is submitted from page1.
If I directly browse to the page page2.php?q=abc, the php will not run unless I submitted the value from page1.
Is it possible to do that?
Edit 1:
Because I can access the page2 and get the result. Don't mention about the session, because I can validate the session to match my needs and the values submitted to php is valid or not.
What I want is to check if the request is sent from specific page or not. If true, then accept the values and process it, else, redirect to homepage or something else.
Edit 2:
My question is, not only values submitted through Ajax, but also direct access, such as href="page2.php?q=abc". I guess token will be the best way to do that, and the query part will validate again.
There are two security checks you could perform while dealing with AJAX:
1) Check if the request it sent through AJAX:
if ( !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' )
{
//AJAX Request Detected
}
2) Hashed tokens:
On the page that's holding the AJAX Request, create a token:
session_start();
$hashed='';
$_SESSION['token'] = microtime();
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
$salt = '$2y$11$' . substr(md5(uniqid(mt_rand(), true)), 0, 22);
$hashed = crypt($_SESSION['token'], $salt);
}
This is using the blowfish algorithm with the crypt() to create hashed string.
Your AJAX function would be like:
$.ajax({
type: "POST",
url: 'page2.php',
data: {
action: '<?php echo $hashed;?>', //pasted the hashed string created in PHP
q: 'test'
},
success: function (data) {}
});
Upto you whether you want to use $_GET or $_POST method.
And then on the second page which is receiving the AJAX request, you do:
session_start();
if(crypt($_SESSION['token'], $_POST['action']) == $_POST['action']){
//Hashed string matches. Request has come from page1.
echo $_POST['q'];
}
in your form you can just add a hidden field and add a page id. On the page that should send post or get request you can do something like
<form action='phpscript.php'>
<input type='hidden' name='page' value='valid_page'>
<input name='your_other_info'>
</form>
In the phpscript.php you can do something like
<?php
//If you have a request, it can be either post or get method
if(isset($_SERVER['REQUEST_METHOD']) && (isset($_POST['page']) || isset($_GET['page']))){
}else{
//Post or get is not from the valid page
}
?>
You cannot restrict the "origin" of the request, because there's no such thing per se. Your "page" isn't sending a request, it's the browser that does it. And the browser may have any number of reasons why it's sending you a request; be that because one of your pages has instructed it to do so or because a user is fiddling around with the Javascript console manually.
All you get on your end is an HTTP request. Go ahead, inspect it. In the browser, look at the network tab and inspect the raw request being sent. It's just a bunch of HTTP headers, nothing more. Anyone can send an HTTP request with arbitrary HTTP headers any time from anywhere and make it look like anything they want. Even the Referer HTTP header is not going to "protect" you.
If you need any sort of protection, you can use session tokens or user authentication to restrict the set of potential entities that can send queries somewhat. But what you have is still by definition a public URL endpoint which answers to arbitrary HTTP queries. You cannot restrict their "origin page". The best you can do is obfuscate it by requiring certain headers to be set (like Referer or X-Requested-With).
I have page.php which receives POST data, it's located in a known position. How can I obtain the url of each page that sends data to page.php via POST, or how can I block/allow POST data from certain sites?
You can (although not reliably) get the URL of the referring page via $_SERVER['HTTP_REFERER']. There are, however, a number of situations where this will be blank (most commonly when coming from an HTTPS site).
The only reliable way to limit which sites can cause a browser to submit data to your script which will be accepted is to implement protection against CSRF and stop all sites that are not your site.
Generate a random token. Store that token in a cookie or session. Store it in a hidden input in the form. When the form is submitted, check if the token in the form matches the token in the cookie/session. If it doesn't, then the form that submitted the data was not on your site.
I use PayPal IPN, so I need to check if POST comes from PayPal
You're trying to solve this problem the wrong way.
Read Paypal's IPN documentation. They provide a means to determine if the event came from them or not.
PayPal HTTP POSTs your listener an IPN message that notifies you of an event.
Your listener returns an empty HTTP 200 response to PayPal.
Your listener HTTP POSTs the complete, unaltered message back to PayPal; the message must contain the same fields (in the same order)
as the original message and be encoded in the same way as the original
message.
PayPal sends a single word back - either VERIFIED (if the message matches the original) or INVALID (if the message does not match the
original).
You can verify the form is from a certain page by doing something like this:
In your form add a random hidden value, and save the value to the session along with a page:
<?php
session_start();
$_SESSION['csfr_token'] = $randomValue; // Randomly generated string
$_SESSION['csfr_page_url'] = ; // URL of the current page
?>
<input type="hidden" name="csfr_token" value="<?php echo $randomValue; ?>" />
The above obviously only applies if you are using a form, if not then add the csfr_token to the post using whatever method you are using.
Then on your page that manages the post:
<?php
session_start();
if (isset($_SESSION['csfr_token']) && $_POST['csfr_token'] && $_SESSION['csfr_page_url'] && $_SESSION['csfr_token'] === $_POST['csfr_token'] && $_SESSION['csfr_page_url'] === 'the URL that you want to allow') {
// Do your stuff
} else {
// Post isnt valid
}
Update:
I think the following question is related: Verifying a Paypal transaction via POST information
A little confused. I have a user login form. As usual user has to enter ID and password and then click on login button. If the login fails then I need to show the login failure message on the same page just below my password text input area. I am using php for server side and javascript for client side coding.
Is it possible to do this with going to another web page.
I am following just as in google login form.
Please share some idea how can i implement it.
yes absolutely you can do it and most of the RAD happens that way. You would use AJAX to do that. You can use jquery to send an ajax request to your php function. jQuery will make ajax a breeze for you.
if you give us more details or code to work with, we can help you better
thanks
1) Make a php script that login user and answer to client with content-type 'application/json'. This script must get username and password and return (for example) the following if authentication is OK:
{
"result": "OK"
}
Important. The php script must login a user if his username and his password is correct, otherwise mustn't.
2) Your javascript makes AJAX request to the .php script (username, password) and redirect user to the next page if result is "OK". The page must redirect the user backward (to the login page) if the user is not authenticated indeed.
function success( data )
{
if( data[ 'result' ] == "OK" )
{
document.location.href='/your-next-url';
}
else
{
// a message about auth. error
}
}
3) Otherwise (if result is not OK) your php script must return something like:
{
"result": "FAIL"
}
If your Javascript client gets the such response it mustn't redirect to the next page, but must show the authentication problem.
So, if user tries to access /your-next-url/ but is not authenticated he will be returned back.
I have a jQuery script using .live() to load it's page content.
$('#content').load("content.php?" + id);
Question: How can I deny a user from accessing the file content.php directly via a URL?
I tried to put this code on top of content.php but Access Denied appear in my #content div
if (!empty($_SERVER['SCRIPT_FILENAME']) && 'content.php' == basename($_SERVER['SCRIPT_FILENAME']))
die('Access Denied');
What is the correct way to make sure users can't access my content.php file using a URL?
You could use some sort of hashing. For example if content.php has the parameter id; you add an additional parameter hash which contains the MD5 hash of "'some random string' + id*15". In content.php you check if the hash & id match; if not access denied.
The computation has to be done in PHP (not ajax) because the user must not know the hashing algprithmus.
With this method the user can look up the source code and access the page directly but you can't disallow that completly because the browser need to access the page to show it. But the user can't access pages he hasn't accessed through ajax before. You could use some headers (HTTP_X_REQUESTED_WITH) to prevent most internet users to access the page directly but experienced users will change the header and access it anyway.
If you want to protect the usage you can use a one time key algorithm. Have the server generate a key that the page will contain in a variable or attribute somewhere. Then on the load command you pass the key to content.php like this:
key = $("{some selector to get the key}")
$('#content').load("content.php?id=" + id + "key=" + key);
Once the page makes the call to server using the key the server will expire the key making it unusable. This way only active page requests will have access to your content.php file.
This method is still not bullet proof but would make it more difficult to access the content.php by the user.
Since you're calling a resource via ajax a possible solution is sending a particular header into the request like HTTP_X_REQUESTED_WITH and then detect the header server side like so:
/* AJAX check */
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) ||
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') {
die($content);
}
I suggest reading this: Detecting Ajax Events on the Server.
Is there other content on the mainpage that you could reference from the content.php file to verify that you are loading it as part of the mainpage and not a stand alone page? You could also pass something via a session from the mainpage into the content.php page and then remove the item at the end of loading of the content.php.
If the URL is accessible with AJAX request then it can be accessed directly and there is not much you can do about it. You can try to detect if a request is the AJAX request with:
function isAjaxRequest() {
return array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
}
and check for it in the beginning of the script:
if (!isAjaxRequest())
die('Access Denied');
but you shouldn't rely on this check too much because it's rather easy to bypass.
I have several forms brought in via jQuery .ajax funciton. In the parent page I start a session like this
<php
session_start();
$_SESSION['authenticated'] = 'yes';
?>
then in the form that is loaded have a check like this:
<?php
session_start();
if($_SESSION['authenticated'] != 'yes') {
header("Location: http://www.google.com");
}
?>
I know its not the best, but it's an attempt to stop people form accessing the forms directly. The problem is that if you go to the parent page, then you can enter the form URL and get there because the session was started when you hit the parent page. How can I destroy the session or remedy this issue?
Effectively, you can't.
To make it more complicated, don't request the form URLs directly. Try to request authorize tokens per request of the main page:
If you generate the main page and you know the form to be requested beforehand, then generate tokens e.g. using md5(time().rnd()), associate each with one you your forms and save the association in your session
Then, your JS code won't request the form URLs, but a factory script using a token injected into the JS code
If you find the token in your saved association in your session, emit the form and delete the token in your session.
This way, each form can only be requested once by one preceding call of the main page.
Note, that this isn't fully safe too: If a user requests the URL of the main page using wget, he can request each form once.
You can check $_SERVER['HTTP_REFERER'] in your form .php code to see where the request is coming from. An AJAX call will set the HTTP_REFERER to the page it is called from.
if (strpos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) === false) {
die();
}
It's not a bulletproof solution. Any page that is publicly accessible can be retrieved by an automated script.