node.js 啟動後放棄 root 權限
node.js 當伺服器運行時,需要有 root 權限才能綁定 80 連接阜, 所以有時會用 sudo 來執行 node.js。 但如果 node 有 root 權限,被挾持後相當於讓駭客取得了 root 權限。 posix 有 api 可以讓程序執行時改變自己的 uid, 從而能在以 root 權限執行後放棄 root 權限。
process.getuid() // 0 root
// 可以傳入 username 或 uid
// 變成普通的使用者 gholk
process.setuid('gholk')
// 失敗,現在只是普通的使用者了,
// gholk 沒有權限改自己的 uid
process.setuid('root')
一開始是簡單用 setuid 把 root 換掉, 但要注意是換成一般人後就換不回來了, 而且也沒辦法改自己的 uid gid。 所以如果 gid uid 都要改的話, 要在還有 root 權限時改自己的 gid, 再改自己 uid;不然先改 uid 會沒辦法改 gid。
const express = require('express')
const app = express()
app.listen(80, () => {
console.log('server start')
const user = 'gholk'
process.setgid(user)
process.setuid(user)
console.log('drop root')
})
但後來發現一個問題,setgid 後雖然有了 user 的 group,
但只有 user 的 group,也就是 uid 對應的 gid,
而 user 的其它 group 像 sudoer、docker 都沒有。
又研究了一下,發現是要用 initgroup 才對,
會根據 /etc/group
把該使用者的所有群組查出來。
所以正確流程應該是:
function switchUser(process) {
const user = 'gholk'
process.initgroups(user, user)
process.setgid(user)
process.setuid(user)
console.log('drop root')
}
詳細 可以查 node.js 的 api 。
因為最近開始寫 node.js 配 express, 想把自己一些機器上的程式能對外發布, 最簡單就是用 web api,但又不太想寫 php, 就用 express 了,來學個比較強的 server。