這不是一般的檔案伺服器,這是為了讓使用者在沒有 https 的情況下安全通訊,如果有漏洞 (無論是對 client 或是 server 而言),歡迎回報。
對 NAS 有興趣,於是自己在家設定路由,買樹莓派,建立自己的檔案伺服器。
本伺服器是依靠 server、和 client 都知道密碼的情況下,用該密碼 (password) 與其他隨機碼 (nonce) 產生對稱金鑰 (Session Key) 通訊。一開始會要求使用者輸入密碼。加密演算法 AES,模式 CBC,需要 key、iv,之後會提到如何產生。 信息摘要演算法 sha256
我雖希望可以常駐登入,但是用 cookie 容易遭受 CSRF 攻擊,所以只會有一個主介面 (index.htm),透過該介面 fetch 所需要的檔案,這樣密碼就可以存在 memory。
又稱 replay attack,是本伺服器抵禦的重點之一。發生時機是,每次都是由 client 傳送請求,server 再做對檔案操作,並回應 client。就算過程加密,駭客拿 client 請求封包,重新發送,控制 server 完成檔案操作,即便對他沒有意義。url 中,client 將真實的請求加密,並且附帶明文隨機碼 Cnonce,
http://127.0.0.1/?c=12685cb59d7229d9f0bb9fbe6120e115&nonce=3675955&padding=7&digest=2b93c1030be447de1f5909bf223180e8277116051f58651bac64e974d60c5e5a
(以上網址表示 ls 指令)
而 server 每次開機會產生新隨機碼 Snonce 以明文型式隨著腳本 (index.htm) 傳給 client,password 是不洩漏的 (現實通道),產生 key、iv 的公式如下。
constructor(password,Cnonce,Snonce) {
this.key = aesjs.utils.hex.toBytes(sha256(Cnonce+'*'+password + '*' + Snonce))
this.iv = aesjs.utils.hex.toBytes(sha256(Snonce + '*' + Cnonce)).slice(0, 16)
this.salt=sha256(Cnonce + '*' + Snonce)
}
server 確保每次 Cnonce 不一樣,就能抵禦重送攻擊,當 server 重啟時會產生 Snonce,確保不會接受啟動前的重送封包。
client、server 為了確認自己的封包是對的,沒被改過,必須要用信息摘要伴隨密文送傳送。
c 就是密文,digest 是摘要,nonce 是隨機碼,padding 是為了將明文填滿一個塊 (16 位元) 所填充的位元組數量。
可以把 c、digest、padding 視為得到明文並且確認明文沒有被竄改的的必要材料,缺一不可,而 nonce、password 視為一種工具,用來產生 iv、key,沒有他們也無法解開 c。傳送檔案是特別的情況,因為檔案需要跟網址分開放。網址的材料跟檔案的材料可以分開存,因為如果有人掉包檔案或網址,接收方一定解不開 (如下圖),結論就是這六樣東西隨便放別人也無法竄改,但是可以把檔案跟網址交換,為了避免這件事情,我讓兩者的存放關係不對襯。
生成 client 隨機數
加密程式
In javascript:
$(c_0,\ d_0,\ p_0)\ =\ K(m_0)$
In URL:
先將 body (檔案)
$(c_1,\ d_1,\ p_1)\ =\ K(m_1)$
將路徑訊息
$m_0'\ =\ (m_0,\ d_1,\ p_1)$
將
$(c_0',\ d_0',\ p_0')\ =\ K(m_0')$
In URL:
In body:
In headers:
In body:
以本伺服器最複雜的請求目錄為例子。
- client 做出 utf-8 請求字串,編碼 bits,進行摘要並加密,解碼成 16 進制字串 (utf-8),傳送。
- server 收到 hex (utf-8),轉二進制 (bits),解密確認摘要,以 utf-8 解碼成真實請求明文。
- server 將 dictionary 序列化成字串 (utf-8),編碼成 bits,摘要並加密,傳送。
- client 收到 bits,解密並確認摘要,解碼成 utf-8,反序列化成 dictionary。
接著就用 dictionary 渲染網頁,結構如下
{
"files":["fa.txt","fb.txt"],
"dirs":["d1","d2"]
}
- 順向訪問、逆向訪問 (透過 GUI)
- 上傳 (多檔案)、下載檔案
- 絕對路徑重新命名,包含檔案及資料夾
- 下載資料夾 (zip)
- 刪除資料夾、檔案
安裝
npm init
npm install
啟動
node server.js
建立 config 檔並且啟動
node server.js -a config.json
我原本的加密方法會導致相同的指令,例如取得根目錄,其摘要會是一樣的,這會給駭客留下線索,可能透過一些機器學習得到我們的資料夾結構,為了不要讓駭客得到訊息,我在雜湊中加鹽 (Cnonce、Snonce 的產物)。
hashf(data) {
return sha256(this.salt+sha256(data))
}
一開始需輸入使用者,如果輸入錯誤將只能讀,使用者會以隨機碼做加鹽雜湊,每次的值皆不同,並且跟著網址一起加密。