איך להמנע מהזרקת SQL
-
צד שרת: node.js
מסד נתונים: sql serverאני לא הולך להמציא את הגלגל
אבל מעוניין לדעת איך מנפחים אותו...התוצאה הרצויה: להמנע מהזרקת SQL
השאלה: מה מתוך הפעולות המצ"ב
מקטינות/מיותרות
באופן משמעותי את הסיכוי/ן להזרקת SQL
והאם יש צורך במשהו נוסף-
הגדרת משתמש להרשאות גישה למסד נתונים ספציפי בודד
-
הגדרת משתמש לשאילתות Select + Update + insert בלבד
-
בדיקת הקלט המתקבל בביטוי רגולרי שמאפשר הזנת אותיות ומספרים ונקודה בלבד
-
עטיפת הקלט המתקבל בגרש
דוגמא:
app.get('/api/jobs', (req, res) => { pool.query(` SELECT * FROM users where id = '${where_string}' `, (err, result) => { if (err) { console.log(err); return res.send("error") } res.send(result.recordset); }); });
-
-
אני מנסח שני כללים בלבד:
א. ערנות אנושית: להסתכל תמיד על החלקים הדינמיים בשאילתה (כמו הפרמטר ID) ולתת לב מאין המידע בא, ומה ההשלכות למקרה של מידע שגוי או עויין.
ב. שימוש בכלים הנכונים: לעבוד לפי הספר של הספריה/טכנולוגיה (במקרה שלך, הדרך שספריית MSSQL מציעה עבור שתילת קלט דינמי בשאילתה בצורה בטוחה).נתחיל מהכלל השני.
בשונה מכל תחום בתכנות בהם זה נחמד להיות מקורי ולממש לבד, באבטחה אתה צריך כמה שפחות לממש בעצמך.
מה שהצעת עם הרג'קס ועטיפת הגרש הוא ניסיון מימוש עצמי של טיהור קלט.
אתה דומה למישהו שמנסה לחשוב מאיפה הגנב ייכנס, מוצא רעיון בראש, סוגר את הפרצה ונרגע. הבעיה היא שהרעיון הוא אחד מתוך מאה! איך תדע שעברת על כל הרעיונות?
למשל לענייננו, לעטוף בגרש לא עוזר כלום. אם התוקף שלנו שתל גרשים בתוך המחרוזת, למשל הקלט הזהid=123'; update users set pass = 123 where name = 'admin' OR name = '
יעבוד מצויין עם עטיפת גרש מכל צד.
אז מה נשאר? ניקוי עם רגקס. ברג'קס תוודא שאין מה? אם תוודא שאין גרשים למשל, תצטרך להתמודד עם קלטים לגיטמיים שמכילים גרשים! מה, אסור להכניס לטבלה שם רחוב עם גרש?
מה הפתרון? להכיר את הדרך שהספריה/טכנולוגיה שאתה עובד איתה הכינו למקרה הזה, חכמת ההמונים היא מעולה כדי לסגור פרצות. במקרה של MSSQL הם ממליצים להשתמש בES6 Tagged template literals שזה בדיוק מה שעשית רק שאתה הפכת הכל לטקסט לפני שזה עובר למתודה, בשביל שהמתודה היא זו שתחליט איך להשתיל את הטקסט צריך לעשות ככה:app.get('/api/jobs', (req, res) => { const req = pool.query`SELECT * FROM users where id = ${where_string}`; req.then(result => res.send(result.recordset)); req.catch(err => console.error(err)); });
שים לב שהטקסט מגיע מייד אחרי שם הפונקציה query בלי סוגריים! זה נקרא tag function וזה הדרך הנוחה לתת לספריית הMSSQL את השליטה בטיהור הפרמטרים. יש דרך אחרת וזה שימוש מפורש בפרמטרים, זה טיפה יותר טרחה.
יש לשים לב שהכלל השני לא עוזר כלום בלי הראשון.
למשל אם הid הוא מספר תקין והכל בסדר אבל הוא פונה לרשומה שאסור למשתמש לגשת/לעדכן אליה/אותה? כל מקום שיש נתונים דינמיים בשאילתה זה אמור להדליק את מנגנון העירונות שאמור לבדוק תמיד את פונטציאל הסכנה במקרה שפספסנו משהו והנתונים חופשיים, וכשלב ב' אחרי אומדן הסכנה שחזור הדרך בהם הנתונים מתגלגלים, וכמה הדרך מאובטחת.כל יתר הדברים שהזכרת, הינם לדעתי לא מועילים או לא נצרכים.
ברור שזה פרקטיקה טובה לצמצם הרשאות, אבל זה לא נדרש (זה בעיקר טוב נגד באגים או טעויות אנוש קשות). -
דוד כבר ענה הכל, אני רק מוסיף שהזרקת SQL כבר נפתרה בצורה מושלמת על ידי שימוש ב-prepared statements וזה מה שה-ES6 Tagged template literals עושה.
-
@mekev עטיפה עם גרש הוא בית חולים מתחת לגשר, אתה מכניס לתוך השאילתא דברים במקום שמותר להכניס קוד, אבל אתה מנסה לוודא שאין שם קוד, זה גם לא עובד בלי עבודה נוספת כמו שדוד ציין, משא"כ בפרמטר ל-Prepared statement המונע לעולם לא יתייחס לתוכן של הפרמטר כקוד "בעל הרצה" כלומר גם אם תכניס לשם פקודות SQL הם יתורגמו כ"שם" ולא כקוד