Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Beralih ke Pernyataan yang Disiapkan

Saya telah berada dalam situasi yang sama. Saya juga menggunakan pernyataan bersambung, lalu saya mengalihkan aplikasi saya ke pernyataan yang sudah disiapkan.

kabar buruknya apakah Anda akan mengubah setiap pernyataan SQL yang dibuat dengan menggabungkan data klien ke pernyataan SQL, yang hampir akan menjadi setiap pernyataan SQL yang Anda miliki di 50 file sumber Anda.

kabar baik adalah keuntungan dari beralih ke pernyataan siap tak ternilai harganya, misalnya:

1-Anda tidak akan pernah khawatir tentang sesuatu yang disebut "Serangan SQL Injection"

php manual mengatakan

Bagi saya, alasan itu -ketenangan pikiran- sudah cukup untuk membayar biaya mengubah kode sumber saya. , sekarang klien Anda dapat mengetikkan bidang nama formulir robert; DROP table students; -- ;) dan Anda merasa aman bahwa tidak akan terjadi apa-apa

2- Anda tidak perlu keluar dari parameter klien lagi. anda dapat langsung menggunakannya dalam pernyataan SQL, seperti :

$query = "SELECT FROM user WHERE id = ?";
$vars[] = $_POST['id'];

bukannya

$id = $mysqli->real_escape_string($_POST['id']);
$query = "SELECT FROM user WHERE id = $id";

yang merupakan sesuatu yang harus Anda lakukan sebelum menggunakan pernyataan yang telah disiapkan, yang menempatkan Anda dalam bahaya lupa untuk melarikan diri dari satu parameter sebagai manusia normal. dan yang diperlukan penyerang untuk merusak sistem Anda hanyalah 1 parameter yang tidak dapat lolos.

Mengubah Kode

biasanya mengubah file sumber selalu berisiko dan menyakitkan, terutama jika desain perangkat lunak Anda buruk dan jika Anda tidak memiliki rencana pengujian yang jelas. tapi saya akan memberi tahu Anda apa yang saya lakukan untuk membuatnya semudah mungkin.

Saya membuat fungsi yang akan digunakan oleh setiap kode interaksi basis data, sehingga Anda dapat mengubah apa yang Anda inginkan nanti di satu tempat -fungsi itu- Anda dapat membuat sesuatu seperti ini

class SystemModel
{
    /**
     * @param string $query
     * @param string $types
     * @param array $vars
     * @param \mysqli $conn
     * @return boolean|$stmt
     */
    public function preparedQuery($query,$types, array $vars, $conn)
    {
        if (count($vars) > 0) {
            $hasVars = true;
        }
        array_unshift($vars, $types);
        $stmt = $conn->prepare($query);
        if (! $stmt) {
            return false;
        }
        if (isset($hasVars)) {
            if (! call_user_func_array(array( $stmt, 'bind_param'), $this->refValues($vars))) {
                return false;
            }
        }
        $stmt->execute();
        return $stmt;
    }

    /* used only inside preparedQuery */
    /* code taken from: https://stackoverflow.com/a/13572647/5407848 */
    protected function refValues($arr)
    {
        if (strnatcmp(phpversion(), '5.3') >= 0) {
            $refs = array();
            foreach ($arr as $key => $value)
                $refs[$key] = &$arr[$key];
                return $refs;
        }
        return $arr;
    }
}

Sekarang, Anda dapat menggunakan antarmuka ini di mana pun Anda inginkan dalam file sumber Anda, misalnya mari kita ubah pernyataan SQL Anda saat ini yang telah Anda berikan dalam pertanyaan. Mari kita ubah ini

$mysqli = new mysqli('localhost', "root", "", "testdb");
$addresult = "
                SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined 
                FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id 
                WHERE b.id = '".$inputvalues['schoolid']."'";

if( $result = $mysqli->query($addresult) ) {
    while($row = $result->fetch_all())
    {
        $returnResult = $row;
    }
}

Ke dalam ini

$mysqli = new mysqli('localhost', "root", "", "testdb");
$sysModel = new SystemModel();
$addresult = "
                SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined
                FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id
                WHERE b.id = ?";
$types = "i"; // for more information on paramters types, please check :
//https://php.net/manual/en/mysqli-stmt.bind-param.php
$vars = [];
$vars[] = $inputvalues['schoolid'];

$stmt = $sysModel->preparedQuery($addresult, $types, $vars, $mysqli);
if (!$stmt || $stmt->errno) {
   die('error'); // TODO: change later for a better illustrative output
}
$result = $stmt->get_result();
$returnResult = [];
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
    $returnResult[] = $row;
}

Ya, serangan Injeksi Sql diterapkan dengan menggabungkan string buruk ke pernyataan SQL Anda. di mana itu adalah INSERT , SELECT , DELETE , UPDATE . misalnya

$query = "SELECT * FROM user WHERE name = '{$_GET['name']}' AND password = '{$_GET['pass']}'"

sesuatu seperti itu bisa dimanfaatkan oleh

// exmaple.com?name=me&pass=1' OR 1=1; -- 

yang akan menghasilkan pernyataan SQL

$query = "SELECT * FROM user WHERE name = 'me' AND password = '1' OR 1=1; -- '"
//executing the SQL statement and getting the result
if($result->num_rows){
    //user is authentic
}else{
    //wrong password
}
// that SQL will always get results from the table which will be considered a correct password

Semoga berhasil dengan mengalihkan perangkat lunak Anda ke pernyataan yang sudah disiapkan, dan ingat bahwa ketenangan pikiran yang akan Anda dapatkan dari mengetahui bahwa apa pun yang terjadi, Anda aman dari serangan injeksi SQL sepadan dengan biaya yang harus dikeluarkan untuk mengubah file sumber




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Memilih rentang tanggal MySQL dengan date_format

  2. Hitung persentil di MySQL berdasarkan total

  3. Tampilkan gambar BLOB Laravel 4

  4. MySQL group_concat_max_len dalam kueri

  5. mysql pilih dari n baris terakhir