Unicode bypass form sanitization and validation?

0

Issue

This is what I have right now but while "stress testing" it. I found out that you can access index.php when you use Unicode for both username and password such as this string " ◌󠇯◌󠇯◌󠇯◌󠇯 "

register here https://constitutive-return.000webhostapp.com/register.php with ◌󠇯◌󠇯◌󠇯◌󠇯 for both username and password then it would result to error but after that if you
goto https://constitutive-return.000webhostapp.com/index.php it show you you the content of index.php but the account ◌󠇯◌󠇯◌󠇯◌󠇯 is not added the database

also while I’m at it I tested username and password for this string " @#$@#4 " it work’s as intended it would do… it was added to the database you can also log in with it

now my question is does adding regex might solve this? I’m using DEFAULT CHARSET = latin1 or should I use UTF-8 instead but I’m worried UTF8 make it more vulnerable on SQLi? or what approach should I take?

register.php

<?php

$username = "";
$email    = "";
$password = "";
$confirm_password = "";
$errors = array();

$db = mysqli_connect('localhost', 'id18172750_root', 'VHUhd}ai%N?4EW2K', 'id18172750_auth');
// host, username, password, dbname

if (isset($_POST['create_account'])) {
    $username = mysqli_real_escape_string($db, $_POST['username']);
    $email = mysqli_real_escape_string($db, $_POST['email']);
    $password = mysqli_real_escape_string($db, $_POST['password']);
    $confirm_password = mysqli_real_escape_string($db, $_POST['confirm_password']);

    if (empty($username)) {
        array_push($errors, "Username is required.");
    }
    if (empty($email)) {
        array_push($errors, "Email is required.");
    }
    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
        // valid email do nothing
    } else {
        array_push($errors, "Enter a valid email.");
    }
    if (empty($password)) {
        array_push($errors, "Password is required.");
    }
    /*
  if ($password != $confirm_password) {
    array_push($errors, "Those passwords didn't match. Try again.");
  }
  */
    if (strcmp($password, $confirm_password) !== 0) {
        array_push($errors, "Those passwords didn't match. Try again.");
    }
    $agree = filter_input(INPUT_POST, 'vCpF', FILTER_SANITIZE_STRING);
    if ($agree) {
        // do nothing
    } else {
        array_push($errors, "You must read and agree to the Terms and Conditions agreement.");
    }

    if (strlen($username) < 4) {
        array_push($errors, "Username must be 4-32 characters.");
    }
    if (strlen($username) > 32) {
        array_push($errors, "Username must be 4-32 characters.");
    }
    if (strlen($email) < 4) {
        array_push($errors, "Email must be 4-32 characters.");
    }
    if (strlen($email) > 32) {
        array_push($errors, "Email must be 4-32 characters.");
    }
    if (strlen($password) < 4) {
        array_push($errors, "Password must be 4-32 characters.");
    }
    if (strlen($password) > 32) {
        array_push($errors, "Password must be 4-32 characters.");
    }

    $user_check_query = "SELECT * FROM users WHERE username='$username' OR email='$email' LIMIT 1";
    $result = mysqli_query($db, $user_check_query);
    $user = mysqli_fetch_assoc($result);

    if ($user) {
        if ($user['username'] === $username) {
            array_push($errors, "That username is taken. Try another.");
        }

        if ($user['email'] === $email) {
            array_push($errors, "That email is already connected to an account!");
        }
    }

    if (count($errors) == 0) {
        $hashed_password = password_hash($password, PASSWORD_BCRYPT);

        $query = "INSERT INTO users (username, email, password) 
              VALUES('$username', '$email', '$hashed_password')";
        mysqli_query($db, $query);
        $_SESSION['username'] = $username;
        header('location: index.php');
        die("Your account has been created successfully!");
    }
}

Solution

This:

    if (count($errors) == 0) {
        $hashed_password = password_hash($password, PASSWORD_BCRYPT);

        $query = "INSERT INTO users (username, email, password) 
              VALUES('$username', '$email', '$hashed_password')";
        mysqli_query($db, $query);
        $_SESSION['username'] = $username;
        header('location: index.php');
        die("Your account has been created successfully!");
    }

