Sunday, August 30, 2015

הדברים הפשוטים, חלק 2

The simple things pt. 2



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

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

במייקרוסופט הגו סדרה של דפוסי איום שמקבילים לתכונות האלה, כדי לעזור לנו לחפש חולשות, הם אפילו המציאו ראשי תיבות כך שיהיה קל לזכור:
STRIDE:
Spoofing - התחזות
Tampering - זיוף. 
Repudiation - הכחשה.
Information disclosure - הדלפת מידע. 
Denial of Service - שלילת שירות. 
Elevation of privilege - העלאת הרשאות (אם למישהו יש רעיון לתרגום טוב יותר, אשמח לשמוע עליו)/
עוד תכונה אליה לא אתייחס היא "בטיחות" – התכונה שגורמת לנו להאמין שהמוצר לא יתפוצץ למישהו בפרצוף.  לא שזה לא חשוב, אבל זה רלוונטי רק למוצרים מסויימים, ואני לא מבין בזה כלום.

בכל מקרה, אחרי כשכולנו מבינים טיפה יותר טוב מה הן תכונות האבטחה שאנחנו רוצים שיהיו למוצר שלנו, אני רוצה לסיים עם שלוש דוגמאות מתוך הדו"ח שקיבלנו. המטרה שלי היא בעיקר להדגים כמה פשוטות יכולות להיות הבעיות וכמה פשוט למצוא אותן. 
 חשוב לציין – גם אם נראה שחלק מהממצאים האלה זניחים או אפילו מטופשים, יש לכל ממצא כזה עלות גבוהה יחסית למוצר שלנו - גם מבחינת מאמץ שאנחנו צריכים להשקיע כדי לתקן את הממצאים בלו"ז שנראה ללקוח הגיוני (הוא הרי סימן את הממצאים כ"עדיפות גבוהה") וגם מבחינת המוניטין שלנו. כשאני נתקל בחולשות כאלה ההנחה הראשונה שלי היא שמי שכתב את התוכנה לא חשב על אבטחת מידע, זה לא משהו שאנחנו רוצים שהלקוחות שלנו יחשבו. 
ועכשיו, לדוגמאות:  
1.    משתמש יכול לבצע פעולה שלא הגיוני שתהיה מותרת לו: במקרה שלנו, ישנו "מנהל קבוצה", הוא רשאי ליצור משתמשים חדשים בתוך הקבוצה שלו. בנוסף, הוא יכול לשנות כמה פרטים שלהם.
הממצא היה פשוט - למרות שמנהל קבוצה לא יכול ליצור משתמש בקבוצה שאינה שלו, בממשק העריכה מנהל הקבוצה יכול להזיז את המשתמש לקבוצה אחרת.
2.    שיקוף קלט בחזרה למשתמש: כשמשתמש מנסה להיכנס ומכניס סיסמה לא נכונה (או טועה בשם המשתמש) מוצגת ההודעה "ניסיון הכניסה כשל עבור שם המשתמש X."  ההתקפה פשוטה - שב בין המשתמש לאתר שלנו (מה שקל מאוד לעשות בעזרת ההתקפה המוכרת כ"איש בדפדפן") וברגע בו הוא מנסה להיכנס, שנה את שם המשתמש שנשלח אלינו ל"X. אנא התקשר למספר: 1-800-1234567".
התוצאה? המשתמש רואה הודעת שגיאה שנראית לגיטימית ומפנה אותו להתקשר לתמיכה הטכנית במספר של המתקיף, שיכול עכשיו לנסות ולחלץ ממנו את הסיסמה. 
3.    אי וידוא קלט בצד השרת:
הממצא הזה הוא כנראה המביך ביותר מבחינתי, ההנחיה לבדוק קלט בצד השרת נמצאת בעמוד הראשון של כל מדריך לכתיבת תוכנה בטוחה. ואנחנו בודקים דברים כאלה עם כל פיתוח חדש שאנחנו עושים, אז פספסנו את זה בחלק ישן יותר של המוצר? נו באמת.
הממצא היה כזה: למשתמש מסוים יש גישה לדף, אבל לא את היכולת לערוך אותו. הוא לא רואה את הכפתורים שמוביל לעריכה (והם גם לא חבויים בדף). אבל, כשהוא מנסה לבצע פעולה הוא עוצר את הבקשה בצד שלו (למשל, בעזרת כלי כמו
fiddler) ומשנה את שם הפעולה מ"צפה" ל"ערוך" - ומקבל גישה לממשק העריכה.

------------------------------------------------------- 




Not long ago I wrote a post about a security report we got (or got smacked with, as some would claim) and I suggested that every tester should think a bit about the security when testing an application. One thing I didn't do enough, mainly since I didn't want the other post to be too long, is to emphasize one simple point:
When most people think about "security tests" they immediately start imagining the complex stuff implied in today's movies. You know, the scene where that super sophisticated hacker is using cool tools, hackers like this guy. And how could you defend against such smart people without being an equally smart security expert?
The reality, of course, is very different. Yes, from time to time you hear about such attacks (did anyone say Stuxnet?), but more often than not there are security vulnerabilities that are far easier to exploit, and simpler attacks. Can an employee in the company access confidential data without anyone knowing about it? Can a user change the clock settings on his PC in order to gain unlimited trial time for your software? Can an admin user see personal data about the users managed by him? Maybe this data isn't required in order to do his work?

So, to cut things short, there are many easy-to-find security problems, and you have only to look. But, before starting to wander around in that dark forest, perhaps it is best to describe the security properties that we want to ensure in the program. Usually, when measuring software security, we speak about six properties (there are some other lists, but I like that one), and sost security related attacks will hinder one (or more) of these properties.
·        Authentication – the ability to identify someone (or some process) is who he claims to be.
·        Integrity – The system's ability to ensure that data, either in transit or in storage, was not changed by an unauthorized entity or was corrupted.
·        Non-Repudiation - No one can perform an action and then claim "I didn't do it", since the system is able to provide credible evidence both action and actor (what was done, who did it)
·        Confidentiality – Information is available only to those allowed to see it.
·        Availability – the system can be used by its legitimate users any time where it is expected to work.
·        Authorization – The system will allow a user to perform only actions that are permitted to that user.


The nice fellows in Microsoft came up with a series of threat patterns that targets each item in the above list, and even gave us a cool acronym to remember it (this, by the way, is the reason the list above is ordered in such a way): STRIDE.
Spoofing
Tampering
Repudiation
Information Disclosure
Denial of service
Elevation of privilege

One thing I will not deal with here is the property called "safety" – the property that gives us confidence that the product won't blow up in someone's face. It's not that it is not important, it's just that it is relevant only to certain types of products, and I don’t understand much in this issue.

Anyway, after we are all a bit more comfortable around software security properties, I want to wrap things up by presenting three cases out of the report we got. My intent in quoting them is to show how simple they are and how easily they can be found.
I want also to note that while some of these may look negligible, or even silly, they all have a significant cost to our product – both in terms of effort we had to invest to fix these things in a schedule that meets our client's expectations, and in terms of reputation of our product: when I see such vulnerabilities I assume that those who wrote the software didn't care much about information security, and that's not something we want our customers to think.
So, that in mind – to the list:
1.    A user can perform an action that shouldn't be available to him:
In our system we have a group admin user that can create other users. All users created are in the same group as that group admin. However, when the group admin edits the user's properties, he can change its group to a different one.
The nice thing about this vulnerability? It does not require "hacking" of any sort, just legitimate user actions.
2.    Reflecting input back to the user:
we had a nice error message when a user could not login – it was something in the line of "Login attempt failed for user X"
Now, imagine a scenario where we get the username "X, please call 1-800-1234567".The user will see that in his error message and will call the attacker, that will now try to extract the password from the user. Changing the username from X to "X, call me" is fairly simple to achieve by injecting a simple JavaScript to the user (thus achieving a "man in the browser" attack) or routing the browser traffic via a proxy.
3.    Not checking for permissions on server side:
Really, this was what embarrassed me most. It's in the first page of just about any guide you'll find on dealing with implementing secure software.
What we had was a simple scenario – in a certain user in our application had the permissions to view a page, but not to edit it. The edit button was properly removed, but if someone would click "view" and then stop before sending the request (using a tool such as fiddler) and change "view" into "edit", we would grant access to the edit page.  

Thursday, August 20, 2015

על חשיבותה של שגרה

.
Keep your routine!

מדי פעם אני נתקל במישהו שממליץ "לשנות את הדרך בה אנחנו עושים דברים בדרך כלל" כדי לשפר את הבדיקות (למשל, אפשר לראות את טיפ מס' 71 בקובץ הPDF הזה). עד היום, זה תמיד נשמע לי הגיוני לגמרי - אם אני משנה את ההרגלים שלי, אגיע למקומות בקוד בהם עדיין לא ביקרתי, עם פוטנציאל למצוא באגים נוספים, לא? 
כמובן, כלל כזה הגיוני לא יכול להגיע בלי איזה "אבל..." קטן בצד שלו, והיום נתקלתי בהדגמה קטנה של זה. 
ומעשה שהיה כך היה: ישבתי לבדוק פיתוח חדש במוצר שלנו שעירב הרשאות למגוון משתמשים שונים. יצרתי את המשתמשים להם הייתי זקוק ויצאתי לדרך.
כניסה עם המשתמש הראשון, סקירה זריזה של המצב - הכל נראה בסדר גמור. שיחקתי עוד טיפה כדי לראות אם אני מוצא דברים מעניינים שלא הכרנו קודם ולא מצאתי שום דבר חשוד. שיחת טלפון הקפיצה אותי לרבע שעה בה ישבתי עם מישהו ועזרתי לו להבין כמה אספקטים של משימה שהוא ביצע (משהו שלדעתי היה דחוף יותר מהבדיקה שביצעתי) לפני שחזרתי למטלה המקורית שלי. נכנסתי עם המשתמש השני, בדקתי שדברים נראים בסדר גמור, כשלפתע היכתה בי תובנה - בכניסה הראשונה אנחנו דורשים מהמשתמש לבחור סיסמה חדשה, ולא ראיתי את הדף! לא ראיתי את הדף? לא יכול להיות. זה מנגנון שיושב בתוכנה שלנו כבר כמה שנים טובות בלי ששמנו לב לשום בעיה בו, ולא נגעו בשום דבר שאמור להשפיע עליו, בטוח נכנסתי בלי לשים לב שעברתי את הדף הזה. 
וזו הנקודה בה דווקא ההרגלים שפיתחתי תוך כדי בדיקה של המוצר הזה בשנים האחרונות נכנסו לפעולה - לא יכול להיות ששיניתי את הסיסמה, כי הסיסמה שאני עובד איתה היא הסיסמה הראשונית שאני נותן למשתמשים. יצאתי, נכנסתי שוב - זו אכן הסיסמה הראשונית. אחרי כמה רגעים בהם ניסיתי להבין מה עשיתי הפעם שלא קרה בעבר הצלחתי למצוא את הפעולה הנוספת שביצעתי כדי לגרום למצב הזה. חיטטתי קצת וראו זה פלא - הבעיה נמצאת אצלנו במוצר לפחות שנה, סביר להניח שקרוב יותר לעשור. זוכרים את כלל האצבע על בעיות באבטחת מידע?
בדרך הביתה חשבתי קצת על העניין הזה.את היעדרו של מסך שינוי סיסמה הצלחתי כמעט לפספס. בדרך כלל, כנראה שהייתי מתעלם מדבר כזה ומניח שבגלל שסוף היום אני כבר לא מרוכז, וממילא זה היה רק צעד בדרך למה שבאמת תכננתי לבדוק. אבל, דווקא בגלל שפעלתי על חצי-אוטומט החריגה הזו בלטה - היא שברה לי את הפרוצדורה.  בתור בונוס, בגלל שאני תמיד משתמש באותן סיסמאות כסיסמה ראשונה ושנייה, היה קל לי לבדוק (מהר) אם אני רק מדמיין או שבאמת יש כאן משהו. 

אז מה המסקנה שלי מכל העניין? כנראה שאני צריך לאמץ רעיונות קצת יותר בזהירות. אם עד היום הייתי בטוח שגיוון הוא תמיד טוב ושזו רק עצלנות שמונעת ממני לחפש כל הזמן דרכים חדשות לעבוד מול התוכנה שלנו, עכשיו אני כבר לא בטוח שאני רוצה לגוון כל כך הרבה. לפחות מבחינתי - שמירה על שגרה בכל הצעדים המקדימים מאפשרת לי גם לבצע אותם מהר יותר וגם מדגישה (לפחות בפני) את המקומות בהם יש חריגה מהצפי. לפחות כמו שזה נראה לי עכשיו, אני חושב לחלק את הבדיקות שאני מבצע לשני חלקים - הפיצ'ר שאני בודק וכל שאר הפרטים מסביב - הכנות, דברים שנמצאים לי ליד העין אבל לא באמת קשורים וכו'. בחלק הראשון, בו אני ממוקד ומחפש באופן אקטיבי "מה יכול להיות שבור כאן", אני מאמין שגיוון יכול להוסיף המון.
בחלק השני אני מעדיף לשמור על שגרה, נכון, אני בהחלט עלול להחמיץ ככה באגים שאולי הייתי תופס אם הייתי מתאמץ ומגוון קצת את הפעולות שלי,  אבל אני לא בודק את כל התוכנה שלנו בבת אחת, כי אם אעצור לבדוק כל חלק של המוצר שלנו בדרך למטרה, כנראה שכל משימה תיקח לי שבועיים. כמובן, אני ארשה לעצמי להתפזר אם אתקל במשהו חריג, אבל אם אני בודק פיצ'ר מסויים, כנראה שעדיף לי לבדוק אותו ולא פיצ'רים אחרים שבמקרה נמצאים בדרך. שמירה על שגרה בכל הפעולות מסביב עוזרת לי לתפוס מוזרויות במקומות בהם תשומת הלב שלי נמוכה יותר.

חוץ מזה, אני חושב שאפשר להסתכל על יצירת שגרה בפעולות היקפיות כעל סוג של mise-en-place, משהו שמאיץ את הבדיקות שלנו. 
---------------------------------------------------------------------------------
Here and there I come across a recommendation that can be summed up as "try to vary the way you would usually do things in order to make you tests more effective" (For instance, one might check tip #71 in the linked PDF). Up until today, this sounded to me like a perfectly reasonable advice - if I change my habits I will get to places in the code where I have not yet visited before, what can be wrong in that, right? 
Obviously, such a reasonable and decent rule cannot simply be without a tiny "but.." tagging along, and today I stumbled upon a nice example of it. The story is as follows: I was testing a new feature on our product, the feature revolved around permissions granted to various types of users to some new area in our system. So I created the users I needed, an off I went to test the feature. 
Using the first user, everything seemed just fine. I gave it a little effort when I tried to get around some of the limitations, trying to see whether I can get anything interesting out of it. Then my phone rang, which lead to me sitting with a team member and helping him to understand an aspect of a task he was doing - Something I considered to be more urgent than my original task. 
Returning to my test 15 minutes later, I logged in a the second user, checked that things looked OK, when a thought crossed my mind - I did not see the new password selection page! Normally, when a user is created in our system by an admin (that's the only way to create a user of the type I wanted), the user is required to change its password upon the first successful login. 
Hold your horses now... am I certain I did not see the page? could it be I just filled up what was needed and then forgot? this piece of logic exists for years in our system, probably over a decade, and no change could have affected it. This is where my habits proved useful:   logout, re-login, o.k. - I wasn't imagining things. the password is still my regular 1st password for such users. retracing my actions a bit helped me find the one extra step I did to cause this issue. five more minutes and I was able to confirm that this issue exists in our system well over a year (and probably closer to ten years). Oops. Remember my thumb-rule about information security problems?
On my way home I gave some thought to this whole affair. I have nearly missed the fact that the change password page did not appear. Normally, I would have ignored such a glitch and assuming that since it's already the end of the day, I have probably filled the page without noticing, and besides - This was only a step in my way to what I really wanted to test. had the users existed before I wouldn't even bother going through this whole process. However, because I was performing my actions on sort of an auto-pilot mode this deviation from the standard pattern was very visible to me - it broke my routine.  Also, since I use the same passwords for first & 2nd passwords I was able to easily (and quickly) validate I wasn't imagining things. 
So - what is my conclusion of this short anecdote? While I still think that a versatile performance of similar tests can be a good thing, I learned to take new ideas with a pinch of salt: if up until today I was convinced that variation is always a good idea and the main reason I don't do it is just me being lazy and falling into habits, now I'm not sure I want to avoid routines all of the time as I have found that they help me to notice deviations from standard behavior.  In fact, the way I see it now (at least, until a better thought will spring to mind), I think it may be helpful to divide the actions I do while testing into two distinct groups: the feature I'm testing and all of the peripheral actions required for this test.  For the first part, I think trying to be as divers as possible is great. it uncovers new behaviors of the software and teaches me a lot more about the feature under test. For the peripheral actions - setup, cleanup, stuff that are just there on the corner of my eye, I think sticking with my routine is preferred. True, it might miss a bug or two, but I'm not testing my whole software at once. I will defocus and allow myself to be sidetracked if I'll stumble across something suspicious, but my main goal is to test the feature I was set out to test. I don't have the time to go looking for problems in *every* dusty corner of my application, so why not leave the variations to times when I'm performing tests on that part? This way I can see problems even though I do not concentrate on that particular piece of software. In addition, I think one can consider this routine as a sort of mise-en-place that will speed up your testing, 

Thursday, August 13, 2015

לפעמים, צריך שמישהו יזכיר לך את הדברים הפשוטים

Sometimes, someone should remind you of the simple things

לפני זמן מה, אחד הלקוחות שלנו ביקש לקבל גישה לסביבת בדיקות כדי לבצע בדיקות אבטחה. כמו שקורה תמיד במקרים כאלה, הלקוח קיבל גישה, שיחק קצת ובסוף התהליך שלח לנו דו"ח מפורט של כמה עשרות עמודים. כיוון שהיה מדובר בלקוח לא קטן, הדו"ח שלו קיבל עדיפות גבוהה יחסית ומצאתי את עצמי קורא אותו מוקדם בבוקר. 
הציפייה שלי הייתה לקרוא משהו דומות לדו"חות שראיתי בעבר - אוסף של אי-הבנות, בעיות זניחות שנמצאו ע"י איזה כלי אוטומטי כזה או אחר וכמה בעיות שאנחנו כבר מודעים אליהן ולא נמצאות באחריותנו (בפרוטוקול אליו אנחנו מחוייבים יש חולשה מובנית שכל הכלים האוטומטיים מוצאים) ובעיות שרלוונטיות רק לסביבת הבדיקות שניתנה ללקוח. מתוך הבעיות האלה, עשרה אחוזים יסווגו כחמורות, שלושים כבינוניות וכל היתר בחומרה נמוכה. 
אלא שהפעם עברתי על הבעיות שהם מצאו, ומתוך בערך שבעה ממצאים חמורים, הצלחתי לאמת חמישה, ועוד שישה או שבעה לא טרחתי לשחזר כי הם דרשו יותר עבודה והם היו מצליחים בוודאות גבוהה (יש כאן יותר משבעה ממצאים כי הם החביאו תתי-סעיפים בתוך כל ממצא).  ולא רק שכמעט כל הממצאים היו מדוייקים, כל אחד ואחד מהם גרם לי להרגיש קצת יותר שהם תפסו אותנו עם המכנסיים למטה. 
למעשה, הדו"ח הזה גרם לי להתבייש מספיק כדי לאסוף את כל הבודקים שמתעסקים עם המערכת שלנו ולהעביר להם הדרכה על איך לבצע בדיקות אבטחה בסיסיות. תוך כדי שאני מכין את המצגת, נזכרתי בשני דברים שכבר ידעתי (באמת שידעתי, אחרת איך הם הגיעו למצגת?): 
·           בעיות אבטחה הן רעיון שצריך להיתקל בו לפני שיודעים לחפש אותו לבד.
·           בדרך כלל,  יש קשר הפוך בין חומרת בעיית האבטחה לבין הקושי לנצל אותה.
מטרת המצגת, אגב, הייתה פשוטה - שכל אחד ואחד מהבודקים שמתעסק בתוכנה יקדיש קצת זמן לבדיקות אבטחה ויסלק את הבעיות הקלות. כך, כשאנחנו מזמינים מומחי אבטחה לבדוק את המערכת שלנו, הם לא יבזבזו זמן וידווחו לנו על השטויות האלה, אלא (בתקווה) יפעילו את הכלים והכישורים שאין לנו וימצאו בעיות קשות יותר לאיתור. 

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

עכשיו, להרחבה קצרה של שתי הנקודות שהזכרתי: 
ברוב המקרים, קל יותר לחפש בעית אבטחה אחרי שרואים דברים דומים
רוב מי שמתעסק קצת עם מחשבים שמע בעבר על  הזרקת SQL, וכנראה שגם על cross-site-scripting, מי שלמד קורס רלוונטי ידע לספר ש stack overflow זה לא רק אתר האינטרנט שכל המתכנתים מבלים בו שעות, אלא גם איום שעלול לתת לתוקף שליטה מלאה על המכונה שמריצה את הקוד שלנו.  בדרך כלל, מי ששמע על אלה יכיר גם את המונח CSRF גם אם הוא לא לגמרי בטוח איך לגרום לזה לקרות. 
מצד שני, מתי בפעם האחרונה הקדשתם מחשבה לדרך בה אתם מנהלים את הלוגים של המערכת? או לאופן המדוייק בו אתם שומרים את מפתחות ההצפנה? והאם טרחתם אי פעם לתהות אם יכול להיות שפיצ'ר מסויים שמפותח עכשיו הוא פתח להדלפת מידע? ואם אתם מתעסקים עם אינטרנט אבל לא ממש בקטע של אבטחת מידע - אתם זוכרים שאסור לסמוך על שום דבר שאתם חושבים שאתם עושים בצד הדפדפן? אחרי שמישהו יראה לכם באג כזה, לא תוכלו להתעלם מבעיות כאלה.

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

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

אז הנה כמה דברים שאפשר לעשות, כמעט בחינם: 

  1. בצעו פעולות חוקיות, אבל נסו לעקוף כל מיני הגבלות - גם הגבלות ייחודיות לתוכנה וגם הגבלות שנובעות מתוך היגיון.למשתמש אסור לראות דף מסויים במערכת, ביטלתם את הלינק מהדף הראשי אבל הלינק מדף FAQ עדיין מוביל לשם? בעיה.משתמש יכול לבקש איפוס סיסמה ולספק כתובת דוא"ל שאינה כתובה במערכת? בעיה.
  2. כשאתם מחפשים מידע רגיש, סרקו את כל הפלט, לא רק מה שמוצג למשתמש מול העיניים.אתם מדפיסים סיסמאות של משתמשים לקבצי הלוג? בעיה.יש מידע שאתם לא רוצים להציג למשתמש שגולש לאתר שלכם והמתכנתים חושבים שלהגדיר את השדה כhidden זה טוב מספיק? עדיין אפשר לראות אותו בעזרת view source
  3. השתלטו על כל מקורות הקלט של האפליקציה שלכם: המשתמש הקליד משהו במסך? ומה אם זה באורך של חמישים אלף תווים? או מכיל קוד HTML?ומה קורה אם שרת של חברה אחרת איתה אתם עובדים מתחיל להחזיר תשובות מוזרות? או אם מישהו שיחק עם אחד מקבצי הקונפיגורציה  - האם הוא יכול להשיג משהו בעזרת זה? או להפיל את המערכת?
  4. בדקו מקרי שגיאה ונסו לנצל אותם.
    האם הודעת שגיאה חושפת מידע שהיא לא צריכה לחשוף?
    האם כשל בתקשורת עם שרת LDAP מאפשרת למשתמש שכבר נכנס למערכת לבצע פעולות שהוא לא מורשה לבצע?
    מערכת ההפעלה (או JVM, אם משתמשים בג'אווה) עלולה להדפיס לקובץ את הזיכרון של תהליכים שקורסים  - האם ניתן למצוא שם מידע רגיש?
והכי חשוב לזכור - בדיקות אבטחה הן עניין של צורת מחשבה יותר מאשר כישורים טכניים ספציפיים.
----------------------------------------------------------------------------
 A while ago, one of our customers requested access to a testing environment in order to perform some security testing on our system. As is usually the case, he got the requested access, played a bit with our system and in the end sent us a lengthy report detailing all of the findings.
Since this was a big customer, providing an initial response to the report was given high priority and I found myself reading the report early in the morning.
My expectation was to read a report very similar to other such reports I read in the past: a collection of misunderstandings, some negligible problems found by an automated tool scanning our system, some problems we are already aware of and can do nothing about (In the design of the protocol we are implementing there is a security issue that most automated tools find) and some issues that exist only in the test environment. Out of these, about 10% will be marked as "high", 30% more will be labeled as medium, and the rest are low severity issues.
This time, however, as I went over the seven high findings I was able to reproduce five issues and I didn't bother reproducing six or seven more issues  since they required a bit more work and I was certain they would be just as easily reproduced (you might have noticed that this sums up to more than just seven findings, this is because the customer was kind enough to group issues and detail them in sub-sections).
Worse: not only most of the findings were accurate, almost each and every one of them made me feel a bit more as if we were caught with our pants down.
In fact, this report made me ashamed enough to set up a meeting with all of the testers working on our system and give them a short lecture on security testing.
While I was preparing the presentation to the meeting, I recalled two things I already knew (Honestly, I knew those things. How would they otherwise end up in my presentation?):
·        Before being able to look for security issues yourself, you have to encounter the idea for that type of vulnerability.
·        Normally, there is an inverse connection between how simple is a security vulnerability and how severe this vulnerability is.
The goal of the presentation was simple: to have every tester in the room to invest some time doing security tests as part of the feature testing and get rid of the easy problems. This way, when we hire security expert to test our system, they won't waste time reporting the trivial problems but will (hopefully) put to use the tools and skills they have and we don't in order to find stealthier problems.
In a manner, this is also the purpose of this post: are you testing something? Perhaps you should invest some time to security testing, and maybe even avoid problems like FIAT had. At the end of the day, everyone can perform at least some security testing, it is only a matter of knowing what to look for.
After claiming that, I want to elaborate just a little bit on the two points I mentioned before:
Most of the time, it is easier to look for security problems after seeing similar things.
Probably almost anyone that knows just a tiny bit about computers has heard about SQL-injection, and it is very likely that the term "cross-site-scripting" will be familiar as well. Those that took a relevant course (even a basic one) will know that stack-overflow isn't just a website where programmers spend hours, but also a threat that could potentially give the attacker full control on your computer. Most of the time, they will know the term CSRF, even if they will be a bit sketchy on the details of how to exploit it.
On the other hand, when was the last time you stopped to examine the way you manage your cryptographic keys? Have you ever thought to check your application log files for usernames and passwords? Did you ever consider that the feature being developed right now might leak sensitive information to unauthorized personas? If you are testing a client-server system such as a website, do you remember that you cannot rely on any validation made in the client side?  After someone will show you such issues you will not be able to ignore these things.
The cases in the first group of attacks, those that everybody remembers, are cases of obvious, straightforward attacks. It is a clear case of a user doing things he's not allowed to do.  The second group items, however, might be little bit vague. In some cases you will have to argue your case to explain this is even an issue. Those parts are usually less technically challenging – which brings us to the second point:
If the vulnerability is easy to exploit, the problem is more severe
At first glance, this is counter intuitive. We are all used to think of the lone genius hacker writing super sophisticated attacks against our systems and causes creative damage to it. In practice, while this scenario is a viable possibility, there are much more cases of attackers with limited resources and knowledge. Moreover - even this creative hacker will start by looking for the easy targets (either since they will provide him with sufficient power, or they will be leveraged in the next attack), and just like a thief who sees that your house has an intruder alarm, he might go over to the neighbor's house since the profit there will not be as risky and will require less effort.
Don't provide the attacker with free gifts.
So, what to look for while performing security tests?
There is a significant difference between regular bugs and security vulnerabilities: in most cases, no one wants a regular bug to manifest. In most cases it will be at least a bit inconvenient to the user that only wants to use your application to the end it was built for. The bug might be caused by a faulty implementation of the logic, by some tricky race-condition or even by problematic requirements, but it is safe to assume the user will try to avoid bugs (except if they provide some cool outcome, but even then, the user isn't being malicious).
While performing security testing, this assumption is thrown out of the window. The basic assumption is that an attacker will do anything within his power to exploit those weaknesses to his own ends. This means that there is someone that will actively try to make your system fail in order to take advantage of this. This means you cannot make assumptions such as "no user will ever do this". The assumption in security testing is that you are facing a skilled and determined adversary. Furthermore, on top of being very good at causing damage, you also assume the attacker knows your application inside out, alongside with any security vulnerability you have.
As I wrote before – anyone can perform security tests, and even if they will not block the super-complex attacks, they will deter and filter out a large number of the less skilled attackers, will save your company from embarrassing security audit results and leave more time for the security tester your company hired for a short contract job to find effective findings and look for the more complex issues.
So, here are some ideas you can implement with almost zero cost (zero but the time you invest):
1.    Perform legitimate actions, but try to bypass boundaries and limitations – both limitations defined in your product and those that are just common sense.
a certain type of user shouldn't be able to access some page, and you removed  the link from the main page – did you also remove the link from the FAQ section? That's a problem.
A user can ask for reset password and provide his own, unregistered email address for the recover password link? This might be a problem.
2.    When searching for sensitive information, look at every output channel, not only what is visible to the simple user.
Are you printing passwords to the debug log files?  That's a problem.
There is something you don't want the user browsing to your website to see and the developers thought it would be enough to mark the element visibility as "hidden"? you can still see that by using "view source" functionality.
3.    Take control of every input channel to your application.
The user can type something on the screen? What if it's a 50 thousand characters long text? What if it contains HTML meta characters?
And what happens if a server of a third party you are using starts to return funny responses? Or if someone edits a configuration file? Can this crash the system?
4.    Look for error cases and try to leverage them.
Does an error message reveal more information than it should?
Will a failure in communicating with the LDAP sever enable a logged in user to perform actions he's not allowed to perform?
When a process crashes, the OS (or JVM, if you're using java) might print that process's memory to a file, does this file contain sensitive data?

And on a final note, it is important to remember: Security testing is more a mindset than it is a set of specific technical skills.