1
votes

I want to prevent people to use cURL on my php files, and not only cURL, but every POST request come not from my website
I think about a way to do that, please tell me if that process is wrong.

I have a simple POST form, that do an action according to $_POST details:
form.php:

<?PHP
session_start();
session_regenerate_id();

if( isset($_POST['username']) && isset($_SESSION['pass']) )
{
    // start mysqli query to check the details
}
?>

That way, a client can use cURL and send a lot of POST requests to form.php,
and the if statement will always return true.

Now, I think about that way:
When a client is in my domain, I will create an unique token and save it in a session,
for example: $_SESSION['UID'] = getRandomToken();
This code will only run on a separate file named: createUID.php :

<?PHP
session_start();
session_regenerate_id();
$_SESSION['UID'] = getRandomToken();
?>

This code runs on every request in my website.

Now, here is the updated form.php:

<?PHP
session_start();
session_regenerate_id();

if( ! isset($_SESSION['UID']) )
{
    die('You are trying to use cURL.');
}

if( isset($_POST['username']) && isset($_SESSION['pass']) )
{
    // start mysqli query to check the details
}
?>

That way, when a client try to use cURL on form.php, he will need $_SESSION['UID'] to be setted in order to continue the code. When the user send a request to form.php via cURL, $_SESSION['UID'] is never setted, and so, the code will die.

In order to know if that technique is secure, I have one question: Is there anyway a client will send a request to createUID.php to set a $_SESSION['UID'], and then send a request to form.php with a $_SESSION['UID'] which already setted ? (and not only with cURL)

I tested that using 2 cURL requests:
test.php:

<?php
session_start();
session_regenerate_id();

$url = "http://localhost/createUID.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);

$url = "http://localhost/form.php";
$data = array('username' => 'admin', 'pass' => '123456');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);

?>

createUID.php:

<?php

session_start();
session_regenerate_id();
$_SESSION['UID'] = '456a4sd56a4s65d4as'; //example of a random token

echo 'session of createUID.php: ';
print_r( $_SESSION ); //will print 456a4sd56a4s65d4as
echo '<br /><br />';

?>

form.php:

<?php

session_start();
session_regenerate_id();

echo 'session of form.php: ';
print_r( $_SESSION ); //will print nothing
echo '<br /><br />';

if ( ! isset($_SESSION['UID']) )
{
    die('Not allowed');
}
?>

The result is if ( ! isset($_SESSION['UID']) ) will always return true.
What do you think?
Thanks!

1
Is there anyway a client will send a request to createUID.php to set a $_SESSION['UID'], and then send a request to form.php with a $_SESSION['UID'] which already setted ? yesIłya Bursov
You probably want to use a CSRF-token. See stackoverflow.com/questions/5207160/… .drkdsk

1 Answers

0
votes

You asked

Is there anyway a client will send a request to createUID.php to set a $_SESSION['UID'], and then send a request to form.php with a $_SESSION['UID'] which already setted ?

The answer is: Yes.

That wouldn't be difficult at all.

Using a CSRF token in your form would be a good way to deter this kind of thing. Or you could use a captcha to do a similar job.

CSRF is not totally unbeatable but it makes it far more difficult for the attacker. A captcha should be pretty much unbeatable by a non-human / non-browser client, but it also has a downside that it can often be intrusive for real users as well.


P.S. the reason your two-request cURL test appeared to work is that it probably created two separate sessions. Browsers store session cookies (sent by the server) in their cache. When they next make a request to the same site (unless you close the browser first of course), they send back the session cookie to the server. That way the server knows which user is making the request, and associates it with the correct session data in the server's memory.

Your cURL code didn't do that, so it likely created 2 sessions on the server. However, it's entirely possible to implement that with cURL or any other HTTP client, which is why your idea won't prevent anything but the most naive attempts to call your script.