Ich war in der gleichen Situation. Ich habe auch verkettete Anweisungen verwendet, dann habe ich meine Anwendung auf vorbereitete Anweisungen umgestellt.
die schlechte Nachricht werden Sie jede SQL-Anweisung ändern, die durch Verketten von Client-Daten mit der SQL-Anweisung erstellt wurde, was fast jede SQL-Anweisung sein wird, die Sie in Ihren 50 Quelldateien haben.
die gute Nachricht Der Gewinn durch die Umstellung auf vorbereitete Anweisungen ist unbezahlbar, zum Beispiel:
1-Sie werden sich nie Sorgen um einen sogenannten „SQL-Injection-Angriff“ machen
das PHP Handbuch sagt
Für mich reicht dieser Grund – Seelenfrieden – aus, um die Kosten für die Änderung meines Quellcodes zu bezahlen. , jetzt können Ihre Kunden in ein Formularnamensfeld robert; DROP table students; -- ;)
und Sie fühlen sich sicher, dass nichts passieren wird
2- Sie müssen die Client-Parameter nicht mehr maskieren. Sie können sie direkt in der SQL-Anweisung verwenden, z. B. :
$query = "SELECT FROM user WHERE id = ?";
$vars[] = $_POST['id'];
statt
$id = $mysqli->real_escape_string($_POST['id']);
$query = "SELECT FROM user WHERE id = $id";
was Sie tun mussten, bevor Sie vorbereitete Anweisungen verwenden konnten, wodurch Sie Gefahr liefen, als normaler Mensch zu vergessen, einen Parameter zu maskieren. und alles, was ein Angreifer braucht, um Ihr System zu beschädigen, ist nur 1 Parameter ohne Escapezeichen.
Ändern des Codes
Normalerweise ist das Ändern der Quelldateien immer riskant und schmerzhaft, insbesondere wenn Ihr Softwaredesign schlecht ist und Sie keinen offensichtlichen Testplan haben. aber ich werde Ihnen sagen, was ich getan habe, um es so einfach wie möglich zu machen.
Ich habe eine Funktion erstellt, die jeder Datenbank-Interaktionscode verwenden wird, sodass Sie später an einer Stelle ändern können, was Sie möchten – diese Funktion – Sie können so etwas machen
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;
}
}
Jetzt können Sie diese Schnittstelle überall in Ihren Quelldateien verwenden, z. B. ändern wir Ihre aktuellen SQL-Anweisungen, die Sie in der Frage angegeben haben. Lassen Sie uns das ändern
$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;
}
}
In diese
$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;
}
Ja, der SQL-Injection-Angriff wird angewendet, indem fehlerhafte Zeichenfolgen mit Ihrer SQL-Anweisung verkettet werden. wo es ein INSERT
ist , SELECT
, DELETE
, UPDATE
. zum Beispiel
$query = "SELECT * FROM user WHERE name = '{$_GET['name']}' AND password = '{$_GET['pass']}'"
so etwas könnte von
ausgenutzt werden// exmaple.com?name=me&pass=1' OR 1=1; --
was zu einer SQL-Anweisung führt
$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
Viel Glück beim Umstellen Ihrer Software auf vorbereitete Anweisungen, und denken Sie daran, dass die Gewissheit, dass Sie in jedem Fall vor SQL-Injection-Angriffen sicher sind, die Kosten für die Änderung der Quelldateien wert ist