發現Webpack中洩露的api

R3col發表於2021-05-07

發現Webpack中洩露的api

已在先知社群發表,轉載請註明出處

1 - 安裝 reverse-sourcemap

需要配置好npm環境 (runoob教程)

使用命令(需要代理) npm install --global reverse-sourcemap 進行安裝

2 - 尋找xxx.js.map

如果有sourcemap的話,在js最後會有註釋:

//# sourceMappingURL=xxxxxxx.js.map

比如這裡我要下載MarketSearch.js.mapMarketSearch.js是與站點同名的js,應該是主要的js檔案)

  • 在開發者工具中搜尋.js.map (位置1)
  • 找到MarketSearch.js.map所在的js (位置2)
  • 找到對應的鏈URL (位置3)
    • 一般來說,靜態檔案會掛載在當前域名下,但不排除其他站點掛載的情況,所以需要找到對應的URL,比如這裡就不同站
    • 這裡MarketSearch.jsURL記為http://xxx.xxx/mulu/MarketSearch.js

3 - 下載xxx.js.map並獲取所有webpack打包檔案

使用curl -O http://xxx.xxx/mulu/MarketSearch.js.map

或者直接訪問http://xxx.xxx/mulu/MarketSearch.js.map 下載MarketSearch.js.map

使用命令reverse-sourcemap --output-dir ./MarketSearch MarketSearch.js.map即可獲取所有webpack打包檔案

4 - 使用IDE/其他編輯器尋找介面

我這裡使用的是vs code

直接使用全域性搜尋 左邊側邊欄的搜尋圖示,或者ctrl+shift+f

4-1 搜尋介面

搜尋介面有兩個方法:

一個是借鑑先驗請求的url,這種情況需要我們可以訪問到某些介面,比如非SSO的登入

另一個是直接搜尋,這種情況大多是我們沒法訪問到當前站點的介面

4-1-1 借鑑先驗請求的url

比如我們訪問的站點xxx.xxx存在登入介面,通過嘗試,發現會呼叫/MarketSearch/api/login介面

那麼我們可以通過不斷刪減來搜尋介面/MarketSearch/api/login,/api/login,/login

可以看到,當我們刪減到/api/login的時候,就可以找到介面對應的程式碼

這個介面是可以呼叫的,但是發現其定義的介面與實際訪問的介面不同(第五部分解釋,這裡使用了動態定義的介面)

4-1-2 直接搜尋

直接搜尋有兩種方法,根據請求方法,或者猜測命名規則進行搜尋

4-1-2-1 根據請求方法搜尋介面

介面大多是通過get/post方法進行訪問的,所以這是一個很好的關鍵詞

通過請求方法,可以搜尋到動態定義的介面(第五部分),避免找不到介面的問題。

而且,如果存在請求方法重寫的程式碼,通過請求方法搜尋可以發現這些程式碼的定義。

post

get

4-1-2-1 根據猜測命名規則搜尋介面

一般來說,admin,superadmin,manage之類的關鍵詞比較常見

此外,還可以根據站點名,可呼叫api命名規則,js命名規則進行搜尋。這個站點沒有這樣的介面,就不舉例了。

5 - 尋找動態定義的介面

剛好這個站點存在動態定義的介面(直接明文寫在js程式碼中的靜態介面相反):MarketSearch/api/login ,上面我們通過搜尋,只發現了/MarketSearch/api/user/login介面,這裡介紹一下如何尋找該介面。

首先搜尋login,可以看到在index.ts中對登入進行了定義

檢視index.ts,可以看到這裡定義了用到的檢視,繼續跟蹤Login檢視,命名為Login_1,路徑在./Login

開啟Login.tsx,可以看到根據vse_client_1.defaultMainView.Login檢視,建立了對應的元素,vse_client_1定義為vse-client

開啟vse-client目錄,尋找defaultMainView檢視的定義

跟蹤Login檢視,可以看到api_1路徑在./api,且Login檢視定義了遊客登入使用者登入兩個登入方式,這裡跟蹤使用者登入登入方法

使用者登入使用了LoginModal模態框

跟蹤LoginModal模態框,可以看到登入的行為通過yield api_1.api.login(input)來實現

api_1 = ./apiinput則是ItemKey生成的表單中使用者填寫的資料(username & password

跟蹤api_1.api.login

大致說一下這裡的邏輯:

  • key是鍵值,比如這裡呼叫的是api.login,則key === login

  • 對於每一個vse_share_1.Api定義的介面

  • 如果傳入的key與其中一個介面相同,且不為constructor(通過prototype原型讀取,所以需要排除建構函式),則向下繼續

  • login傳入__awaiter_

  • 通過axios_1.default.post(`/${NAMESPACE}/${vse_share_1.ShareConfig.apiPrefix}/${key}`, args)發起請求

    • ${NAMESPACE} === MarketSearch

      • 檢視名稱空間的定義

      • 跟蹤../share

    • ${vse_share_1.ShareConfig.apiPrefix} === api

      • 跟蹤vse-share,尋找ShareConfig

    • ${key} === login

    • args === input,即,由ItemKey生成的json{username:"xxx",password:"xxx"}

這種情況下,通過拼接預定義引數和傳入的api名稱,動態生成url路徑,避免了靜態儲存api路徑,使得尋找api介面需要花費的精力大大提升。(web安全狗流淚)

相關文章