מדריך להגנה על CSRF באבטחת אביב

1. סקירה כללית

במדריך זה נדון בהתקפות CSRF על זיוף בקשות בין אתרים וכיצד למנוע אותם באמצעות Spring Security.

2. שתי התקפות CSRF פשוטות

ישנן צורות רבות של התקפות CSRF - בואו נדון בכמה מהנפוצות ביותר.

2.1. דוגמאות לקבל

בואו ניקח בחשבון את הדברים הבאים לקבל בקשה המשמשת משתמשים מחוברים להעברת כסף לחשבון בנק ספציפי “1234”:

GET //bank.com/transfer?accountNo=1234&amount=100

אם התוקף רוצה להעביר כסף מחשבון הקורבן לחשבונו במקום זאת - “5678” הוא צריך לגרום לקורבן להפעיל את הבקשה:

GET //bank.com/transfer?accountNo=5678&amount=1000

ישנן מספר דרכים לגרום לזה לקרות:

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

2.2. דוגמה ל- POST

אם הבקשה הראשית צריכה להיות בקשת POST - לדוגמא:

POST //bank.com/transfer account No = 1234 & amount = 100

ואז התוקף צריך שהקורבן ינהל אותו דומה:

POST //bank.com/transfer accountNo = 5678 & סכום = 1000

גם לא או ה יעבוד במקרה זה. התוקף יצטרך - כדלהלן:

עם זאת, ניתן להגיש את הטופס באופן אוטומטי באמצעות Javascript - כדלקמן:

  ...

2.3. סימולציה מעשית

כעת, לאחר שהבנו כיצד נראית מתקפת CSRF, בואו לדמות דוגמאות אלה באפליקציית Spring.

נתחיל עם יישום בקר פשוט - ה- בנק בקר:

@Controller מחלקה ציבורית BankController {לוגר לוגר פרטי = LoggerFactory.getLogger (getClass ()); @RequestMapping (value = "/ transfer", method = RequestMethod.GET) @ResponseBody public העברת מחרוזות (@RequestParam ("accountNo") חשבון int לא, @RequestParam ("סכום") סכום int סופי) {logger.info ("העברה אל {} ", חשבון לא); ...} @RequestMapping (value = "/ transfer", method = RequestMethod.POST) @ResponseStatus (HttpStatus.OK) העברת חלל ציבורית 2 (@RequestParam ("accountNo") חשבון int לא, @RequestParam ("סכום") סופי int סכום) {logger.info ("העבר אל {}", חשבון לא); ...}}

ובואו שיהיה לנו גם דף HTML בסיסי שמפעיל את פעולת ההעברה הבנקאית:

 העבר כסף לסכום מספר חשבון ג'ון 

זהו הדף של היישום הראשי, הפועל בדומיין המקור.

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

עכשיו - בואו נראה איך דף התוקף ייראה כמו:

  הראה תמונות של חתלתולים 

דף זה יפעל בדומיין אחר - דומיין התוקף.

לבסוף, בואו נפעיל את שתי היישומים - המקור ויישום התוקף - באופן מקומי, ובואו ניגש לדף המקורי תחילה:

//localhost:8081/spring-rest-full/csrfHome.html

לאחר מכן, בוא ניגש לדף התוקף:

//localhost:8081/spring-security-rest/api/csrfAttacker.html

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

3. תצורת אבטחה באביב

על מנת להשתמש בהגנת Spring Security CSRF, ראשית עלינו לוודא שאנחנו משתמשים בשיטות ה- HTTP המתאימות לכל דבר שמשנה את המצב (תיקון, הודעה, לָשִׂים, ו מחק - לא GET).

3.1. תצורת Java

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

התצורה הריקה מוגנת @Override (HttpSecurity http) זורקת חריג {http .csrf (). השבת (); }

3.2. תצורת XML

בתצורת ה- XML ​​הישנה יותר (pre Spring Security 4), הגנת CSRF הושבתה כברירת מחדל ונוכל להפעיל אותה באופן הבא:

 ...  

התחיל מ אביב אבטחה 4.x - הגנת CSRF מופעלת כברירת מחדל גם בתצורת ה- XML; אנחנו כמובן יכולים להשבית אותו אם נצטרך:

 ...  

