הזרקת SQL

הזרקת SQL (באנגלית: SQL Injection) היא שיטה לניצול פרצת אבטחה בתוכנית מחשב בעזרת פניה אל מסד הנתונים. השם נובע מכך שהמשתמש מכניס קוד SQL לשדה קלט אליו אמורים היו להיכנס נתונים תמימים. באופן זה יכול משתמש זדוני לחרוג לחלוטין מן התבנית המקורית של השאילתה, ולגרום לה לבצע פעולה שונה מזו שיועדה לה במקור. הזרקת SQL היא מקרה פרטי של קבוצה רחבה של פרצות אבטחה הנקראות הזרקות קוד, שמתרחשות כאשר תוכנה כלשהי יוצרת קוד בזמן ריצה על־פי הקלט ובלי לבדוק את תוכן הקלט תחילה. כל תוכנית שבונה שאילתות SQL תוך שילוב של נתונים מן המשתמש, עלולה להיות פגיעה להזרקה, עלולה לחשוף נתונים שהמתכנת חשב שלא יוכלו להחשף ועלולה לגרום נזק לנתונים עצמם ומכיוון שכך, היא עלולה להיות פגיעה ללוחמת סייבר. בדוגמה הבאה, הנתונה ב־ASP, ביקש המתכנת לקלוט מהמשתמש את סיסמת הגישה שלו לאתר אינטרנט מאובטח, לבדוק את תקינותה כנגד מסד הנתונים ולאשר את הגישה אם הסיסמה אכן קיימת. הקוד (הפגיע לפריצה) הבונה את שאילתת ה-SQL נראה כך: SQL = "SELECT * FROM users WHERE password='" & Request("password") & "'" כאשר האובייקט Request משמש לקבלת נתונים מטפסים. כעת, השימוש התקין שראה המתכנת לנגד עינו הוא הכנסת סיסמה, למשל 1234, שתייצר את שאילתת ה-SQL הבאה: SQL = "SELECT * FROM users WHERE password='1234'" ובהנחה שאין בטבלת users רשומה שבה העמודה password מכילה את הערך '1234', לא נוכל לקבל גישה. אך על ידי הזרקת SQL יכול משתמש זדוני להכניס את הקלט הבא: ' OR 'a'='a שייצר את שאילתת ה-SQL הבאה: SQL = "SELECT * FROM users WHERE password='' OR 'a'='a'" על ידי הכנסת "נתון" שהוא למעשה בחלקו נתון ובחלקו קוד מבני של השאילתה, שינה המשתמש את השאילתה לכזו שמחזירה את כל הרשומות בטבלה, משום שהערך 'a' תמיד שווה לעצמו. קוד התוכנית שפועל אחרי הרצת השאילתה יניח שמאחר ותוצאת השאילתה אינה ריקה, יש לאפשר גישה מלאה למשתמש, אף שבפועל אין לו סיסמה תקפה. לפורץ כעת יש גישה כאילו הכניס סיסמה. על מנת להיות בטוחים שקוד לא יהיה חשוף להזרקה, אפשר לנקוט באחת משתי הגישות הבאות (ורצוי בשתיהן): על המתכנת לבדוק את כל הנתונים המגיעים מן המשתמש: בשדות טקסט יש לבדוק שהערכים בשדות לא מכילים תווים מיוחדים מסוימים - בדוגמה למעלה מדובר בגרש (') ניתן להשתמש בשגרות של שפת התכנות של מסד הנתונים, כך שניסיון להחדיר את הטקסט יגרום לשגיאה של המערכת במקום לחדירה. בשפה העברית עדיף לבצע החלפה (אם מדובר בשדה שאמור לקלוט מילים), שכן התו גרש נמצא בשימוש יומיומי. נתונים מספריים יש לבדוק כדי לאשר שהם מקבלים ערך מספרי בלבד. נתונים הנשמרים על עוגייה ניתן לערוך בצד המשתמש ולכן יש לבדוק גם אותם. שפות התכנות השונות מציעות פתרון עדיף לבעיה, על ידי כך שהמתכנת יכול להכין שאילתה מובנית ולשים "שומרי מקום" (placeholder) במקומות שאליהן יוכנס אחר כך הנתון הנקלט מהמשתמש. לדוגמה במקום קטע הקוד הבא, הכתוב בשפת JAVA: Connection con = (acquire Connection) Statement stmt = con.createStatement(); ResultSet rset = stmt.executeQuery("SELECT * FROM users WHERE name = '" + userName + "';"); ניתן לכתוב כך: Connection con = (acquire Connection) PreparedStatement pstmt = con.prepareStatement("SELECT * FROM users WHERE name = ?"); pstmt.setString(1, userName); ResultSet rset = pstmt.executeQuery(); באופן זה תשתית התוכנה עצמה מוודאת שמבנה השאילתה אינו משתנה על ידי הנתון. אם ינסה אותו משתמש זדוני את אותה שיטה המודגמת למעלה, תיווצר חריגה בעת הרצת השאילתה, שכן כבילת (binding) הנתון לשומר המקום תיכשל. פריצה לאתר אינטרנט באמצעות הזרקת SQL מהווה את הבסיס לאחת מעלילות המשנה בספר "כיסא פנוי" מאת ג'יי קיי רולינג, משנת 2012. בפרק בשנת 2019 בסדרה "מסע בין כוכבים: דיסקברי" מזהה אחד המפקדים בספינה תקיפה שבוצעה באמצעות כמה הזרקות SQL, אך מאגר הנתונים לא נפגע. בספר שליחות חשאית: מבצע מנהטן גיא פורץ לאתר העבודה של אביו באמצעות הזרקת SQL. Log4Shell XSS CSRF How To: Protect From Injection Attacks in ASP.NET איך לבדוק אם יש לך SQL Injection