Skydda PHP-serverbeteenden från SQL-injektionssårbarhet

Senast uppdaterad den 27 apr. 2021

Problem

Vissa databaser gör det möjligt för dig att skicka flera SQL-satser i en enda förfrågan. Därför finns det potentiella säkerhetsrisker när du skickar parametrar i en frågesträng till en dynamiskt genererad databasfråga. Hackare skulle kunna försöka ändra URL- eller formulärvariabler i en dynamisk fråga genom att lägga till skadliga SQL-satser till befintliga parametrar. Det här kallas ofta en SQL-injektering. En del av serverfunktionskoden som har skapats av Dreamweaver ska ändras för att minska risken för SQL-injektering. Mer bakgrundsinformation om SQL-injektioner finns i den här Wikipedia-artikeln. (Ref. 201713)

Obs: Problemet som beskrivs i denna TechNote har åtgärdats i Dreamweaver 8.0.2 Updater.

Denna TechNote täcker Dreamweavers PHP-serverbeteenden.Det finns separata TechNotes för ColdFusion, ASP VBScript, ASP JavaScript, och JSP serverbeteenden.ASP.NET-serverbeteendena påverkas inte.

Lösning

Se till att endast den förväntade informationen skickas när du tillåter en frågesträng skicka en parameter vidare. Adobe har skapat en Dreamweaver 8.0.2 Updater som minskar risken för SQL-injektionsattacker. Dessa korrigeringar kommer att ingå i alla framtida versioner av Dreamweaver.Efter att ha uppdaterat Dreamweaver 8 behöver du återanvända serverbeteendena på de sidor som använder dem och distribuera om dessa sidor till din server.

Resten av denna TechNote dokumenterar hur du manuellt redigerar Dreamweaver MX 2004-kod för att förhindra SQL-injektionsattacker med PHP-servermodellen.Serverbeteenden som är sårbara för dessa attacker listas nedan, tillsammans med korrigeringar:

Postuppsättning med ett filter

Ofiltrerade postuppsättningar behöver inte ändras men det behöver filtrerade postuppsättningar. I exemplet nedan filtreras en Dreamweaver MX 2004 recordset med namnet "rs_byDate" efter ett datumvärde som skickas in från en URL-parameter. Den markerade koden nedan är det som behöver ändras:

<?php $colname_rs_byDate = "1"; if (isset($_GET['relDate'])) { $colname_rs_byDate = (get_magic_quotes_gpc()) ? $_GET[&apos;relDate&apos;] : addslashes($_GET[&apos;relDate&apos;]); } mysql_select_db($database_dreamqa2, $dreamqa2); $query_rs_byDate = sprintf(&quot;SELECT * FROM albums WHERE relDate = &apos;%s&apos;&quot;, $colname_rs_byDate); $rs_byDate = mysql_query($query_rs_byDate, $dreamqa2) or die(mysql_error()); $row_rs_byDate = mysql_fetch_assoc($rs_byDate); $totalRows_rs_byDate = mysql_num_rows($rs_byDate); ?>

För att skydda recordset från SQL-injektionsattacker ska en anpassad GetSQLValueString()-funktion skapas närmare toppen av sidan. Denna funktion verifierar datatypen för frågeparametern. När funktionen har skapats ska du uppdatera recordset-koden för att använda GetSQLValueString()-funktionen.

Gå till den andra raden i kodvyn, direkt efter include-filen för anslutningen, och lägg till GetSQLValueString()-funktionen i början av koden enligt följande:

