PHP - MySQLi parses request twice or incorrectly

I have this strange error that I do not understand at all. I have the following PHP script that behaves in two ways.

This shell script adds new users to the mysql database. What I want to do is check if the username is already in the database. If so, set the variable that is used to decide how to proceed. If I execute this code this line

if(strcmp($row["username"], $addUser_name) == 0)

      

is executed (or better injected), but I'm 100% sure that the name does NOT (or is not supposed to) exist in the database before this line is executed. Now, although the $ errorName is set to one and the test is printed, the dataset that I would like to add to my database happens in my database, but the last part that starts with

if(!isset($errorName))

      

not executed. I've tested it with simple echo expressions over and over.

To look at my dataset, I removed the comment in this part

while ($row = mysqli_fetch_assoc($allUserNames))
{
    echo $row["username"]."\n";
}

      

this part is done correctly

if(!isset($errorName))

      

but I find the dataset twice in my database.

I don't understand why the script behaves the way it does. I have tried many different things, but I cannot figure out what I am doing wrong.

<?php
    include "auth/auth1.php";
    include "functions/connectToDB.php";
    include "functions/test_input_XSS.php";

    if(isset($_GET["startCheck"])) //TODO Mache auch GET noch POST
    {
        //Sollte niemals true sein! Passiert nur, wenn man Unsinn macht
        if(strcmp($_GET["addUser_pw"], $_GET["addUser_pwRepeat"]) !== 0) { die; }

        $servername     = "localhost";
        $databasename   = "X";
        $mysqluser      = "X";
        $mysqlpass      = "X";
        $addUser_name   = $_GET["addUser_name"];

        $connection = connectToDB($servername, $mysqluser, $mysqlpass, $databasename);

        if(mysqli_connect_errno())
        {
            printf("Connect failed!");
            die();
        }

        $query_getAllUserNames = "SELECT username FROM user;";
        $allUserNames = mysqli_query($connection, $query_getAllUserNames);

        /*while ($row = mysqli_fetch_assoc($allUserNames))
        {
            echo $row["username"]."\n";
        }*/

        while ($row = mysqli_fetch_assoc($allUserNames))
        {
            if(strcmp($row["username"], $addUser_name) == 0)
            {
                $errorName = 1;
                echo "test";
            }
        }

        if(!isset($errorName))
        {
            $username = test_input_for_XSS($_GET["addUser_name"]);
            $password = hash("sha256", $_GET["addUser_pw"]);
            $permission = test_input_for_XSS($_GET["addUser_permission"]);

            $query_addUser = "INSERT INTO user (username, passwordhash, permissionlevel) VALUES ('".$username."', '".$password."', '".$permission."');";

            $addUserSuccess = mysqli_query($connection, $query_addUser);

            if($addUserSuccess !== 1)
            {
                $hostname = $_SERVER['HTTP_HOST'];
                $path = dirname($_SERVER['PHP_SELF']);
                echo"Success";
                //header("Location: http://".$hostname.($path == "/" ? "" : $path)."/userManagment.php?added=".$username."");
            }
            else
            {
                echo "ANNOYING_ERROR";
            }
        }

        //Tidy up
        mysqli_free_result($allUserNames);
        mysqli_close($connection);
    }
?>

      

This is the relevant HTML, following it in the same file:

        <?php
            include "home.php";
        ?>

        <section>
            <h3>Einen neuen Benutzer hinzufügen</h3>

            <?php
                if(isset($errorName))
                {
                    echo '<p class="warningMessage">Der Nutzername <b>'.$_GET["addUser_name"].'</b> ist bereits vergeben.<br />Bitte wählen Sie einen anderen aus!</p>';
                }
            ?>

            <form method="GET" action="addUser.php">
                <table>
                    <tr>
                        <td>Nutzername:</td>
                        <td><input type="text" name="addUser_name" required pattern="\w+" /></td>
                        <td></td>
                        <td class="annotation">z.B.: Vorname</td>
                    </tr>

                    <tr>
                        <td>Passwort:</td>
                        <td><input type="password" name="addUser_pw" required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}" title="Passwort muss mindestens 6 Zeichen, Groß- und Kleinbuchstaben, sowie Zahlen enthalten"
                                    onChange="this.setCustomValidity(this.validity.patternMismatch ? '' : ''); if(this.checkValidity()){ form.addUser_pwRepeat.pattern = this.value; }" /></td>
                        <td></td>
                        <td class="annotation">Muss Groß- und Kleinbuchstaben, Zahlen und mindestens 6 Zeichen enthalten</td>
                    </tr>
                    <tr>
                        <td>Passwort wiederholen:</td>
                        <td><input type="password" name="addUser_pwRepeat" required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}" /></td>
                        <td></td>
                        <td class="annotation">Muss identisch sein zum ersten eingegebenen Passwort</td>
                    </tr>
                    <tr>
                        <td>Berechtigungslevel:</td>
                        <td>
                            <input type="radio" name="addUser_permission" value="1" checked />1<br />
                            <input type="radio" name="addUser_permission" value="2" />2
                        </td>
                    </tr>
                </table>
                <input type="hidden" name="startCheck" value="1" />
                <input type="submit" value="Nutzer hinzufügen" class="button" />
            </form>
        </section>
    </body>
</html>

      

If my problem is not clear enough, I will happily provide any additional information that is required.

+3


source to share


2 answers


I would advise you not to fetch all usernames and check if there is the same username via PHP. You can just make a request like this

$result=$connection->query("SELECT username FROM user WHERE username='".$connection->real_escape_string($addUser_name)."';"); 

      



and then check if the query returns you any string

if($result -> num_rows > 0)
{
  //the username is already in use
}
else
{
  //the username is unique
}

      

+3


source


You check all the usernames in your database and loop through them in a while loop.

So, in each iteration, you rewrite the variable $errorName

for each username when you use the variable $errorName

outside the value of the scope variable for the last user in your result set.



What can you do,

$query_getAllUserNames = "SELECT count(*) FROM user where username=?"; 

if ($stmt = mysqli_prepare($connection, $query_getAllUserNames)) {
    /* bind parameters for markers */
    mysqli_stmt_bind_param($stmt, "s", $addUser_name);
    /* execute query */
    mysqli_stmt_execute($stmt);
    /* bind result variables */
    mysqli_stmt_bind_result($stmt, $userCount);
    /* fetch value */
    mysqli_stmt_fetch($stmt);
} 

if(!isset($userCount) || $userCount == 0) {
    //Create a new user here
    echo "Create new user";
} else {
    //Go with the flow
    echo "User exists";
}

//rest of your code 

      

+1


source







All Articles