+3

Web cache poisoning - Lỗ hổng đầu độc bộ nhớ cache (phần 3)

IV. Phân tích và khai thác các lỗ hổng Web cache poisoning (tiếp)

4. Cache parameter cloaking

Ở các phần trước, chúng ta đã cấu hình Varnish Cache ngăn chặn tấn công web cache poisoning bằng cách loại bỏ các tham số vô nghĩa khỏi quá trình xử lý caching, đồng thời chú ý đến các tham số UTM. Điều này hầu như đã ngăn chặn tốt việc tấn công web cache poisoning bằng cách tấn công Unkeyed query string và Unkeyed query string. Tuy nhiên, trong một số trường hợp kẻ tấn công có thể lợi dụng tính bất đồng trong việc xử lý cú pháp URL giữa cơ chế xử lý caching và ứng dụng, từ đó tạo ra một số yêu cầu tới URL đặc biệt nhằm bypass cơ chế ngăn chặn của ứng dụng.

Xét cấu hình Varnish Cache như sau:

sub vcl_recv {
    # Remove all parameters after the first "?"
    set req.url = regsub(req.url, "\?.*$", "");
    // ...
}

Với yêu cầu /?example=123?excluded_param=bad-stuff-here, cấu hình trên sử dụng regsuball() sẽ tìm thấy hai chuỗi được phân tách bằng dấu ?, lấy giá trị của tham số example và loại bỏ tham số excluded_param. Đối với server sẽ không chấp một một URL với hai dấu ?, nên chỉ chấp nhận tham số đầu tiên là example cùng với giá trị chứa cả payload của chúng ta.

Bạn đọc có thể luyện tập kỹ thuật tấn công này trong bài lab Parameter cloaking.

Để ngăn chặn tấn công Cache parameter cloaking, ta cần bổ sung một số bước kiểm tra và xử lý trong cấu hình Varnish Cache. Ví dụ cấu hình dưới đây:

sub vcl_recv {
  # Block requests with more than one question mark
  if (req.url ~ "\?.*\?") {
    return(synth(400, "Bad Request"));
  }
  
  # Strip out any parameters starting with "utm_" or containing "gclid"
  if (req.url ~ "\?(.*&)?(utm_|.*gclid.*)") {
    set req.url = regsuball(req.url, "([\?&])(utm_[^&=\s]*|.*gclid[^&=\s]*)(=[^&\s]*)?(&|$)", "\1");
  }

  # Set cache key to include only the relevant parameters
  if (req.url ~ "\?") {
    set req.url = regsub(req.url, "\?.*$", "");
  }
  return(hash);
}

Ở đây, ta đã thêm hai bước kiểm tra để ngăn chặn tấn công Cache parameter cloaking. Bước đầu tiên là kiểm tra số lượng dấu hỏi ? trong URL, nếu nó lớn hơn 11, chúng ta sẽ coi đây là một yêu cầu không hợp lệ và trả về mã lỗi 400400. Bước thứ hai là loại bỏ các tham số bắt đầu bằng "utm_" hoặc chứa từ khóa gclid trong URL. Cuối cùng, sử dụng regex để cắt bỏ tất cả các tham số không cần thiết khỏi cache key.

Tùy thuộc vào yêu cầu của ứng dụng cụ thể, ta có thể cần bổ sung thêm các bước kiểm tra và xử lý khác để đảm bảo an toàn cho cache khỏi các cuộc tấn công.

5. Exploiting fat GET support

HTTP GET request thường được sử dụng để truy xuất dữ liệu từ máy chủ, và không bao gồm phần thân (body).

image.png

Tuy nhiên, một số ứng dụng hoặc framework có thể hỗ trợ GET request bao gồm phần body yêu cầu, được gọi là "fat GET request".

Như vậy, kẻ tấn công có thể tạo ra một yêu cầu fat GET có dạng như sau:

GET / HTTP/1.1
Host vulnerable-website.com
...

...payload malicious data...

Varnish Cache xử lý yêu cầu này và đưa các dữ liệu độc hại lưu trữ trong cache, kẻ tấn công có thể lợi dụng để tìm kiếm hướng khai thác cho một số lỗ hổng khác và tấn công người dùng trang web.

Bạn đọc có thể luyện tập phương thức tấn công này trong bài lab Web cache poisoning via a fat GET request.

Để ngăn chặn loại tấn công này, có thể áp dụng một số cấu hình trên máy chủ web hoặc trên Varnish Cache, ví dụ như:

5.1. Chuẩn HTTP

Sử dụng chuẩn HTTP và hạn chế sử dụng phần body cho GET request.

5.2. Công cụ