Change to this:

    if (count($errors) == 0) {
        $hashed_password = password_hash($password, PASSWORD_BCRYPT);

        $query = "INSERT INTO users (username, email, password) 
              VALUES('$username', '$email', '$hashed_password')";
        if(mysqli_query($db, $query)){
         $_SESSION['username'] = $username;
         header('location: index.php');
         exit;
        }
    }

What’s happening is your query is failing but the script continues and sets the session which then results in the user being seen as logged in.

I am going to say this as nicely as I can but this is very poor coding if you are new then good job you just discovered what not to do and next time please check your code as thats almost the number one rule of coding with any lang is check for error and success always and i MEAN ALWAYS check if your database query was successful.

But your code is very clean, easy to read and you are using comments and you are doing stuff like stress test etc… which is good just try and work on your database skills a bit more i recommend cheking w3schools and my fav teacher Dani Krossing on youtube previous name mmtuts

Hope you have a great day or night and dont give up! you are just learning even i did this mistake when i started.

EDIT:::
I updated some of your code now everything should work fine

if (isset($_POST['create_account'])) {
    $username = $_POST['username'];
    $email = $_POST['email'];
    $password = $_POST['password'];
    $confirm_password = $_POST['confirm_password'];
    $check_err = 0;

    if (empty($username)) {
        array_push($errors, "Username is required.");
        $check_err = 1;
    }
    if (empty($email)) {
        array_push($errors, "Email is required.");
        $check_err = 1;
    }
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        array_push($errors, "Enter a valid email.");
        $check_err = 1;
    }
    if (empty($password)) {
        array_push($errors, "Password is required.");
        $check_err = 1;
    }
    /*
  if ($password != $confirm_password) {
    array_push($errors, "Those passwords didn't match. Try again.");
        $check_err = 1;
  }
  */
    if (strcmp($password, $confirm_password) !== 0) {
        array_push($errors, "Those passwords didn't match. Try again.");
        $check_err = 1;
    }
    $agree = filter_input(INPUT_POST, 'vCpF', FILTER_SANITIZE_STRING);
    if ($agree) {
        // do nothing
    } else {
        $check_err = 1;
        array_push($errors, "You must read and agree to the Terms and Conditions agreement.");
    }

    if (strlen($username) < 4) {
        $check_err = 1;
        array_push($errors, "Username must be 4-32 characters.");
    }
    if (strlen($username) > 32) {
        $check_err = 1;
        array_push($errors, "Username must be 4-32 characters.");
    }
    if (strlen($email) < 4) {
        $check_err = 1;
        array_push($errors, "Email must be 4-32 characters.");
    }
    if (strlen($email) > 32) {
        $check_err = 1;
        array_push($errors, "Email must be 4-32 characters.");
    }
    if (strlen($password) < 4) {
        $check_err = 1;
        array_push($errors, "Password must be 4-32 characters.");
    }
    if (strlen($password) > 32) {
        $check_err = 1;
        array_push($errors, "Password must be 4-32 characters.");
    }

    if($check_err === 0){
    $stmt = $conn->prepare("SELECT * FROM users WHERE username = ? OR email = ? LIMIT 1");
    $stmt->bind_param("ss", $username, $email);
    $stmt_results = $stmt->get_result(); // get result
    $row_get_user = $stmt_results->fetch_assoc();

    if ($stmt_results->num_rows > 0) {
        if ($row_get_user['username'] === $username) {
            array_push($errors, "That username is taken. Try another.");
        }

        if ($row_get_user['email'] === $email) {
            array_push($errors, "That email is already connected to an account!");
        }
    }

    if (count($errors) == 0) {
        $hashed_password = password_hash($password, PASSWORD_BCRYPT);

        $stmt = $conn->prepare("INSERT INTO users (username, email, password) 
              VALUES(?, ?, ?)");
        $stmt->bind_param("sss", $username, $email, $hashed_password);
        $stmt_results = $stmt->store_result(); // store result

        if($stmt_results->affected_rows > 0){
         $_SESSION['username'] = $username;
         header('location: index.php');
         exit;
        }
    }
   }
}

Please try this code and tell me if any errors happen from what i can see i cleaned all your mistakes 🙂 and it should work fine now.

Answered By – DB_cont

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave A Reply

Your email address will not be published.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More