0

I'm using mysqli_real_escape_string to stop sql injections but I read that this is not full proof and am trying to add more security for this insert into database code. I'm fairly new to php but need to use it for this particular project. I have been reading about other methods but am not sure of the right way to insert these methods or if I should use another sanitizing feature. Below is my code any suggestions will help me in my attempt to provide the best security for this program.

<?php

$servername = "localhost";
$username = "hidden";
$password = "hidden";
$db = "hidden";

//Connection using MySQLi Object oriented
$conn = new mysqli($servername, $username, $password, $db);

//If connection fails give error
if ($conn->connect_error){
    die("Connection failed: ". $conn->connect_error);
}

//Defined variable for success message
$sucess = "";
//Check if form submit button submitted
if(isset($_POST['submit'])){

    //Set-up variable to be inserted in table and add escape string using mysqli function for security purposes
    $name = $conn->real_escape_string($_POST['name']);
    $issue = $conn->real_escape_string($_POST['issue']);
    $solution = $conn->real_escape_string($_POST['solution']);
    $os = $conn->real_escape_string($_POST['os']);
    $category = $conn->real_escape_string($_POST['category']);

    // Define three database tables based on the os chosen
    if($os == "Windows"){
        $table = "windows";
    }elseif($os == "Linux"){
        $table = "linux";
    }elseif($os == "macOS"){
        $table = "macos";
    }

    // Define category options to be chosen
    if($category == "Backup"){
        $category = "Backup";
    }elseif($category == "Database"){
        $category = "Database";
    }elseif($category == "Hardware"){
        $category = "Hardware";
    }elseif($category == "Internet"){
        $category = "Internet";
    }elseif($category == "Networking"){
        $category = "Networking";
    }elseif($category == "Security"){
        $category = "Security";
    }elseif($category == "Servers"){
        $category = "Servers";
    }elseif($category == "Software"){
        $category = "Software";
    }
    //Inserts into database based on chosen os, name, issue, category in respective table 
    $sql = "insert into $table (name,issue,solution,os,category) values('$name','$issue','$solution','$os','$category')";

    //Check if record inserted then assign success msg to variable and print.
    if ($conn->query($sql) === TRUE) {
        //echo "ADDED: $name .", ". $issue .", ". $solution .", ". $os .", ". $category";
        $sucess = "Solution successfully saved!!";
    } else {
        //Insert failure error
        echo "Error: ".$sql."<br>".$conn->error;
    }

    //close connection
    $conn->close();

}
?>

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Insert Solutions Database</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />  
           <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>  
           <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> 
    </head>
    <body>
        <h1>Insert Solutions Database</h1>
        
         <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="POST">
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>Issue Name :</th>
                        <td><input type="text" name="name" value="" size="50" /></td>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <th>Issue :</th>
                        <td><input type="text" name="issue" value="" size="50" /></td>
                    </tr>
                    <tr>
                        <th>Solution :</th>
                        <td><input type="text" name="solution" value="" size="50" /></td>
                    </tr>
            <tr>
                        <th>Operating System :</th>
                        <td>
            <select name="os">
            <option value="">Please select os</option>  
            <option value="Windows">Window</option> 
            <option value="Linux">Linux</option>
            <option value="macOS">MacOS</option>
            </select>
            </td>
                    </tr>
        <tr>
                        <th>Category :</th>
            <td>
            <select name="category">
            <option value="">Please select category</option>
            <option value="Backup">Backup</option>
            <option value="Database">Database</option>
            <option value="Hardware">Hardware</option>
            <option value="Internet">Internet</option>
            <option value="Networking">Networking</option>
            <option value="Security">Security</option>
            <option value="Servers">Servers</option>
            <option value="Software">Software</option>
                        </td>
                    </tr>
                </tbody>
            </table>   
            <br>
        <!-- <input type="reset" value="Clear" name="clear" /> -->
<a href="connect.php" class="btn btn-info mb-2" style="margin-top: 22px">Clear</a>
            <input type="submit" class="btn btn-info mb-2" value="Submit" name="submit" style="margin-top: 22px">
    </form>

<!-- If record inserted successfully then it shoud print success message -->
    <?php if(isset($sucess)){
        echo "<h1>$sucess</h1>";
    } ?>
</body>
</html>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Anyonomiss
  • 25
  • 5
  • 1
    You are over-complicating it. Just use prepared statements, https://phpdelusions.net/mysqli#prepare – Your Common Sense Oct 12 '22 at 13:49
  • 1
    The way you are using it might be safe, but you are creating a messy code that would be very easy to introduce SQL injection. Why risk it? Why not go for the easier solution of prepared statements? – Dharman Oct 12 '22 at 13:52
  • 2
    If you are only starting to learn PHP then you should learn PDO instead of mysqli. PDO is much easier and more suitable for beginners. Start here https://phpdelusions.net/pdo & https://websitebeaver.com/php-pdo-prepared-statements-to-prevent-sql-injection. Here are some good video tutorials https://youtu.be/2eebptXfEvw & https://www.youtube.com/watch?v=sVbEyFZKgqk&list=PLr3d3QYzkw2xabQRUpcZ_IBk9W50M9pe- – Dharman Oct 12 '22 at 13:53
  • 2
    Also, please forget the word "sanitize". It's highly ambiguous and doesn't mean anything good. If you need to remove some part of data, do it for business reasons, not because of security reasons. https://kevinsmith.io/sanitize-your-inputs/ – Dharman Oct 12 '22 at 13:54
  • 3
    Besides, it must be only **one** table, where `os` being a column – Your Common Sense Oct 12 '22 at 13:54
  • 1
    Learn about database normalisation - as the above comment implies, having multiple tables with the same set of columns is a design mistake. They can all be one table, and instead of differentiating between the data by using a different table name, just add another column to the table to store that information. Then you'll find it's a lot simpler to write queries against it. – ADyson Oct 12 '22 at 13:56
  • 1
    P.S. This `if($category == "Backup"){ $category = "Backup";`...and all the similar elseif's underneath it, are literally pointless. You're saying "if category equals backup, then make category equal backup". So basically you're making it set the variable to the exact same value it already has. I'm not really clear what you were thinking the purpose of that block of code was. – ADyson Oct 12 '22 at 13:58
  • 1
    Another tip: Add `mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);` before your `mysqli_connect()` (or `new mysqli()`) command, and this will ensure that errors with your SQL queries are reported correctly to PHP automatically, without you needing to have the tedious clutter of error-checking code after every mysqli command. – ADyson Oct 12 '22 at 13:59
  • Thank you for the MYSQLI_REPORT_ERROR before the connect(). The category == "Backup" is for purposes that aren't displayed in this code and have a purpose for the user to chose the categories that are listed. They will later be used for searches because this program is part of another program I am developing that searches specific categories. – Anyonomiss Oct 12 '22 at 14:38
  • If I just use prepared statements, don't I still need to restrict certain types of input into the database? – Anyonomiss Oct 12 '22 at 14:40
  • 1
    `have a purpose for the user to chose the categories that are listed`...sure, but the specific code you've shown literally does nothing. You'd get the same result by removing all of those `ifs`. – ADyson Oct 12 '22 at 15:21
  • 1
    `don't I still need to restrict certain types of input into the database`...in what way, do you think? I'm not really sure what specifically you're concerned about? As long as you don't do something silly like try to put text into a date field or a number field then you should be fine (but those sorts of mistakes would be nothing to do with prepared statements or SQL injection anyway). – ADyson Oct 12 '22 at 15:25
  • I think I understand now. I do know what you are saying about the categories. They don't do anything because I'm not finished with that part of the code yet. However, they will filter results based on the specific category. – Anyonomiss Oct 12 '22 at 16:01
  • `they will filter results based on the specific category` ...filter the results of what? Your code is inserting data, not searching or filtering it. If you're planning on some search functionality, that's probably something to put in a separate function in your code, away from the insert code. Unless you mean you want to filter the list of categories which appears in the dropdown in your form, or something? – ADyson Oct 12 '22 at 16:02
  • No you don’t understand because I need the category involved so rather than input it. I can just use a selection. – Anyonomiss Oct 12 '22 at 22:21

0 Answers0