לקחת את ה-SQL Injection למקומות רחוקים

המקרה המדהים של SQL Injection בשעת לילה מאוחרת
הזרקת קוד באתר פרטנר

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

בגדול, פירצת SQL מאפשרת לנו להזריק פקודת SQL. הדוגמה הפשוטה ביותר היא ב-Node.js. שימו לב לקוד הזה למשל:

const username = req.body['username'];
const password = req.body['password'];
const query = `SELECT * FROM users WHERE username = "${username}" AND password = "${password}";`

זה קוד שלא צריך להכיר Node.js או Express כדי להבין אותו. בגדול, המשתמש שולח בטופס username ו-password ואנו שמים אותם בשאילתת MySQL כדי לבדוק אותם. אם למשל המשתמש שולח שם משתמש admin וסיסמה 123456 השאילתה שתרוץ היא:

SELECT * FROM users WHERE username = "admin" AND password = "123456"

אם יש שם משתמש וסיסמה כאלו, אז התוצאה היא TRUE ואז הקוד יודע שמדובר במשתמש ולידי ויכול להציב אצלו עוגית סשן או להציג לו את העמוד המתאים. אבל יש חולשה משמעותית בקוד הזה, כי משתמש יכול לשלוח שם משתמש admin וסיסמה שהיא:

" OR "1" = "1

ואז השאילתה תרוץ כך:

SELECT * FROM users WHERE username = "admin" AND password = "" OR "1" = "1"

וכיוון שהכנסנו את התנאי של ״1״=״1״ בעורמה, התוצאה תמיד תהיה TRUE. זה SQL Injection בסיסי. המשתמש יכול להכניס איזו שאילתה שבא לו בקוד הזה, כמו DROP או SELECT אחר שמביא לו את כל מסד הנתונים בכיף.

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

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

אז מה שהכי מדהים בפירצה הזו הוא הדרך שבה היא נעשתה. האם היה צורך לבנות איזשהו קלט מיוחד ומסובך כמו שבדרך כלל בונים? משהו כמו:

-1 union select top 1 null, lead(pass, 0) over (order by pass) from users;

התשובה היא לא. צילום המסך הזה יראה לכם:

הזרקת קוד באתר פרטנר

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

SELECT * FROM ALL_CATALOG

שמביא לכם את כל הישויות שיש במסד הנתונים ואז אפשר להקליד איזה SELECT שבא לנו. כמו בדוגמה למשל:

SELECT * FROM all_users

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

ללא מילים.

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

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

רינדור של קליינט סייד עם SSR

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

תמונה מצוירת של רובוט שמנקה HTML
יסודות בתכנות

סניטציה – למה זה חשוב

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

יסודות בתכנות

מספרים בינאריים בקוד

איך, ויותר חשוב למה, משתמשים במספרים בינאריים בתכנות? גם בפייתון ובג׳אווהסקריפט?

גלילה לראש העמוד