הגנו על התנהגויות שרת PHP מפני פגיעות הזרקת SQL

עודכן לאחרונה בתאריך 27 באפריל 2021

בעיה

מסדי נתונים מסוימים מאפשרים לך לשלוח כמה משפטי SQL בשאילתה אחת. לכן ישנם סיכוני אבטחה פוטנציאליים כאשר אתם מעבירים פרמטרים במחרוזת שאילתה לשאילתת מסד נתונים שנוצרת באופן דינמי. האקרים עלולים לנסות לשנות את ה-URL או משתני טופס בשאילתה דינמית על ידי הוספת הצהרות SQL זדוניות לפרמטרים קיימים. התקפה מעין זו נקראת בדרך כלל "התקפה מסוג החדרת SQL". יש לשנות חלק מקוד אופן הפעולה של השרת, אשר נוצר על-ידי Dreamweaver, על מנת לצמצם את הסיכון להתקפות מסוג החדרת SQL. למידע רקע נוסף על החדרת SQL, עיין במאמר בוויקיפדיה. (Ref. 201713)

הערה: הבעיה המתוארת בהודעה הטכנית הזו תוקנה ב-Dreamweaver 8.0.2 Updater.

TechNote זה מכסה את התנהגויות שרת PHP של Dreamweaver. קיימים TechNotes נפרדים להתנהגויות שרת ColdFusion, ASP VBScript, ASP JavaScript ו-JSP.התנהגויות שרת ASP.NET אינן מושפעות.

פתרון

כאשר אתה מאפשר למחרוזת שאילתה להעביר פרמטר, עליך לוודא שמועבר המידע הצפוי בלבד. Adobe יצרה Dreamweaver 8.0.2 Updater שמפחית את הסיכון להתקפות הזרקת SQL. התיקונים האלה ייכללו בכל המהדורות העתידיות של Dreamweaver. לאחר עדכון Dreamweaver 8, תצטרכו להחיל מחדש את התנהגויות השרת לעמודים שמשתמשים בהן, ולפרוס מחדש את העמודים האלה לשרת שלכם.

החלק הנותר ב-TechNote זה מתעד איך לערוך ידנית קוד Dreamweaver MX 2004 כדי למנוע התקפות הזרקת SQL עם מודל שרת PHP.התנהגויות שרת שפגיעות להתקפות האלה רשומות למטה, יחד עם התיקונים:

ערכת רשומות עם מסנן

אין צורך לשנות ערכות רשומות ללא סינון, אך צריך לשנות ערכות רשומות עם סינון. בדוגמה למטה, recordset של Dreamweaver MX 2004 בשם "rs_byDate" מסונן לפי ערך תאריך שהועבר מפרמטר URL. הקוד המודגש למטה הוא מה שצריך לשנות:

<?php $colname_rs_byDate = "1"; if (isset($_GET['relDate'])) { $colname_rs_byDate = (get_magic_quotes_gpc()) ? $_GET['relDate'] : addslashes($_GET['relDate']); } mysql_select_db($database_dreamqa2, $dreamqa2); $query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = '%s'", $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); ?>

כדי להגן על ה-recordset מפני התקפות הזרקת SQL, יש ליצור פונקציה מותאמת GetSQLValueString() ליד החלק העליון של העמוד. הפונקציה הזו מאמתת את סוג הנתונים של פרמטר השאילתה. לאחר יצירת הפונקציה, יש לעדכן את קוד ה-recordset כדי להשתמש בפונקציה GetSQLValueString().

עברו לשורה השנייה בתצוגת הקוד, מיד לאחר קובץ ה-include עבור החיבור, והוסיפו את הפונקציה GetSQLValueString() לתחילת הקוד כך:

<?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; } } ?>

הסירו את קוד ה-magic quotes כדי למנוע הוספה שגויה של לוכסנים לנתוני GET ו-POST כאשר magic quotes מכובים בשרת ה-PHP.

קוד מקורי:

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

קוד מעודכן:

$colname_rs_byDate = $_GET['relDate'];



