CSRF protections cause "Invalid or Unexpected Token" error - javascript

I am trying to integrate CSRF protection on my forms, and I have started with my registration form that started out working before the CSRF tokens were added, but now just produce a "Invalid or Unexpected Token" error. Here is my current form:
<form method="post" name="registration_form" action="<?php echo esc_url($_SERVER['PHP_SELF']); ?>">
<input type="hidden" name="<?= $token_id; ?>" value="<?= $token_value; ?>" />
First Name: <input type="text" name='<?=$form_names['firstname'];?>' id='firstname' /><br>
Last Name: <input type="text" name='<?=$form_names['lastname'];?>' id='lastname' /><br>
Phone: <input type="tel" name='<?=$form_names['phone'];?>' id='phone' /><br>
Email: <input type="email" name="<?=$form_names['email'];?>" id="email" /><br>
Username: <input type="text" name='<?=$form_names['username'];?>' id='username' /><br>
Password: <input type="password"
name="<?=$form_names['password'];?>"
id="password"/><br>
Confirm password: <input type="password"
name="<?=$form_names['passwordconf'];?>"
id="confirmpwd" /><br>
<input type="button"
value="Register"
onclick="return regformhash(this.form,
this.form.<?=$form_names['firstname'];?>,
this.form.<?=$form_names['lastname'];?>,
this.form.<?=$form_names['phone'];?>,
this.form.<?=$form_names['username'];?>,
this.form.<?=$form_names['email'];?>,
this.form.<?=$form_names['password'];?>,
this.form.<?=$form_names['passwordconf'];?>);" />
</form>
</body>
I have included a hidden field with a name/value pair token, as well as random tokens for each name field. The tokens all work as intended, so the issue isn't in generating them. There is also a Javascript file that validates form entry, I don't know if it is relevant, but here is the js validation:
function regformhash(form, firstname, lastname, phone, username, email, password, confirmpwd) {
// Check each field has a value
if (firstname.value == '' || lastname.value == '' || phone.value == '' || email.value == '' || password.value == '' || confirmpwd.value == '') {
alert('You must provide all the requested details. Please try again');
return false;
}
// Check the First Name
re = /^[A-Za-z\s]+$/;
if(!re.test(form.firstname.value)) {
alert("First Name must contain only upper and lower case letters. Please try again");
form.firstname.focus();
return false;
}
// Check the Last Name
re = /^[A-Za-z\s]+$/;
if(!re.test(form.lastname.value)) {
alert("Last Name must contain only upper and lower case letters. Please try again");
form.lastname.focus();
return false;
}
// Check the Phone Number
re = /\d{3}[\-]\d{3}[\-]\d{4}/;
if(!re.test(form.phone.value)) {
alert("Phone Number must be formatted as follows, xxx-xxx-xxxx or (xxx) xxx-xxxx. Please try again");
form.phone.focus();
return false;
}
// Check the username
re = /^\w+$/;
if(!re.test(form.username.value)) {
alert("Username must contain only letters, numbers and underscores. Please try again");
form.username.focus();
return false;
}
// Check that the password is sufficiently long (min 6 chars)
// The check is duplicated below, but this is included to give more
// specific guidance to the user
if (password.value.length < 6) {
alert('Passwords must be at least 6 characters long. Please try again');
form.password.focus();
return false;
}
// At least one number, one lowercase and one uppercase letter
// At least six characters
var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/;
if (!re.test(password.value)) {
alert('Passwords must contain at least one number, one lowercase and one uppercase letter. Please try again');
return false;
}
// Check password and confirmation are the same
if (password.value != confirmpwd.value) {
alert('Your password and confirmation do not match. Please try again');
form.password.focus();
return false;
}
// Create a new element input, this will be our hashed password field.
var p = document.createElement("input");
// Add the new element to our form.
form.appendChild(p);
p.name = "p";
p.type = "hidden";
p.value = hex_sha512(password.value);
// Make sure the plaintext password doesn't get sent.
password.value = "";
confirmpwd.value = "";
// Finally submit the form.
form.submit();
return true;
}
I don't know if the parameter names need to match up with the form names, they didn't all before and it worked.
Finally, the "Invalid or Unexpected Token" error was pointing to the closing </body>, if that helps as well.
Update:
I'm going to go more in depth about how this particular CSRF is working for this particular form. The form has an include to another php file, called register.inc.php, that does a series of sanitizations when adding data to the database, but I decided to also use it for the CSRF check. Here is the base code that relates to the CSRF (note, I haven't added the sanitization functions inside of the if statement yet, I'm trying to get the form to work without it before I add it in. I have a comment where it will eventually go):
include 'csrf.class.php';
require 'Sessions/session.class.php';
$session = new session();
// Set to true if using https
$session->start_session('_s', false);
$csrf = new csrf();
// Generate Token Id and Valid
$token_id = $csrf->get_token_id();
$token_value = $csrf->get_token($token_id);
// Generate Random Form Names
$form_names = $csrf->form_names(array('firstname','lastname','phone','email', 'username', 'password','passwordconf'), false);
if(isset($_POST[$form_names['email']], $_POST[$form_names['password']])) {
// Check if token id and token value are valid.
if($csrf->check_valid('post')) {
// Get the Form Variables.
// Add Sanitization function here
}
// Regenerate a new random value for the form.
$form_names = $csrf->form_names(array('email', 'password'), true);
}
Here is the csrf.class.php that is being referenced here:
<?php
class csrf{
public function get_token_id() {
if(isset($_SESSION['token_id'])) {
return $_SESSION['token_id'];
} else {
$token_id = $this->random(10);
$_SESSION['token_id'] = $token_id;
return $token_id;
}
}
public function get_token() {
if(isset($_SESSION['token_value'])) {
return $_SESSION['token_value'];
} else {
$token = hash('sha512', $this->random(500));
$_SESSION['token_value'] = $token;
return $token;
}
}
public function check_valid($method) {
if($method == 'post' || $method == 'get') {
$post = $_POST;
$get = $_GET;
if(isset(${$method}[$this->get_token_id()]) && (${$method}[$this->get_token_id()] == $this->get_token())) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public function form_names($names, $regenerate) {
$values = array();
foreach ($names as $n) {
if($regenerate == true) {
unset($_SESSION[$n]);
}
$s = isset($_SESSION[$n]) ? $_SESSION[$n] : $this->random(10);
$_SESSION[$n] = $s;
$values[$n] = $s;
}
return $values;
}
private function random($len) {
if (function_exists('openssl_random_pseudo_bytes')) {
$byteLen = intval(($len / 2) + 1);
$return = substr(bin2hex(openssl_random_pseudo_bytes($byteLen)), 0, $len);
} elseif (#is_readable('/dev/urandom')) {
$f=fopen('/dev/urandom', 'r');
$urandom=fread($f, $len);
fclose($f);
$return = '';
}
if (empty($return)) {
for ($i=0;$i<$len;++$i) {
if (!isset($urandom)) {
if ($i%2==0) {
mt_srand(time()%2147 * 1000000 + (double)microtime() * 1000000);
}
$rand=48+mt_rand()%64;
} else {
$rand=48+ord($urandom[$i])%64;
}
if ($rand>57)
$rand+=7;
if ($rand>90)
$rand+=6;
if ($rand==123) $rand=52;
if ($rand==124) $rand=53;
$return.=chr($rand);
}
}
return $return;
}
}
When the form is submitted, it saves the CSRF tokens from the form in a Session and compares it to the Tokens in the Post value. If the two match, then it continues with the code. Here is the site I used to create the CSRF protection, Prevent CSRF.

Related

request.args.get() returns None

I am trying to check the users input on my login form.
I am sending an HTTP request to the server to check the database for the username.
Here is the network URL:
https://bceec5a5-eba3-49e3-b255-d3976d185fad-ide.cs50.xyz:8080/user_name?username=fabianomobono
Here's the html
<form id="login_form" action='/home' method='post'>
<input id="login_credentials_username" name='login_username' type='text' placeholder='Username' >
<input id="login_credentials_password" name='login_password' type='password' placeholder="Password" >
<button class="btn btn-primary" type='submit'>Log in</button>
</form>
This is the JS code:
$('#login_form').ready(function() {
$('#login_form').on('submit', function(e) {
e.preventDefault();
logincheck();
});
});
function logincheck(){
var username = document.getElementById("login_credentials_username").value;
var password = document.getElementById("login_credentials_password").value;
if (username == ''){
alert("no user");
return false;
}
else if (password == ''){
alert('no password');
return false;
}
else if (password && username){
alert(password + username);
console.log(username)
$.get('/user_name?username' + username, function(r){
if (r === false){
alert('python returned false');
return false;
}
else{
alert('python returned true');
return true;
}
});
return false;
}
else {
return true;
}
}
and here is the python function:
#app.route("/user_name", methods=["GET"])
def login_usercheck():
print(Fore.GREEN + "user_check function, line 171")
username = (request.args.get('login_username'),)
print(username)
conn = sqlite3.connect('database.db')
c = conn.cursor()
c.execute("SELECT username FROM users WHERE username =?", username)
old_user = c.fetchall()
if len(old_user) > 0:
return jsonify(True)
else:
return jsonify(False)
The problem is that my username variable in the python function always returns NULL. I tried all combinations of,(request.form.get, request.args.get... and so on)
Funny thing is I have a similar function to check for the register credentials and that one works just fine. I can't seem to figure out what the problem is...
Here's what I get in the terminal:
(None,)
192.168.164.98 - - [05/Nov/2019 17:54:01] "GET /user_name?username=cf HTTP/1.0" 200 -
username = request.args.get('username')
$.get('/user_name?username' + username,...
the bold parts need to match
it was pointed out to me by another user...

Javascript function to check the username and password fields and if they are not completed accordingly to stop

I've just started learning PHP and my teacher recommended I use JS to check the input fields for acording lentgh.
And if the fields are matching specifications to continue with the registration
How do I stop the php from running if RegistrationValidation() returns false ?
Submit button
<input type="button" name="Register" value="Register" onclick="RegistrationValidation()">
Registering the new user
<?php
if (isset($_POST['Register'])) {
include 'SQL.php';
$username = $_POST['username'];
$password = $_POST['password'];
NewUser($username, $password);
} else
echo '';
?>
Javascript function
function RegistrationValidation() {
var username = document.getElementById('username');
var password = document.getElementById('password');
var usererror = document.getElementById('usererror');
var passerror = document.getElementById('passerror');
var registration = document.getElementById('registrationCheck');
var username_check = true;
var password_check = true;
if (username.value.length < 6) {
var username_check = false;
usererror.innerHTML = 'Username must have at least 6 characters.';
} else {
usererror.innerHTML = '';
}
if (password.value.length < 6) {
var password_check = false;
passerror.innerHTML = 'Password must have at least 6 characters.';
} else {
passerror.innerHTML = '';
}
if (username_check == true && password_check == true) {
document.getElementById("myForm").submit();
} else {
return false;
registration.innerHTML = 'Retype username and password';
}
}
//
Your function returns false if the validation failed. So you can simply add an onsubmit handler to the form, using your function as the handler.
// put this before the close </body> tag or wrap it in window.onload = function(){ }
document.getElementById("yourform").onsubmit = RegistrationValidation;
This is better than using a click event on the button because the onsubmit handles other situations, such as the form being submitted via the enter key.
Remember you still need to do the same validation on the PHP side, because the JavaScript validation can easily be circumvented.

Javascript Email Validation Specific Domain with PHP data

There is something wrong in this line:
var reg = /^[a-z.]+'#'+javaScriptVar$/;
but I don't know how to correctly write this. The current code would make "Please enter Email Address" appear every time. Here are the codes:
<?
$em=$_POST['myemail'];
$ar=split("#",$em);
?>
function validateForm()
{
var x=document.forms["myForm"]["username"].value;
if (x==null || x=="")
{
alert("User Name must be filled out");
return false;
}
if (document.forms["myForm"]["email"].value.length == 0) {
alert("Please enter Email Address");
return false;
} else {
var javaScriptVar = "<?php echo $ar[1]; ?>";
var reg = /^[a-z.]+'#'+javaScriptVar$/;
if (!reg.test(document.forms["myForm"]["email"].value)) {
alert("Please Enter Correct Email Domain");
return false;
}
}
}
You seem to be trying to include an # in your regex to check for url validation. Since there are no quotes used around your regex, specifying it like +'#'+ will not work.
Change it to:
/^[a-z.]#javaScriptVar$/
EDIT:
I think you are using the wrong regex to validate the url. Try this:
/^[a-zA-Z0-9]+[#][a-zA-Z0-9]+.{1}[a-z]{3}$/

Prevent user from registering if username is taken

So my script perfectly checks whether username is free or not but regardless of that when user submits all forms he is able to register. I need a way to prevent user from registering if username is taken. Here is the code:
index.php
$("#username").keyup(function(){
var val=$("#username").val();
$("#address").html("Your address will be askfolio.com/" + val);
$("#freeu").html("<img src='css/ajax-loader.gif' style='margin-left:-75px;'>");
if (val != ''){
$.ajax({
url:"s/ufree.php",
method:"POST",
data:$("#username"),
success:function(data){
if (data == 1){
$("#freeu").html("<img src='css/accept.png' style='float:left;padding-right:65px;'>");
$("#reg-error").css("display","none");
}else{
$("#freeu").html('');
$("#reg-error").css("display","block");
$("#reg-error").html('Username is already taken, try another.');
$("#username").focus();
return false;
}
}
});
}else {
$("#freeu").html('');
}
});
function Users_Registration()
{
var reg = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
var name = $("#name").val();
var lastname=$("#lastname").val();
var username = $("#username").val();
var remail = $("#remail").val();
var rpass = $("#rpass").val();
var day=$("#day").val();
var month=$("#month").val();
var year=$("#year").val();
if(name == "")
{
$("#reg-error").css("display","block");
$("#reg-error").html('Please enter your name in the required field.');
$("#name").focus();
}
else if(lastname == "")
{
$("#reg-error").css("display","block");
$("#reg-error").html(' Please enter your Last Name in the required field.');
$("#lastname").focus();
}
else if(username == ""){
$("#reg-error").css("display","block");
$("#reg-error").html('Please enter your desired username to proceed.');
$("#username").focus();
}
else if(remail == "")
{
$("#reg-error").css("display","block");
$("#reg-error").html('Please enter your email address to proceed.');
$("#remail").focus();
}
else if(reg.test(remail) == false)
{
$("#reg-error").css("display","block");
$("#reg-error").html('Please enter a valid email address to proceed.');
$("#remail").focus();
}else if (rpass == "") {
$("#reg-error").css("display","block");
$("#reg-error").html('Please enter a valid password to proceed.');
$("#rpass").focus();
}
else if (day == ""){
$("#reg-error").css("display","block");
$("#reg-error").html('Please select a day to proceed.');
$("#day").focus();
}else if (month == "") {
$("#reg-error").css("display","block");
$("#reg-error").html('Please select a month to proceed.');
$("#month").focus();
}else if (year == "") {
$("#reg-error").css("display","block");
$("#reg-error").html('Please select a year to proceed.');
$("#year").focus();
}
else
{
var dataString = 'name='+ name + '&lastname='+ lastname + '&username='+ username + '&rpass='+ rpass + '&remail='+ remail + '&year=' + year + '&month=' + month + '&day=' + day +'&page=signup';
$.ajax({
type: "POST",
url: "register.php",
data: dataString,
cache: false,
beforeSend: function()
{
$("#reg-error").html('<br clear="all"><div style="padding-left:115px;"><font style="font-family:Verdana, Geneva, sans-serif; font-size:12px; color:black;">Please wait</font> <img src="images/loadings.gif" alt="Loading...." align="absmiddle" title="Loading...."/></div><br clear="all">');
},
success: function(response)
{
$("#reg-error").html("Loading");
var username="<?php echo $loguser; ?>";
window.location=username;
}
});
}
}
ufree.php
<?php
include "db.php";
if (isset($_POST['username'])) {
$username=$_POST['username'];
$sql=mysql_query("SELECT * FROM users WHERE username='$username'");
if (mysql_num_rows($sql) == 0) {
echo "1";
}else {
echo "<div style='padding-top:4px;'>username is taken</div>";
}
}
?>
Apart from the SQL Injection vulnerability that you have in your sql queries, your approach to username check is somewhat redundant. By checking the username upon every character input you add extra load to the browser and to your server.
I suggest you combine the two processes in one step meaning you do the username check and register in the same place. In your Register.php file check the username availability right before the registration and if the username is taken display a proper message and if not do the registration.
Goes without saying but regardless of the javascript validation, your server still needs to be checking that the username is available at point of registering, since anyone can disable or manipulate the javascript.
Also as Hamed states, your php code is highly vulnerable. At the very least, you should use the following prior to using it in your sql:
$username = mysql_real_escape_string( $_POST[ 'username' ] );
That said, for usability, what you need to do is add an onsubmit function to your form, which checks if the username is valid or not prior to submitting. (summarised your code for simplicity)
var validUser = false;
$("#username").keyup(function(){
var val=$("#username").val();
validUser = false;
if (val != ''){
$.ajax({
url:"s/ufree.php",
method:"POST",
data:val,
success:function(data){
if (data == 1){
validUser = true;
}else{
$("#username").focus();
return false;
}
}
});
}else {
$("#freeu").html('');
}
function formsubmit()
{
if( !validUser )
{
alert( 'Username is already taken, try another' );
return false;
}
return true;
}
Then in your form:
<form action="whatever" onsubmit="return formsubmit();">
...
</form>
Once of my favorite jQuery plugin is the validation eng.
https://github.com/posabsolute/jQuery-Validation-Engine
It has very nice validation for doing just what you are looking for. It does all kinds of fields including inline ajax for username check. If the response from ajax call is not true, then the form won't submit. I use it for my signup forms. Once the user goes to the next field it validates, if it doesn't pass i.e. the username is not available, it will say username not available in red. The form won't submit.
It's not hard to setup. Here is a demo of the ajax. Note it won't actually validate on this demo site but it's an example. You can see how it won't submit though if it's blank or not validated. It's very customizable.
http://www.position-relative.net/creation/formValidator/demos/demoAjaxSubmitPHP.html
Oh course take care of any mysql security issues and check to make sure dupes can't be entered into the database as well.

how to check inserted regex pattern is valid or not

Hi guys I have to create a demo project, to check if inserted regex pattern is valid or not.
I have one text box.
With help of this text-box, I am entering the regex for date, email, time, etc.
But I don't know how can I do this type of validation check.
Help me out with this.
This is my fiddle: http://jsfiddle.net/ygfQ8/9/
It's not perfect, but just a view of how I am checking the pattern using jquery.
$('input').on('blur',function(){
var str = $('input').val();
var first = '(';
var last = ')';
var get_first = str.charAt( str.length1 );
var get_last = str.charAt( str.length -1 );
if(first==get_first && last==get_last)
{
alert('patter is valid');
}
else
{
alert('pattern is invalid');
}
});
and html textbox is <input type='text'>
This is php working demo:
<?php
//this variable containg any string .... doesnt matter wat ?
$subject = 'This is some text I am searching in'; //simple testing string variable
$pattern = '(fdsfdsfdsfdsfsd'; // user inputed string
if(#preg_match($pattern, $subject) === false)
echo "YOU have entered wrong regex pattern";
else
echo "Great work ";
?>
This could suit your needs:
function isPatternValid(pattern) {
try {
"".match(new RegExp(pattern));
return true;
} catch (err) {
return false;
}
}
Calling with:
$('#input').blur(function() {
alert(isPatternValid(this.value));
});

Categories

Resources