SQL Injection ו-PHP

‏ • 28 באפריל, 2012

מהי פרצת SQL Injection?

כאשר האקר מצליח להכניס פקודת SQL ולהריץ אותה על ה database שלך מבלי ידיעתך.

בדרך כלל SQL Injection מתאפשרת כאשר אתה מבקש באמצעות טופס פרטים מהמשתמש ובמקום פרטים נורמליים, ההאקר מספק לך פקודת SQL הרסנית.

דוגמא:

נניח שיש לנו אתר חלקי חילוף לרכב. באתר יש טופס חיפוש עם שדה שמבקש מילת מפתח לחיפוש ומביא מוצרים רלוונטים. הקוד שמעבד את המידע שמגיע מהטופס יכול להיות משהו כגון:

//nice and polite query 
$part = "wheels";
$query ="select * from parts where name=' ".$part." ' ";

השאילתה למעלה לא תהווה כל בעיה וככל הנראה תביא רשומות של גלגלים שונים. אבל כאשר האקר יגיע לאתר הוא יקיש משהו כזה:

$part = " ' OR 1 ' ";

ואז $query יכיל את השאילתא הבאה:

select * from parts where name=' ' OR 1

ואז, הגרש הבודד שהוקש בהתחלה של $part סוגר את ה-name=' ', כדי שלא תיווצר syntax error ואחרי כן ה-OR 1 יביא לנו את כל הרשומות בטבלה, יתכן שזה כל המלאי, ובוודאי שלא רצינו להציג את כל זה (זה עלול לשרת את האתר המתחרה Smile).

דוגמא נוספת:

נמשיך עם אותו אתר של חלקי חילוף. הדוגמא הבאה ממחישה כיצד ניתן למחוק את תכולת הטבלה.

$part = " ' ; Delete from parts where 1 or name= ' ";

ואז מה שיתבצע בפועל הוא למעשה שתי שאילתות:

select * from parts where name=' ' ; Delete from parts where 1 or name=' ' 

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

  • החלקים '; בהתחלה וגם or name=' בסוף נועדו להשתלב בשאילתה המקורית ולמנוע syntax error שהרי ה-$part נמצא בין גרש בודד לגרש בודד בשאילתה המקורית. ההאקר מנחש את זה ומכין את הקלט שלו בהתאם.
  • בנוסף הפקודה delete from parts where 1 תמחק את כל תכני הטבלה כיון שהתנאי where 1 מתקיים תמיד.

אז אפשר לראות משתי הדוגמאות הללו, שגרש בודד שיחק כאן תפקיד של השלמת שאילתא כך שסינטקטית היא תעבור יפה , ואפשר את כל התעלולים שבאו אחריו.

איך אפשר למנוע SQL Injection ?

הבעיה של SQL Injection כבר ידועה ממזמן, ו-PHP הכינה מספר פונקציות שמאפשרות להתמודד עם העניין.

הפונקציה mysql_real_escape_string :

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

אפשר לקרא על הפונקציה הזו כאן:

http://il.php.net/manual/en/function.mysql-real-escape-string.php

** הפונקציה הזו יוצאת מהנחה שה-connection ל-database כבר קיים. לכן השתמשו בה רק אחרי יצירת הconnection.

דוגמאת שימוש:

<?php

 

$part = $_POST['part'];
// Connect

$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
    OR die(mysql_error());

// Query
$query = sprintf("SELECT * FROM parts WHERE name ='%s' ",
            mysql_real_escape_string($part));
?>

וכעת ה-where clause במקרים הבעייתיים יכיל:

במקרה של הדוגמא הראשונה –

name=\' OR \' 

ובמקרה של הדוגמא השניה

 name=\'; Delete from parts where 1 or name=\'

ומה שיקרה בפועל זה ביצוע של שאילתה המחפשת name שערכו מגוחך ומן הסתם גם לא תביא שום תוצאה.

אם הנחת הבסיס של mysql_real_escape_string , בדבר קיומו של database connection לפני השימוש בה, היא בעייתית עבורכם, ישנה גם הפונקציה addslashes שאף היא מבצעת דבר דומה (מקדימה סלאש לתוים בעייתים כגון גרש בודד או גרשיים כפולים), אך היא פחות מומלצת, כיון שאינה ספיציפית ל-database מסוים.

כאשר אנו משתמשים ב-mysql_real_escape_string הפונקציה יודעת לקחת בחשבון את ה-character set הנוכחי של ה-conncetion ואף קוראת לפונקצית הספריה של mysql כדי לבצע את הריפוד בסלשים.

תגיות: , ,

תגובות בפייסבוק