עדכנו את קוד ה-recordset כדי ליצור מחרוזת SQL באמצעות הפונקציה GetSQLValueString() שנוצרה למעלה. עדכנו את הערך של המשתנה $query_rs_byDate:

קוד מקורי:

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

הקוד המאובטח לאחר השינויים:

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

התנהגויות שרת Insert, Update ו-Delete Record ואשף Record Insertion Form

התנהגויות השרת Insert, Update ו-Delete Record ואשף Record Insertion Form כבר משתמשים בפונקציה GetSQLValueString(), ולכן יש לשפר אותם כדי למנוע הזרקות SQL.השינויים היחידים הנדרשים הם בפונקציה GetSQLValueString().

הנה הקוד המקורי. השורה שצריך לשנות מסומנת בצהוב:

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; } }

עדכנו את ההגדרה של המשתנה $theValue:

קוד מקורי:

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

קוד מאובטח ומעודכן:

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

אופן פעולת השרת Log In User

אלה הם השלבים לתיקון התנהגות השרת 'התחברות משתמש':

צרו פונקציה GetSQLValueString() כמתואר במערך רשומות עם מסנן לעיל.

שנו את הקוד שיוצר את שאילתת ה-SQL של ההתחברות.



קוד מקורי:

$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));

קוד מאובטח ומעודכן:

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

אופן פעולת השרת Check New User

עבור אופן פעולת השרת Check New User, יש להוסיף תחילה לדף אופן פעולת שרת של Insert Record. הפונקציה GetSQLValuesString() כלולה עם התנהגות השרת 'הוספת רשומה'. כל מה שצריך לעשות הוא לעדכן את GetSQLValuesString() כדי להתמודד טוב יותר עם ה-SQL Injection ולעדכן את התנהגות השרת 'בדיקת משתמש חדש' כדי להשתמש בפונקציה זו כשמועבר פרמטר.

שנו את השורה הראשונה בפונקציה כדי לעדכן את הפונקציה GetSQLValuesString() כמתואר בעדכון ההגדרה של המשתנה $theValue.

שנו את הקוד כדי ליצור את שאילתת ה-SQL של ההתחברות כדי להשתמש ב-GetSQLValuesString() כדי להעביר פרמטרים.לקראת החלק העליון של הדף, אתרו את הקוד בחלק המתחיל עם // *** Redirect if username exists.



קוד מקורי:

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



קוד מאובטח ומעודכן:

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

הגדרת דף פרטים ראשי

עבור אובייקט היישום Master Detail Page Set (הגדרת דף פרטים ראשי), השינויים נערכים בעיקר בערכת הרשומות ש-Dreamweaver יוצר עבור דף הפירוט. אם אין לך ערכת רשומות מסוננת בדף הראשי, אין צורך בשינויים בדף הראשי. אם יש לכם מערך רשומות מסונן, ראו מערך רשומות עם מסנן כדי לעדכן את קוד מערך הרשומות.

Dreamweaver יוצר מערך רשומות מסונן בדף הפרטים, כך שקוד מערך הרשומות צריך להתעדכן כדי להשתמש בפונקציה GetSQLValueString() להעברת פרמטרים וב-sprintf() כדי ליצור את מחרוזת ה-SQL.

צרו את הפונקציה GetSQLValueString() כמתואר במערך רשומות עם מסנן לעיל.

עדכנו את קוד הצהרת המשתנה וצרו את שאילתת ה-SQL באמצעות הפונקציה GetSQLValuesString().



קוד מקורי:

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



קוד מאובטח ומעודכן:

$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"));

אשף טופס עדכון רשומה

עדכנו את הגדרת המשתנה $theValue כפי שמתואר בInsert, Update, and Delete Record server behaviors and Record Insertion Form wizard.
עדכנו את הקוד של ה-Recordset הנדרש עבור Record Update Form כפי שמתואר בשלב 2 של Recordset עם מסנן.

מידע נוסף

עיינו במאמר הבא למידע נוסף אודות SQL injection:‏ מאמר ויקיפדיה על SQL injection.

עדכון אבטחה של Adobe:‏ APSB 06-07 Dreamweaver Server Behavior SQL Injection vulnerability.