logo

הזרקת SQL

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

הזרקת SQL (SQLi) היא פגיעות אבטחה המתרחשת כאשר תוקף יכול לתפעל את שאילתות מסד הנתונים של יישום אינטרנט על ידי הכנסת קוד SQL זדוני לשדות קלט של המשתמש. שאילתות אלו המוזרקות יכולות לתפעל את מסד הנתונים הבסיסי כדי לאחזר שינויים או מחיקה של נתונים רגישים. במקרים מסוימים התוקפים יכולים אפילו להסלים הרשאות ולקבל שליטה מלאה על מסד הנתונים או השרת.



הזרקת sql' title=

דוגמה בעולם האמיתי:

בשנת 2019 פרצת הנתונים של Capital One התרחשה עקב יישום אינטרנט שהוגדר בצורה שגויה שאפשרה לתוקף לנצל פגיעות של הזרקת SQL. זה הביא לדליפה של נתונים אישיים של למעלה מ-100 מיליון לקוחות כולל שמות כתובות וציוני אשראי.

רמת אבטחת הזרקת SQL

DVWA מספק ארבע רמות אבטחה עבור SQL Injection כדי לעזור ללומדים לראות כיצד הגנות שונות משפיעות על התקפות:



1. אבטחה נמוכה

האפליקציה לוקחת את הקלט שלך ומכניסה אותו ישירות לשאילתת SQL ללא סינון.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • נכנסים ': שובר את השאילתה וגורם למסד הנתונים לזרוק שגיאה שחושפת שהוא פגיע.
  • נכנסים 1' OR '1'='1: מרמה את השאילתה כך שהיא תמיד אמיתית כך שכל המשתמשים יוחזרו.
  • נכנסים 1' UNION SELECT user password FROM users--: מצטרף לשאילתה נוספת כדי להביא נתונים מוסתרים כמו שמות משתמש וסיסמאות.

2. אבטחה בינונית

האפליקציה מיישמת חיטוי קלט בסיסי באמצעות פונקציות כמוaddslashes()לברוח'.

$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';

איך יכולה להיות תקיפה:



פשוט'ההזרקה לא תעבוד יותר (כי היא הופכת').

אבל תוקפים עדיין יכולים לעקוף באמצעות הזרקה מספרית (מכיוון שמספרים אינם צריכים מרכאות).
דוּגמָה:

מחרוזת java ל-json
1 OR 1=1

זה עדיין מחזיר את כל הרשומות.

3. אבטחה גבוהה

האפליקציה משתמשת בהצהרות מוכנות (שאילתות עם פרמטרים) כדי לטפל בבטחה בקלט המשתמש.

$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);

לִתְקוֹף:

ניסיונות כמו' OR 1=1אוֹUNION SELECTכבר לא עובד.

השאילתה מתייחסת לכל הקלט כאל נתונים ולא כקוד SQL.

סוגי הזרקת SQL

ישנם סוגים שונים של הזרקת SQL

1. הזרקת SQL מבוססת שגיאות

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

איך זה עובד

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