Sử dụng một số công cụ chặn thư rác (spam) như CAPTCHA hoặc Google reCAPTCHA để giảm thiểu các request tấn công từ bot.

5.3. Cấu hình Varnish Cache

Cấu hình Varnish Cache để xử lý các request GET chứa phần body. Để làm điều này, có thể sửa file cấu hình VCL (Varnish Configuration Language) bằng cách thêm đoạn mã sau đây vào phần vcl_recv:

if (req.method == "GET" && req.body) {
    return (pipe);
}

Đoạn mã này sẽ kiểm tra xem request method là GET và có phần body không. Nếu có phần body, Varnish sẽ xử lý request bằng phương thức pipe, đồng nghĩa với việc Varnish sẽ đẩy request đến backend server mà không lưu vào cache.

5.4. Firewall

Ngoài ra, có thể sử dụng các giải pháp bảo mật như Web Application Firewall (WAF) để chặn các request độc hại. Với WAF, có thể tùy chỉnh các quy tắc để chặn các request không hợp lệ hoặc có chứa các chuỗi độc hại.

6. Từ lỗ hổng web cache poisoning thực hiện tấn công XSS

Kẻ tấn công có thể lựa chọn thời điểm ngay sau khi thời gian caching kết thúc, lợi dụng giá trị unkeyed là header X-Forwarded-Host thực hiện poisoning tài nguyên cache của ứng dụng.

Dựa vào cấu tạo trong response, có thể xây dựng payload tấn công XSS như sau:

X-Forwarded-Host: "></script><script>alert(origin)</script>//

Tài nguyên cache sau khi bị poisoning:

image.png

Tất cả người dùng sau khi truy cập tới ứng dụng được trả về tài nguyên cache sẽ trở thành nạn nhân của cuộc tấn công:

image.png

Để các bạn có thể nắm vững các bước khai thác lỗ hổng web cache poisoning dẫn tới tấn công XSS, chúng ta sẽ cùng phân tích bài lab Web cache poisoning to exploit a DOM vulnerability via a cache with strict cacheability criteria.

Sử dụng extension Param Miner chúng ta tìm được unkeyed value là header X-Forwarded-Host.

image.png

Chúng ta có thể sử dụng unkeyed value này để ghi đè giá trị data.host trong response. Chú ý rằng ứng dụng có thực thi hàm initGeoLocate() với data.host được sử dụng trong tham số input.

image.png

Hàm initGeoLocate() tại /resources/js/geolocate.js:

function initGeoLocate(jsonUrl)
{
    fetch(jsonUrl)
        .then(r => r.json())
        .then(j => {
            let geoLocateContent = document.getElementById('shipping-info');

            let img = document.createElement("img");
            img.setAttribute("src", "/resources/images/localShipping.svg");
            geoLocateContent.appendChild(img)

            let div = document.createElement("div");
            div.innerHTML = 'Free shipping to ' + j.country;
            geoLocateContent.appendChild(div)
        });
}

Hàm trên lấy dữ liệu từ jsonUrl, trong trường hợp trang web hoạt động bình thường là tại:

image.png

Sau đó sử dụng innerHTML tạo ra chuỗi Free shipping to United Kingdom trên giao diện trang chủ. Do không chứa cơ chế ngăn chặn các ký tự đặc biệt nên nếu có thể thay đổi giá trị j.country thì trang web ẩn chứa nguy cơ bị tấn công XSS:

image.png

Với unkeyed value X-Forwarded-Host, chúng ta có thể poison giá trị data.host, dẫn đến trong thời gian caching, ứng dụng thực hiện fetch dữ liệu từ nguồn do chúng ta control, chẳng hạn, với X-Forwarded-Host: anysite.com, ứng dụng sẽ lấy dữ liệu từ //anysite.com/resources/json/geolocate.json

image.png

Lúc này, do không tìm thấy //anysite.com/resources/json/geolocate.json nên không còn chuỗi trên giao diện:

image.png

Bởi vì bắt buộc cần truy cập đến path /resources/json/geolocate.json, nên có thể tạo ra path này tại chính exploit server được lab cung cấp. Cài đặt như sau:

image.png

Thêm giá trị X-Forwarded-Host là domain exploit server để poison cache:

image.png

Lúc này, ứng dụng lấy dữ liệu biến country từ exploit server của chúng ta để sinh chuỗi trên giao diện trang chủ:

{
"country": "<img src=1 onerror=alert(origin) />"
}

Dẫn tới người dùng truy cập trang web với response trả về từ tài nguyên cache sẽ thực thi payload kích hoạt XSS:

image.png

Các tài liệu tham khảo


©️ Tác giả: Lê Ngọc Hoa từ Viblo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí