iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0

前言

在了解 cookie 的安全性設定之後,接下來的兩天要來講講跟 session 安全性有關的注意事項

很多網站在你輸入帳號密碼按下登入之後,會產生一串長長的 session ID 存在資料庫,然後把這串 ID 利用 Set-Cookie 存到你的 cookie 裡面去,如此一來當你下次從瀏覽器發出請求時,因為 cookie 裡面的 session ID 會一起被帶上,所以 API Server 就可以根據這個 ID 判斷你是誰,然後讓你進行發文、留言等等操作

Session ID 長什麼樣

光用講的太抽象了,我們來看看各網站的 session id 都長什麼樣子,首先這是 Gmail 的例子,在經過二階段驗證之後,他會給我一串 session ID 叫做 SIDCC,目測超過 100 個英數字(真的有夠長)

而我最近用來找房子的 591,他也是給一串很長的 session ID 叫做 591_new_session,整串將近 300 字,而且在眾多 cookie 裡面只有他被加上 HttpOnly,顯示這個 cookie 的安全性特別重要

那為什麼 session ID 都要這麼長呢?答案就是因為這樣才不會太容易被猜中。如果你的 session ID 只有五位數字,那基本上我只要寫個程式花點時間從 00000 試到 99999,應該就可以試出很多可用的 ID,再來就可以用這些 ID 輕易的假冒別人的身分進行各種操作

你的 ID 夠亂嗎

Session ID 光長是沒用的,因為如果只有長但卻不夠亂,那就很容易被猜出來。譬如說我就曾經看過 API Server 用看起來像是 MongoDB ObjectId 的東西當作 session ID,像是 507f1f77bcf86cd799439011

雖然由 MongoDB 自動建立的 ObjectId 看起來很長,但那個 ObjectId 其實是從 timestamp 轉過去的,因此只會增加不會減少,而且增加的速度也不會太快。知道了這個特性之後,我就一樣可以寫個程式去猜別人的 Session ID,猜到了之後就可以冒用別人的身份

實際範例

知道 Session ID 要夠長、夠亂之後,那在實際開發中應該怎麼做呢?說真的並不用特別做什麼,因為各框架幾乎都有比較熱門的 session 管理 library,只要好好善用他們不要自作聰明拿資料庫的 auto increment ID 來當 session ID 就好了

像如果你是寫 express 的話 express-session 就非常好用,你只需要直接用它當作 middleware,他就會自動幫你在瀏覽器上存一個夠長、夠亂、夠安全的 session ID,而且你也可以在這個 session object 中放各種使用者的資訊,需要時就可以拿出來用

var session = require('express-session');

app.use(session({
    secret: 'larry_is_handsome',  // 用來驗證 cookie 有沒有被篡改的 secret
    cookie: { secure: true }
}));

app.post('/login', function(req, res, next){
    // 登入時用信箱、密碼找找看有沒有這個使用者
    const user = db.users.findOne({ email: req.body.email, password: hash(req.body.password) })
    if (!user) { res.send('Invalid username or password') }
    
    // 把這個 session 對應到使用者的 ID
    req.session.userId = user._id
    res.send('登入成功')
});

app.get('/api/whoami', function(req, res, next){
    // 用 session 裡面儲存的 userId 去找使用者,就可以知道請求是誰發過來的
    const user = db.users.findOne({ _id: req.session.userId })    
    res.send(`你好啊 ${user.name} !`)
});

而 Go 的話也有一個 sessions package 可以用,因為用起來跟 express 非常像,去讀一下它的文件應該就會用,所以這邊就不寫範例了~

小結

今天講解了兩個跟 session ID 安全性有關的注意事項,雖然最後的結論是不用特別做什麼、直接去用別人造好的輪子就好,但至少你在用的時候會知道怎麼識別這些第三方套件的安全性,不會到真的出事時才發現這個別人造的輪子偷工減料、一上路就破,到時真的會欲哭無淚


上一篇
Day16-守護餅乾大作戰(三)
下一篇
Day18-Session 管理(二)
系列文
從以卵擊石到堅若磐石之 Web API 安全性全攻略30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言