הראה למשתמשים mysql
  1. זיהוי קלט פגיע: התוקף מוצא שדה קלט כמו סרגל חיפוש או פרמטר של URL שמקיים אינטראקציה ישירה עם מסד הנתונים ללא חיטוי קלט מתאים.
  2. הזרקת מטען זדוני: התוקף מחדיר דמות מיוחדת (כמו ציטוט בודד') או פונקציה שידועה כגורמת לשגיאת מסד נתונים.
  3. נתח את השגיאה: מסד הנתונים אינו מסוגל לעבד את השאילתה השגויה מחזיר הודעת שגיאה מפורטת. הודעה זו יכולה לחשוף מידע חיוני כגון:
    • מערכת מסד הנתונים (למשל MySQL Oracle SQL Server).
    • הגרסה של מסד הנתונים.
    • שאילתת SQL המלאה מבוצעת.
    • שגיאות תחביר ספציפיות שניתן להשתמש בהן כדי להבין את שמות הטבלה או העמודות.
  4. חידד את ההתקפה: באמצעות המידע שנאסף מהודעת השגיאה, התוקף יכול לחדד את המטען שלו כדי לחלץ נתונים נוספים כגון שמות משתמש וסיסמאות.

דוּגמָה:

שלב 1: הגדר את הסביבה שלך

  • הפעל את DVWA. גישה אליו בדרך כלל על ידי ניווט לכתובת אתר כמוhttp://localhost/dvwaבדפדפן שלך.
קוֹבֶץ' loading='lazy' title=
  • היכנס ל-DVWA עם אישורי ברירת המחדל:admin/password.
קוֹבֶץ' loading='lazy' title=
  • עבור לכרטיסייה DVWA Security והגדר את רמת האבטחה לנמוכה. זה יבטיח שקל לנצל את הפגיעויות.
קוֹבֶץ' loading='lazy' title=

שלב 2: זהה את הפגיעות

לדף הזרקת SQL יש תיבת קלט פשוטה שבה ניתן להזין מזהה משתמש. השאילתה האחורית היא כנראה משהו כמוSELECT * FROM users WHERE id = 'user_input'

  • הזן מזהה חוקי כמו1לתוך תיבת הקלט ולחץ על 'שלח'. אתה אמור לראות את הפרטים של המשתמש עם מזהה 1.
קוֹבֶץ' loading='lazy' title=

מקור הזרקת SQL

PHP
 $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?>
  • כעת נסה לשבור את השאילתה. הזן הצעת מחיר בודדת'בתיבת הקלט ושלח.
קוֹבֶץ' loading='lazy' title=

השאילתה הופכת:

SELECT * FROM users WHERE id = ''';

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

בנאים ב-java

במקום להראות לך את פרטי המשתמש, האפליקציה תחזיר שגיאת SQL (משהו כמו 'יש לך שגיאה בתחביר ה-SQL שלך...')

זה נקרא הזרקת SQL מבוססת שגיאות מכיוון:

  • התוקף שולח קלט לא חוקי (')
  • מסד הנתונים זורק שגיאה
  • השגיאה הזו דולפת מידע שימושי על מסד הנתונים (כמו סוג של מבנה מספר DB של עמודות וכו')

2. הזרקת SQL מבוססת איגוד

הזרקת SQL מבוססת איחוד היא טכניקה שבה תוקפים משתמשים ב-UNIONמפעיל כדי לשלב את התוצאות של שניים או יותרSELECTהצהרות לקבוצת תוצאות אחת. זה יכול לאפשר להם לחלץ מידע מטבלאות אחרות במסד הנתונים. הUNIONניתן להשתמש באופרטור רק אם:

  • לשתי השאילתות יש אותו מספר עמודות
  • לעמודות יש סוגי נתונים דומים
  • העמודות באותו סדר

מפעיל UNION : הUNIONהאופרטור משמש לשילוב מערך התוצאות של שניים או יותרSELECTהצהרות.

  • כֹּלSELECTהצהרה בפניםUNIONחייב להיות אותו מספר עמודות
  • העמודות חייבות לכלול סוגי נתונים דומים
  • העמודות חייבות להיות באותו סדר
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

דוּגמָה:

שלב 1: ראשית עלינו למצוא את מספר העמודות של הטבלה הקיימת באתר כדי להזרים הזרקת SQL מבוססת UNION:

לדף הזרקת SQL יש תיבת קלט פשוטה שבה ניתן להזין מזהה משתמש. השאילתה האחורית היא כנראה משהו כמו

 SELECT * FROM users WHERE id = 'user_input'

כעת נסה לשבור את השאילתה. הזן הצעת מחיר בודדת'בתיבת הקלט ושלח.

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

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

שלב 2: השתמש ב-UNIONמילת מפתח לגילוי מספר העמודות

כדי להשתמש בUNIONמילת מפתח (שלב הבא נפוץ) עליך לדעת את מספר העמודות בשאילתה המקורית. אתה יכול לגלות זאת על ידי שימוש ב-ORDER BYסָעִיף

פקודה arp-a
  • נסה למיין את התוצאות לפי עמודות
1: 1 ORDER BY 1. 
  • לְהַגִישׁ. זה אמור לעבוד.
קוֹבֶץ' loading='lazy' title=

מקור הזרקת SQL

PHP
 if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?>
  • הגדל את המספר:
 1 ORDER BY 2. 

לְהַגִישׁ. זה אמור לעבוד.

קוֹבֶץ' loading='lazy' title=
  • המשך להגדיל עד שאתה מקבל שגיאה. לְדוּגמָה1 ORDER BY 4עשוי לתת לך:Unknown column '4' in 'order clause'
  • זה אומר שלשאילתה יש 3 עמודות.

3. הזרקת SQL מבוססת עיוור

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

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

  1. SQLi עיוורת מבוסס בוליאנית: התוקף מזריק שאילתת SQL שמחזירה א נָכוֹן אוֹ שֶׁקֶר תוֹצָאָה. התגובה של יישום האינטרנט משתנה בהתאם לשאלה אם השאילתה נכונה או לא נכונה. לדוגמה, הדף עשוי להציג הודעה אחרת או להציג פריסה אחרת.
  2. SQLi עיוורון מבוסס זמן: התוקף מזריק שאילתת SQL שגורמת למסד הנתונים לבצע פעולה שלוקחת זמן (כמו אSLEEP()פונקציה) אם מתקיים תנאי. התוקף מתבונן בזמן שלוקח לדף להיטען כדי לקבוע אם המצב שהוזרק היה נכון או לא נכון.

דוּגמָה:

תארו לעצמכם דף התחברות שבו אתם מכניסים שם משתמש וסיסמה. היישום בונה שאילתת SQL בצורה הבאה:

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'

הזרקת SQL עיוורת תכלול מניפולציה שלuser_inputכדי לשאול את מסד הנתונים שאלה.

במקום לקבל תגובה ישירה, התוקף עשוי לנסות משהו כמו זה:

user_input = 'admin' AND 1=1; --

אם הדף נטען כרגיל, התוקף יודע זאת1=1הוא א נָכוֹן הַצהָרָה.

user_input = 'admin' AND 1=2; --

אם הדף מציג שגיאה או מתנהג אחרת, התוקף יודע זאת1=2הוא א שֶׁקֶר הַצהָרָה.

קוֹבֶץ' loading='lazy' title=

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

השפעת התקפות הזרקת SQL

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

מניעת התקפות הזרקת SQL

ישנן מספר שיטות עבודה מומלצות למניעת התקפות הזרקת SQL:

1. השתמש בהצהרות מוכנות ובשאילתות עם פרמטרים

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

משחקי imessage עם אנדרואיד

דוגמה ב-PHP (באמצעות MySQLi):

$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();

2. השתמש בנהלים מאוחסנים

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

דוּגמָה:

CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;

3. אימות קלט ברשימת ההיתרים

ודא שקלט המשתמש מאומת לפני השימוש בשאילתות SQL. אפשר רק תווים ודפוסים מסוימים כגון קלט אלפאנומרי עבור שדות כמו שמות משתמש או כתובות דוא"ל.

4. השתמש במסגרות ORM

מסגרות מיפוי יחסי אובייקט (ORM) כמו שינה אוֹ מסגרת ישות יכול לסייע במניעת הזרקת SQL על ידי טיפול אוטומטי בהפקת שאילתות ומניעת בניית שאילתות דינמית.

5. הגבל הרשאות מסד נתונים

הענק את הרשאות מסד הנתונים המינימליות הנדרשות למשתמשים. ודא שיישומים יכולים לבצע רק פעולות נחוצות (למשל SELECT INSERT) ולהגביל הרשאות כמו DROP TABLE או ALTER.

6. טיפול בשגיאות

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