I'm trying to implement CSRF protection to a webform. Its a one page website that captures data, posts it to a PHP file which then emails me the information. The webpage functions as intended (minus the security).
I'm having the following issues:
token.php
<?php
session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];
?>
formsubmit.php
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!empty($_POST['token'])) {
if (hash_equals($_SESSION['token'], $_POST['token'])) {
$emailbody = 'Name: ' . $_POST['m_title'] . ' ' . $_POST['m_firstname'] . ' ' . $_POST['m_surname'] . "\n"
. 'Email: ' . $_POST['m_email'] . "\n"
. 'Phone: ' . $_POST['m_phone'] . "\n"
. 'D.O.B: ' . $_POST['m_dob_day'] . ' ' . $_POST['m_dob_month'] . ' ' . $_POST['m_dob_year'] . "\n"
. 'Postcode: ' . $_POST['m_postcode'] . "\n"
. 'Lenders: ' . $_POST['m_bank1'] . ',' . $_POST['m_bank2'] . ',' . $_POST['m_bank3'] . ',' . $_POST['m_bank4'] . ',' . $_POST['m_bank5'] . ',' . $_POST['m_bank6'] . ',' . $_POST['m_bank7'] . ',' . $_POST['m_bank8'];
mail('**removed**', 'Web Lead', $emailbody);
header('Location: **removed**/thankyou');
exit();
}
else {
echo "token invalid";
}
}
else {
echo "token blank";
}
}
else {
echo "invalid request";
}
?>
My jQuery attempt in index.html
<script>
$(document).ready(function() {
$.get('token.php');
});
</script>
Provided the PHP above is not riddled with errors, I had assumed that successfully converting it to index.php would resolve my issues, but I am having difficulty doing so.
There's a few problems with your code:
token.php
needs to output the token. Which is as simple as echo $token;
The main problem is that you've used the following jquery:
$(document).ready(function() {
$.get('token.php');
});
What this means is that when the page (index.html
) is loaded, your browser makes an ajax request to token.php
. However... nothing further happens. You're not actually doing anything with the response (output) from token.php
.
What you need to do is place the response from token.php
into your web page. Going off the code you've posted I assume there is a form field with the name "token"
? If this is the case then you would make the ajax request like this, which writes the response of token.php
to that field:
$(document).ready(function() {
$.get('token.php').done(function(data) {
$('input[name="token"]').val(data);
}).fail() {
// Handle ajax request failure here
});
)};
To answer your questions:
$_SESSION['token'] = bin2hex(random_bytes(32));
means that the variable $_SESSION['token']
contains your token. That's where you are setting it.
If you're getting a 403 error requesting token.php
in the ajax request this means that the server won't process that request. So it could be a permissions issue or some other problem. Try putting die('test');
at on the first line of the script and then executing /token.php
in your browser. Can you access it, or does it give you an error? If it's accessible it will say "test". Check the servers error log if you're unsure why you can't access it. Based on the code, it's unlikely that the URL to the script is wrong, or that'd give you a 404 error.
It's unclear why you're bothering with: "When I try and run the script in a 1-pixel iframe". I assume this is an attempt to write the response of token.php
back to the page. That can be solved by my answer above.