🍪Exploit a misconfigured CORS - Lab

TL;DR - show me the fun part❗

  1. Nạn nhận login vào app có hổng.

  2. Nạn nhân sẽ đi tới page của kẻ tấn công.

  3. Kẻ tấn công sẽ leak API key🎉.

I don’t get it. Show me the flow 🔎

  1. Người dùng được xác thực sẽ tới trang web tấn công.

  2. Trang web của kẻ tấn công chưa một đoạn JS độc hại cái mà sẽ yêu cầu trình duyệt gửi một cross-origin request được xác thực( qua XMLHttpRequest hoặc fetch) tới endpoint có lỗ hổng ở example.com.

  3. Endpoint có lỗ hổng reflect nhầm request của Origin header vàoAccess-Control-Allow-Origin response header.

  4. Trình duyệt thấy Origin của kẻ tấn công được cho phép. Do đó, nó cho phép JS read response.

How did this happen❓

Chúng ta đã nói trước đó rằng CORS là một cách để tạo ra một exception tới same origin policy. Nó cho phép đoạn JS để READ một cross-origin resource(Thực hiện đọc tài nguyên của trang web cross)

Ở đoạn JS, bạn có thể thực hiện các request CORSS-Origin được xác thực. Có nghĩa là, một JS có thể yêu cầu trình duyệt tự động gửi cookie cùng với yêu cầu.

Để cho phép loại request được xác thực này, điểm đến endpoint phải cho phép rõ ràng request được xác thực qua HTTP header

Access-Control-Allow-Credentials: true

Khi header trên được sử dụng, sau đó endpoint cũng phải chỉ định rõ ràng một origin trong giá trị của Access-Control-Allow-Origin header, ví dụ:

Access-Control-Allow-Origin: https://origin.secure-cookie.io

Vì các nhà phát triển phải chỉ định một origin. Các nhà phát triển nhầm khi cho phép bất kỳ orign nào thông qua việc reading the origin của request đến và sau đó "reflect" nó trong response header

Access-Control-Allow-Origin: <REQUEST ORIGIN HERE>

Điều này gây ra lỗ hổng bảo mật vì request có thể đến từ origin của kẻ tấn công và nó sẽ được reflect trong header được phép. Do đó, JS từ trang web của kẻ tấn công sẽ được phép read response và rò rỉ dữ liệu của người dùng.

Analysing the attack 👀

Chúng ta sẽ xem xét ứng dụng có lỗ hổng sau:

  1. Mở dev tool rồi chuyển qua tab network monitor ở trình duyệt của bạn

  2. Một người dùng được xác thực có thể generate API key bằng cách nhấn vào "Generate API key".

  3. Khi kích hoạt nút generate sẽ trigger đoạn JS này:

    function get_api_key(){
    var options = {
    method:"GET",
    credentials: 'include'
    }
    var users = fetch(url="https://demo-api.secure-cookie.io/getKey",options);
    users.then(resp => {
               return resp.json()
    }).then(data => {
            update_key_html(data);
         })
    }
  4. Đoạn JS này sẽ yêu cầu trình duyệt tạo GET request tới https://demo-api.secure-cookie.io/getKey.

  5. Tùy chọn credentials:'include', sẽ cho trình duyệt thực hiện request được xác thực (thêm cookie dọc theo bên request). Theo mặc định mà không có tùy chọn này, trình duyệt sẽ không bao gồm cookie.

  6. Endpoint có lỗ hổng sẽ response header như này:

#Reflects orgin(https://csrf.secure-cookie.io) của request ở “Access-Control-Allow-Origin” header
Access-Control-Allow-Origin: https://csrf.secure-cookie.io 

#Cho phép GET method
Access-Control-Request-Method: GET

#Cho phép người gọi gửi request xác thực kèm cookie 
Access-Control-Allow-Credentials: true

Làm thế nào để kẻ tấn công exploit điều này ❓

Ở lab này, hãy mở trang của kẻ tấn công:

  1. Lưu ý rằng ngay khi bạn/nạn nhân mở trang, khóa API bị hack

  2. Trang web của kẻ tấn công chứa đoạn JS mà thực hiện cùng một công việc chính xác mà chúng ta đã giải thích trong các bước (4, 5, 6) ở trên.

  3. Endpoint có lỗ hổng sẽ reflect tới origin bị tấn công https://s3-eu-west-1.amazonaws.com trong respone header

Access-Control-Allow-Origin: https://s3-eu-west-1.amazonaws.com
Access-Control-Request-Method: GET
Access-Control-Allow-Credentials: true

Vì orgin của kẻ tấn công được cho phép, JS trong trang kẻ tấn công có thể đọc API Key🎉.

Show me the source code of the backend❓

Cho ví dụ này, chúng ta sẽ sử dụng Python cho backend. Đoạn code chứa lỗ hổng ở endpoint /getKey

def get_key():
    #Đọc request header tới và láy giá trị của Origin
    rcvd_origin = request.headers.get("Origin")
    resp = make_response(jsonify(key=GetRandom.session(size=16)))
    
    #Reflect origin tới ở response header Access-Control-Allow-Origin
    resp.headers['Access-Control-Allow-Origin'] = str(rcvd_origin)
    resp.headers['Access-Control-Allow-Credentials'] = 'true'
    resp.headers['Access-Control-Request-Method'] = 'GET'
    
    #Gửi response
    return resp

Conclusion

Đây là một lab đơn giản phân tích rõ hổng hổng liên quan tới CORS phần mở rộng cho SOP. Cảm ơn các bạn đã đọc bài..

Last updated