ადმინის ქვედომენი CSRF-ს არ აჩერებს: ოთხი შემოწმება გაშვებამდე
ახალი ჰოსტის სახელი ახალი წარმომავლობაა, ხშირად იგივე საიტი, ამიტომ same-site ქუქიები და მარტივი ფორმები მას კვეთს. შეამოწმეთ ტოკენები, კარიბჭე და ავტორიზაცია.
ადმინისტრირების ინტერფეისის admin.example.com-ზე გადატანა ნამდვილი გაუმჯობესებაა: ის ადმინის ქუქიებს საჯარო გვერდებისგან მოშორებულად ინახავს, ორ აპლიკაციას ცალკე ქეშს აძლევს და საშუალებას გაძლევთ უფრო მკაცრი ქსელური პოლიტიკა ერთ ჰოსტის სახელზე მიმართოთ. მაგრამ ეს CSRF-ის კონტროლი არ არის და საჯარო საიტის კოდს უსაფრთხოს არ ხდის შესული ადმინისტრატორის წინაშე ღიად დატოვებისთვის. გაყოფა ცვლის იმას, რასაც ბრაუზერი საზღვრად თვლის და არა იმას, რასაც სერვერი ამოწმებს, ამიტომ სამუშაოს დასრულებულად გამოცხადებამდე ეს ოთხი შემოწმება შეასრულეთ.
წაიკითხეთ წარმომავლობა და საიტი როგორც ორი სხვადასხვა სიტყვა
წარმომავლობა არის სქემა, ჰოსტი და პორტი, ამიტომ https://www.example.com და https://admin.example.com სხვადასხვა წარმომავლობაა. საიტი SameSite-ის მნიშვნელობით არის სქემა პლუს რეგისტრირებადი დომენი, ამიტომ ეს ორი ჰოსტის სახელი ჩვეულებრივ ერთი საიტია. ეს განსხვავება მთელი ხაფანგია: SameSite ატრიბუტი დედა-ქვედომენებს შორის არ დაგეხმარებათ, რადგან ბრაუზერი მოთხოვნას საიტთაშორისოდ საერთოდ არ თვლის. მიმართეთ ადმინის ინტერფეისი ნამდვილად სხვა რეგისტრირებად დომენზე, მაგალითად admin-example.net-ზე, და მოთხოვნა ნამდვილად საიტთაშორისო გახდება, და სწორედ იქ იწყებს SameSite=Lax ან Strict იმ სამუშაოს შესრულებას, რომელსაც შეგიძლიათ დაეყრდნოთ.
შეამოწმეთ ეს ბრაუზერში და არა მსჯელობით.
ჩატვირთეთ საჯარო საიტი, გახსენით დეველოპერის ხელსაწყოები და ნახეთ, რომელი ქუქიები მიაბავს ბრაუზერი ადმინის ჰოსტისკენ მიმართულ მოთხოვნას. თუ ქუქის Domain ატრიბუტი არ აქვს, ის მხოლოდ ჰოსტისთვისაა და საკუთარ სახელზე რჩება; თუ ატარებს Domain=example.com-ს, ის ყველა დედასთან მიდის, და ახალმა ქვედომენმა ამ ქუქისთვის არაფერი მოგცათ.
გაყავით პასუხის წაკითხვა მოთხოვნის გაგზავნისგან
ერთი და იმავე წარმომავლობის პოლიტიკა ზღუდავს პასუხების წაკითხვას წარმომავლობებს შორის. ის არ აჩერებს მოთხოვნის გაგზავნას და არ უშლის ხელს ფორმას გაატაროს ის მოწმობები, რომლებიც ბრაუზერს უკვე აქვს. მარტივი მოთხოვნა, ფორმის შიგთავსის ტიპით ან ჩვეულებრივი GET-ით, წინასწარი შემოწმების გარეშე მიეწოდება; შემდეგ CORS წყვეტს, შეუძლია თუ არა გამომძახებელ სკრიპტს პასუხის წაკითხვა. CSRF მთლიანად გაგზავნის მხარეს ცხოვრობს.
ამიტომ სერვერს სჭირდება ცხადი შემოწმება მდგომარეობის შემცვლელი ოპერაციებისთვის. სესიაზე მიბმული სინქრონიზაციის ტოკენი, ან სერვერზე შედარებული ორმაგი გაგზავნის ქუქი, ფარავს ამ შემთხვევას; Origin ან Referer-ის შედარება ღირს მეორე კარიბჭედ დამატება, მაგრამ არა ერთადერთად, რადგან ყოველი მოთხოვნა არ ატარებს ამ თავსართს და ყოველი პროქსი არ ინახავს მას. OWASP-ის CSRF-ის პრევენციის სახელმძღვანელო SameSite-ს რამდენიმე ფენას შორის ერთ ფენად თვლის ზუსტად ამ მიზეზით.
გადაწყვიტეთ, რას ამტკიცებს სინამდვილეში ქსელური კარიბჭე
ადმინის ჰოსტის წინ VPN-ის გასასვლელების ნებადართული სია კარგი კონტროლია და სუსტი იდენტობის მტკიცება. ის ამტკიცებს, რომ მოთხოვნა მოვიდა მისამართიდან, რომელსაც VPN გასცემს, რომლის გაზიარებაც ამ გასასვლელზე ყველას შეუძლია, და არაფერს ამბობს იმაზე, თუ რომელი ადამიანი ან მოწყობილობა დგას მის უკან. მოეპყარით მას როგორც შესვლის ფილტრს და არა როგორც ავთენტიფიკაციას.
შეინახეთ ის დამოუკიდებლად მოთხოვნის დონის შემოწმებებისგან. თუ სია ერთადერთი რამაა თავდამსხმელსა და მდგომარეობის შემცვლელ ბოლო წერტილს შორის, ერთი არასწორად კონფიგურირებული მარშრუტი, ერთი split-tunnel კლიენტი ან ერთი ნასესხები ლეპტოპი კონტროლს მთლიანად აშორებს.
დაარეგისტრირეთ აგრეთვე უარები მოსალოდნელი დიაპაზონების გარედან. მათი აფეთქება ყველაზე სასარგებლო სიგნალია, რომ ვიღაც ახლახან აშენებულ საზღვარს იკვლევს, ხოლო სიჩუმე სიგნალია, რომ ფილტრს საერთოდ არ აღწევს.
შეინახეთ ქუქიები, შესვლა და ავტორიზაცია ცხადი
ქუქის ფარგლები წყვეტს შედეგის უმეტეს ნაწილს. მშობელი დომენის ქუქი ადმინის ჰოსტს ეგზავნება, ამიტომ საჯარო საიტზე სკრიპტის ინექციას შეუძლია ადმინისტრატორის სესიით იმოქმედოს; მხოლოდ ჰოსტის ქუქის არ შეუძლია. ამჯობინეთ მხოლოდ ჰოსტის ფორმა, დაამატეთ Secure ატრიბუტი და გამოიყენეთ __Host- პრეფიქსი იქ, სადაც პლატფორმა მხარს უჭერს, რადგან ეს პრეფიქსი მოითხოვს Secure-ს, Path=/-ს და Domain ატრიბუტის არარსებობას. წაიკითხეთ პასუხის თავსართი და არა ქუქის ქილა: Set-Cookie: __Host-admin_session=...; Secure; Path=/; HttpOnly; SameSite=Lax, Domain ატრიბუტის გარეშე. ბრაუზერი ისვრის __Host- ქუქის, რომელსაც Domain აქვს, ამიტომ დედა ჰოსტებზე ჯერ კიდევ ხილული ქუქი იმის მტკიცებულებაა, რომ პრეფიქსი არასოდეს გამოყენებულა.
შემდეგ შეინახეთ ავტორიზაცია სერვერზე, ყოველი მოთხოვნისთვის, ყოველ ადმინის ბოლო წერტილზე და არა მხოლოდ შესვლისას. ნებადართული ქსელიდან მოსული მოთხოვნა მაინც უნდა ავთენტიფიცირდეს და ავტორიზდეს იმ ოპერაციისთვის, რომელსაც ითხოვს; ჰოსტის სახელი მოქმედი პირი არ არის. თუ საჯარო და ადმინის აპლიკაციები იზიარებენ შესვლის ნაკადს ან სესიების საცავს, ჩაწერეთ ეს კავშირი, რადგან ეს არის უმოკლესი გზა საჯარო საიტის ხარვეზიდან ადმინის ქმედებამდე.
ხელახლა შეამოწმეთ საზღვარი გაყოფის შემდეგ
გაუშვით ნეგატიური ტესტები და არა მხოლოდ ბედნიერი გზა: ტოკენის გარეშე საიტთაშორისო ფორმა უნდა უარყოფილ იქნას, სხვა სესიის ტოკენი უნდა უარყოფილ იქნას და არც ერთმა GET-მა არ უნდა შეცვალოს მდგომარეობა. შეამოწმეთ ქუქის ატრიბუტები დეველოპერის ხელსაწყოებში, დაადასტურეთ, რომ Origin-ის შემოწმება აქტიურდება შეუსაბამო მოთხოვნაზე, და სცადეთ ადმინის ჰოსტი VPN-ის დიაპაზონის გარედან, რომ ფილტრი მუშაობაში ნახოთ.
ამ არც ერთი რამ არ აშორებს XSS ხარვეზს თავად ადმინის აპლიკაციის შიგნით. ცალკე ჰოსტის სახელი ბრაუზერის მხარის იზოლაციის საზღვარია რეალური ღირებულებით და ის არ ცვლის უსაფრთხო კოდის შესრულების პრევენციას ან სერვერის მხარის მოთხოვნების დაცვას. გაყოფის შემდეგ სია უფრო მოკლეა, ვიდრე ჩანს: ცალკე წარმომავლობა, მხოლოდ ჰოსტის ქუქიები, ტოკენი ყოველ ცვლილებაზე, შესვლის ფილტრი, რომელსაც როგორც იდენტობას არ ენდობით, და ყოველი მოთხოვნისთვის გადაწყვეტილი ავტორიზაცია.