-
מהם האפשרויות למנוע הזרקת SQL?
אפשרות אחת משתמשת בפרמטרים - מאתר stackoverflow
האם פונקציה פשוטה יכולה להחליף את השימוש בפרמטר? האם מספיק לטפל בתווים ' ו " וכבר אין סיכון או שחייבים תמיד את האופציה הראשונה הארוכה יחסית? -
@גגד יש להבין ויש מה לעשות.
לעניין להבין, אתה צריך לראות קוד מקור של כזו פונקציה, ולהבין את הסכנות.
בשביל להשתמש, בחיים אל תעשה לבד... באבטחה, מימוש עצמי של דברים של חצי אנושות ישבה עליהם, זה מתכון לבעיות. אתה תעבוד מאוד מאוד קשה ותהנה ממוצר מוצלח ומוגמר, שעושה 99.9% מהעבודה, התוקף סה"כ יריץ סקריפט מוכן שהוא מצא ברשת, והוא יצליח עליך.
מתכנת צריך לזכור שהוא בן אדם, עם התופעות לוואי שזה אומר.עריכה לא שמתי לב שמדובר באקסס, באקסס לא צריך להגזים בחשש, כי לא מדובר באין סוף פורצים פוטנציאלים וגם יש הרבה דרכים פשוטות יותר להגיע לתוצאה ה(בלתי) רצויה. צריך רק להגן מבאגים שעלולים להיות.
-
@גגד למה חייב דווקא
"
או'
?
תאר לעצמך תיבת טקסט שבה המשתמש מחפש מספר ילדים מסויים במשפחה. הוא אמור להקליד מספר, נכון? מה יקרה אם המתכנת המתחיל הוסיף שורה כזו בקוד:Dim SQL = "SELECT * FROM Families WHERE Children=" & txtChildren CurrentDb.Execute SQL
והמשתמש הלא נחמד הקליד מספר ילדים כזה:
5; DROP TABLE Users;
-
@OdedDvir קיבלתי.
כלומר - מה שנשאר לוודא זה שהמספר הוא ISNUMERIC בלבד.
כעין זה מצאתי ב https://www.hacksplaining.com/prevention/sql-injection
אם כן פונקציה זו תספיק כפרמטר:Public Function SqlParameter(Text As String, Optional AsNumeric As Boolean = False) If AsNumeric Then If IsNumeric(Text) Then SqlParameter = Text Exit Function End If SqlParameter = Replace(Replace(Text, "'", "''"), "", """") End Function
ודרך אגב, אמנם יש אפשרות ב SQL נורמלי לכתוב שאילתות בזו אחר זו, אך באקסס אי אפשר.
לדוגמה הקוד הבא לא יעבוד:Sub A1() CurrentDb.Execute "SELECT טבלה1.שדה1 FROM טבלה1; DROP TABLE טבלה1;" End Sub
אבל עדיין שייך UNION...
-
@גגד
א. אני התכוונתי להקניית הרגלים נכונים, לא דווקא לפתרון של בעיה ספציפית.
ב. בכל מקרה לא הבנתי מה התועלת בפונקציה הנ"ל. אם ממילא בסופו של יום אני מעביר את התוצאה שלה לפרמטרים - הבדיקה שם נעשית ממילא. ואם התעקשת להשתמש בה כבדיקה תחליפית, ולוותר על שימוש בפרמטרים של שאילתא - דוד כבר ענה לך למעלה, וגם אתה הבנת שזה לא פתרון מושלם.אם כבר, עדיף פונקציה שמקבלת שם של שאילתא ורשימה של פרמטרים, ומבצעת השמה לפרמטרים של השאילתה.
-
@גגד אמר בהזרקת SQL באקסס:
@OdedDvir קיבלתי.
כלומר - מה שנשאר לוודא זה שהמספר הוא ISNUMERIC בלבד.
כעין זה מצאתי ב https://www.hacksplaining.com/prevention/sql-injection
אם כן פונקציה זו תספיק כפרמטר:Public Function SqlParameter(Text As String, Optional AsNumeric As Boolean = False) If AsNumeric Then If IsNumeric(Text) Then SqlParameter = Text Exit Function End If SqlParameter = Replace(Replace(Text, "'", "''"), "", """") End Function
ודרך אגב, אמנם יש אפשרות ב SQL נורמלי לכתוב שאילתות בזו אחר זו, אך באקסס אי אפשר.
לדוגמה הקוד הבא לא יעבוד:Sub A1() CurrentDb.Execute "SELECT טבלה1.שדה1 FROM טבלה1; DROP TABLE טבלה1;" End Sub
אבל עדיין שייך UNION...
יפה מאד, זה בדיוק מה שהוא אומר, אתה יכול עכשיו להתחיל לאסוף עוד דוגמאות ועוד דוגמאות ולפתור אותם.
אבל הנה עוד בעיה: מה עם אתה רוצה לקבל ערך שהוא לא int? אז צריך להוסיף גם את התו;
.
ועוד מעט נעלה עוד ועוד מקרים.. למה להמציא את הגלגל? -
@שמואל4
למה להמציא את הגלגל?
בשביל ללמוד, אבל יותר מזה -
באקסס יש פונקציות שנקראות DLookup, DMAX ועוד פונקציות אלו משתמשות בהזרקת SQL רשמית, ושם חייבים לבנות לזה גם הגנה וגם מניעת טעויות משתמשים תמימים (וזה מענה גם ל @OdedDvir ול @dovid שתמהו ע"ז).לגבי הבעיה של תו ;
איך מתבצעת הזרקה? בכל מקום בתכנות שמשתמשים ב Meta programming - טקסט שיש להריץ אותו כתוכנית עבור תוכנה כמו - SQL, HTML, וגם Template של C++ ועוד... קיים חשש שהלקוח יכתוב הוא את הטקסט לתוכנה.
איך יכול להיות שיכתוב? הרי הטקסט מסומן בגרשיים או גרש או <>? פשוט - שהוא בעצמו יסמן את זה בתוך הקוד.
נמצא שאם מבטלים את האפשרות של הסימון הזה אין ללקוח אפשרות להכניס את שום טקסט בקוד, אם הוא יכתוב ; זה יכניס ; לתוך הטבלה, לא לקוד הSQL.
עם ההגנה הזו גם פעולת UNION ו DROP לא תעבוד - זה יכניס את המילים האלו רק לתוך הטבלה.כך שאני גם לא כל כך מבין את הבעיתיות בזה - אם יש הוכחה ברמה מתמטית שאי אפשר להזריק, שוב אין חשש.
מה שכן, יש כאן את ההרגלי תכנות נכונים שזה חשוב מאוד גם בפנ"ע וגם שמא בשפה אחרת יהיה עוד סימון טקסט או חוקיות קצת שונה ושם יהיה אפשר להזריק משא"כ בפרמטרים.תודה רבה על הביקורת - ואשמח לעוד
-
כתבתי
אם כן פונקציה זו תספיק כפרמטר:
Public Function SqlParameter(Text As String, Optional AsNumeric As Boolean = False) If AsNumeric Then If IsNumeric(Text) Then SqlParameter = Text Exit Function End If SqlParameter = Replace(Replace(Text, "'", "''"), "", """") End Function
אבל יש לכאורה טעות בקוד - כי רק את סוג המרכאה המקיפה צריך לשכפל בשביל שישאר הטקסט נכון.
אם מקיף ' יש לשכפל רק את ' , אם מקיף " יש לשכפל רק את ".
לכן נראה לי הקוד הזה נכון יותר (זה מה שאני משתמש) - 2 פונקציות:Public Function Sql_InsertNumeric(MyVariant As Variant) As Variant ' לפני הכנסה כשרשור טקסט לפונקציה ' DLookup ' וכדומה, או לשאילתה שאי אפשר להכניס בה פרמטרים בדרך הרגילה. ' הפונקציה הנוכחית מוודאת שאין הזרקת 'קוד זדוני' לשאילתה על ידי וידוא שמדובר במספר If IsNumeric(MyVariant) Then Sql_InsertNumeric = MyVariant Else Sql_InsertNumeric = "" End If End Function Public Function Sql_InsertString(Text As String) As String ' לפני הכנסה כשרשור טקסט לפונקציה ' DLookup ' וכדומה, או לשאילתה שאי אפשר להכניס בה פרמטרים בדרך הרגילה. ' הפונקציה הנוכחית מוודאת שאין הזרקת 'קוד זדוני' לשאילתה, ומוסיפה גרש מכל צד לציון הטסקט 'תיקנתי כאן, כי בשאילתות וכן בקוד אם מקיף את הטקסט גרש בודד אין משמעות לגרשיים ולהיפך - כשמקיפים גרשיים אין משמעות לגרש Sql_InsertString = "'" & Replace(Text, "'", "''") & "'" End Function
ולשאילתת פעולה רגילה שאפשר להשתמש בה עם פרמטרים:
Public Sub RunSqlWithParameters(TextSql As String, ParamArray TextParameters() As Variant) On Error GoTo MsgErr Dim MyQuery As QueryDef Dim TextParameter As Variant Dim NumParameter As Integer NumParameter = 0 Set MyQuery = CurrentDb.CreateQueryDef("", TextSql) For Each TextParameter In TextParameters MyQuery.parameters(NumParameter) = TextParameter NumParameter = NumParameter + 1 Next MyQuery.Execute ExitErr: Exit Sub MsgErr: MsgBox Error$ Resume ExitErr End Sub
אשמח להערות.
(השמות SQL_INSERTSTRING ו Sql_InsertNumeric לא משהו... אשמח לשמוע שם אחר. יש עדיפות שיתחיל ב SQL למציאה קלה...)
-