3.3. פרמטרים נוספים לטופס

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

3.4. באמצעות JSON

איננו יכולים להגיש את אסימון CSRF כפרמטר אם אנו משתמשים ב- JSON; במקום זאת, אנו יכולים להגיש את האסימון בתוך הכותרת.

ראשית נצטרך לכלול את האסימון בדף שלנו - ולשם כך נוכל להשתמש במטא תגיות:

ואז נבנה את הכותרת:

token = $ ("meta [name = '_ csrf']"). attr ("תוכן"); כותרת var = $ ("meta [name = '_ csrf_header']"). attr ("תוכן"); $ (document) .ajaxSend (פונקציה (e, xhr, אפשרויות) {xhr.setRequestHeader (כותרת, אסימון);});

4. מבחן CSRF מושבת

עם כל זה במקום, נעבור לעשות בדיקות.

ננסה תחילה להגיש בקשת POST פשוטה כאשר CSRF מושבת:

@ContextConfiguration (מחלקות = {SecurityWithoutCsrfConfig.class, ...}) מחלקה ציבורית CsrfDisabledIntegrationTest מרחיב את CsrfAbstractIntegrationTest {@Test public void givenNotAuth_whenAddFoo_thenUnauthorized () זורק חריג {mvc.Type.). content (createFoo ())). andExpect (status (). isUnauthorized ()); } @Test הציבור בטל givenAuth_whenAddFoo_thenCreated () זורק חריג {mvc.perform (פוסט ("/ foos"). ContentType (MediaType.APPLICATION_JSON) .content (createFoo ()). עם (testUser ())). ו- Expect (סטטוס ()) .נוצר()); }}

כפי ששמתם לב, אנו משתמשים בכיתת בסיס כדי להחזיק את ההיגיון הנפוץ של עוזרי הבדיקה - ה- CsrfAbstractIntegrationTest:

@RunWith (SpringJUnit4ClassRunner.class) @WebAppConfiguration מחלקה ציבורית CsrfAbstractIntegrationTest {@Autowired פרטי WebApplicationContext; @Autowired מסנן פרטי springSecurityFilterChain; מוגן MockMvc mvc; @ לפני התקנת הריק הציבורי () {mvc = MockMvcBuilders.webAppContextSetup (context) .addFilters (springSecurityFilterChain) .build (); } מוגן RequestPostProcessor testUser () {return user ("user"). סיסמה ("userPass"). תפקידים ("USER"); } String מוגן createFoo () זורק את JsonProcessingException {להחזיר ObjectMapper חדש (). writeValueAsString (Foo חדש (randomAlphabetic (6))); }}

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

פירוש הדבר שהתוקף יכול פשוט להשתמש בכל אחד מווקטורי ההתקפה שנדונו בעבר בכדי לפגוע במערכת בקלות.

5. מבחן CSRF מופעל

עכשיו, בואו נאפשר הגנה על CSRF ונראה את ההבדל:

@ContextConfiguration (classes = {SecurityWithCsrfConfig.class, ...}) מחלקה ציבורית CsrfEnabledIntegrationTest מרחיב את CsrfAbstractIntegrationTest {@Test public void givenNoCsrf_whenAddFoo_thenForbidden () זורק חריג {mvc.Type. (סוג). content (createFoo ()) .with (testUser ())). andExpect (status (). isForbidden ()); } @Test ציבורי בטל נתוןCsrf_whenAddFoo_thenCreated () זורק חריג {mvc.perform (פוסט ("/ foos"). ContentType (MediaType.APPLICATION_JSON) .content (createFoo ()). עם (testUser ()). עם (csrf ()) ) .andExpect (status (). isCreated ()); }}

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

כעת, בקשת POST פשוט תיכשל אם אסימון CSRF לא נכלל, מה שכמובן אומר שההתקפות הקודמות כבר אינן אפשרות.

לבסוף, שימו לב ל csrf () שיטה במבחן; זה יוצר א RequestPostProcessor שיאכלס אוטומטית אסימון CSRF חוקי בבקשה למטרות בדיקה.

6. מסקנה

במאמר זה דנו בכמה התקפות CSRF וכיצד למנוע אותן באמצעות Spring Security.

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


$config[zx-auto] not found$config[zx-overlay] not found