addslashes 函式

  1. escape.php 如前例 injection.php,select 查詢時 $user 變數沒有加單引號。
    [root@kvm3 html]# vim escape.php
    [root@kvm3 html]# cat escape.php
    <?php
    $dbhost = 'localhost:3306';
    $dbuser = 'root';
    $dbpass = '123qwe';
    $user = $_GET['user'];
    $conn = mysqli_connect($dbhost, $dbuser, $dbpass)
    	or die(mysqli_connect_error().PHP_EOL);
    mysqli_select_db( $conn, 'mysql' )
    	or die('Error: '.mysqli_error($conn).PHP_EOL);
    $sql = "SELECT host,user FROM user WHERE user=$user";
    $retval = mysqli_query( $conn,$sql )
    	or die('Error: '.mysqli_error($conn).PHP_EOL);
    while($row = mysqli_fetch_array($retval, MYSQLI_NUM)) {
        echo "HOST: {$row[0]}<br>User: {$row[1]}<br>".
        "--------------------------------<br>";
    }
    mysqli_free_result($retval);
    echo "Fetched data successfully\n";
    mysqli_close($conn);
    ?>
    
  2. 查詢 user='root' 時,root 必須加單引號。
    [root@kvm3 html]# curl -s http://kvm3/escape.php?"user='root'" | sed 's/<br> */\n/g'
    HOST: localhost
    User: root
    --------------------------------
    Fetched data successfully
    
  3. 為避免使用者輸入一些如單引號等,可能進行 sql injection 的相關字元,可以使用 addslashes() 函式,將取得的字串中相關的字元加入倒斜線,也就是跳脫其作用。以下例子 escape1.php 是將上例 escape.php 的 $_GET['user'] 變數,先經過 addslashes() 函式處理後,再存入 $user 變數。
    [root@kvm3 html]# vim escape1.php
    [root@kvm3 html]# grep addslashes escape1.php
    $user = addslashes($_GET['user']);
    
  4. 再查詢 user='root' 時,出現錯誤,原因為單引號被加倒斜線跳脫了。
    [root@kvm3 html]# curl -s http://kvm3/escape1.php?"user='root'"
    Error: You have an error in your SQL syntax; check the manual that corresponds to
    your MariaDB server version for the right syntax to use near '\'root\'' at line 1
    
  5. 即使查詢 user=root ,也出現錯誤,原因為 root 沒有用單引號括起來。
    [root@kvm3 html]# curl -s http://kvm3/escape1.php?"user=root"
    Error: Unknown column 'root' in 'where clause'
    
  6. escape2.php 將 escape1.php 的 select 查詢,改成 user='$user',也就是單引號由程式自動加上,不要由使用用輸入。
    [root@kvm3 html]# grep '$user' escape2.php
    $user = addslashes($_GET['user']);
    $sql = "SELECT host,user FROM user WHERE user='$user'";
    
  7. 再使用 user=root,不加單引號查詢,正常輸出查詢結果。
    [root@kvm3 html]# curl -s http://kvm3/escape2.php?"user=root" | sed 's/<br> */\n/g'
    HOST: localhost
    User: root
    --------------------------------
    Fetched data successfully
    
  8. escape.php 的變數 $user$_GET['user'] 經 addslashes() 函式處理過,所以即使查詢變數改成 user=a' or 'a'='a,滿足其前後單引號的語法,也無法 sql injection 了。
    [root@kvm3 html]# curl -s http://kvm3/escape2.php?"user=a'%20or%20'a'='a"
    Fetched data successfully