<?php if (!function_exists("GetSQLValueString")) { function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") { $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue; $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue); switch ($theType) { case "text": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "long": case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL"; break; case "double": $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL"; break; case "date": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "defined": $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue; break; } return $theValue; } } ?>

Ta bort magic quotes-koden så att omvänt snedstreck inte läggs till felaktigt i GET- och POST-data när magic quotes är avstängt på PHP-servern.

Ursprunglig kod:

$colname_rs_byDate = (get_magic_quotes_gpc()) ? $_GET['relDate'] : addslashes($_GET['relDate']);

Modifierad kod:

$colname_rs_byDate = $_GET['relDate'];



Uppdatera recordset-koden för att skapa en SQL-sträng med funktionen GetSQLValueString() som skapades ovan. Uppdatera värdet för variabeln $query_rs_byDate:

Ursprunglig kod:

$query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = '%s'", $colname_rs_byDate);

Ändrad säker kod:

$query_rs_byDate = sprintf("SELECT * FROM album WHERE relDate = %s", GetSQLValueString($colname_rs_byDate, "date"));

Server behaviors för Insert, Update och Delete Record samt Record Insertion Form-guiden

Server behaviors för Insert, Update och Delete Record samt Record Insertion Form-guiden använder redan funktionen GetSQLValueString(), så de behöver förfinas för att förhindra SQL-injektioner. De enda ändringarna som behövs är i funktionen GetSQLValueString().

Här är den ursprungliga koden. Raden som ska ändras är markerad i gult:

if (!function_exists("GetSQLValueString")) { function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") {$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue; switch ($theType) { case "text": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "long": case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL"; break; case "double": $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL"; break; case "date": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "defined": $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue; break; } return $theValue; } }

Uppdatera definitionen av variabeln $theValue:

Ursprunglig kod:

$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue;

Modifierad säker kod:

$theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue; $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

Serverfunktionen Logga in användare

Här är stegen för att åtgärda serverbeteendet Logga in användare:

Skapa en GetSQLValueString()-funktion enligt beskrivningen i Postuppsättning med ett filter ovan.

Modifiera koden som konstruerar inloggnings-SQL-frågan.



Ursprunglig kod:

$LoginRS__query=sprintf("SELECT username, password FROM login WHERE username='%s' AND password='%s'", get_magic_quotes_gpc() ? $loginUsername : addslashes($loginUsername), get_magic_quotes_gpc() ? $password : addslashes($password));

Modifierad säker kod:

$LoginRS__query=sprintf("SELECT username, password FROM login WHERE username=%s AND password=%s", GetSQLValueString($loginUsername, "text"), GetSQLValueString($password, "text"));

Serverfunktionen Kontrollera ny användare

Serverfunktionen Kontrollera ny användare kräver att serverfunktionen Infoga post läggs till på den första sidan. Funktionen GetSQLValuesString() ingår i serverbeteendet Infoga post. Allt som behöver göras är att uppdatera GetSQLValuesString() för att bättre hantera SQL-injektion och uppdatera serverbeteendet Kontrollera ny användare för att använda denna funktion när en parameter skickas in.

Ändra första raden i funktionen för att uppdatera funktionen GetSQLValuesString() enligt beskrivningen i Uppdatera definitionen av variabeln $theValue.

Modifiera koden för att konstruera inloggnings-SQL-frågan så att den använder GetSQLValuesString() för att skicka in parametrar. Längst upp på sidan, hitta koden i avsnittet som börjar med // *** Redirect if username exists.



Ursprunglig kod:

$LoginRS__query = "SELECT username FROM login WHERE username='" . $loginUsername . "'"



Modifierad säker kod:

$LoginRS__query = sprintf("SELECT username FROM login WHERE username=%s", GetSQLValueString($loginUsername, "text"));

Huvudsiduppsättningen med information

För tillämpningsobjektet Huvudsiduppsättning med information är ändringarna i huvudsak i postuppsättningen som Dreamweaver skapar för Informationssidan. Om du inte har en filtrerad postuppsättning på huvudsidan behöver inga ändringar göras på Huvudsidan. Om du har en filtrerad postuppsättning, se postuppsättning med ett filter för att uppdatera postuppsättningskoden.

Dreamweaver skapar en filtrerad postuppsättning på detaljsidan, så den postuppsättningskoden behöver uppdateras för att använda en GetSQLValueString()-funktion för att skicka in parametrar och sprintf() för att konstruera SQL-strängen.

Skapa funktionen GetSQLValueString() enligt beskrivningen i Postuppsättning med ett filter ovan.

Uppdatera variabeldeklarationskoden och konstruera SQL-frågan med funktionen GetSQLValuesString().



Ursprunglig kod:

$recordID = $_GET['recordID']; $query_DetailRS1 = "SELECT * FROM albums WHERE ID = $recordID";



Modifierad säker kod:

$colname_DetailRS1 = "-1"; if (isset($_GET['recordID'])) { $colname_DetailRS1 = (get_magic_quotes_gpc()) ? $_GET['recordID'] : addslashes($_GET['recordID']); } $query_DetailRS1 = sprintf("SELECT * FROM albums WHERE ID = %s", GetSQLValueString($colname_DetailRS1, "int"));

Guiden Postuppdateringsformulär

Uppdatera definitionen av variabeln $theValue enligt beskrivningen i Serverbeteenden för Infoga, uppdatera och ta bort post samt guiden Postinfogningsformulär.
Uppdatera koden för Recordset som krävs för Record Update Form enligt beskrivningen i steg 2 av Recordset med ett filter.

Ytterligare information

Se följande artikel för mer information om SQL-injektion: Wikipedia-artikel om SQL-injektion.

Adobe Security Bulletin: APSB 06-07 Dreamweaver Server Behavior SQL Injection vulnerability.