因為資料庫基本上可以分成 SQL 跟 NoSQL 兩大類,昨天講完 SQL injection 之後今天該來講一講 NoSQL 的安全性了。但因為 NoSQL 又分成 Document-based(如 MongoDB)、Key-value(如 Redis)、Graph(如 Neo4J) 等等很多種,不太可能全部講過一遍,所以今天就拿最常被使用的 MongoDB 來說說
如果先前沒有用過 MongoDB 的話,一開始最容易犯的錯就是在啟動 Mongo Server 時沒有加上 --auth
把 Access Control 開起來,而是直接用 mongod --port <port>
來啟動
這樣一來即便你有做到像前天說的權限管理、根據權限需求劃分成不同的 user,但因為沒有啟動 Access Control,任何人都可以不需要帳號密碼就可以登入資料庫,並對你的資料庫進行任何操作,所以可能會造成非常嚴重的後果
那除了在啟動 MongoDB 時加上 --auth
之外,還有沒有什麼其他比較方便的方法可以啟用 Access Control 呢?答案就是在 /etc/mongod.conf
裡面直接把 Authentication 開起來,如此一來就不用擔心啟動時忘記下 --auth
,反正 mongod 在啟動時會自動去讀設定檔
Security:
Authentication: on
但如果你不是自己下 mongod 指令,而是用官方的 Docker image 來啟動 MongoDB。因為啟動 Access Control 已經是 Mongo 的 best practice 了,所以在使用官方的 image 時,只要你把 root user 的帳號密碼設定好,Mongo 就會自動把 Access Control 開起來然後建立好 root user,你只需要用 root user 登入後再根據需求新增其他低權限的 user 就好了(非常不建議直接把 root user 拿來用)
services:
mongo:
image: mongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
如果沒有特別設定的話,預設情況下 MongoDB 開起來就是在 27017 port,也因為這樣,很多駭客在網路上亂掃別人的資料庫時都會順便掃一下 27017,如果你一時大意帳號密碼設得比較簡單,或是根本就忘記開啟 Access Control,那駭客就可以輕易進入你的資料庫胡搞瞎搞
而要改 port 其實也很簡單,只要在啟動 mongod 時加上 --port <port>
來指定想要的 port 就好了,如果你比較懶的話,也可以到 /etc/mongod.conf
裡面加上 port 設定,那在啟動時就不會忘記之前開在哪個 port
net:
port: 12345
如果你是用 Docker 的話,因為 docker-compose 可以直接在 yml 裡面設定 port binding,所以只要直接把外部的任何一個 port bind 到 container 內部的 27017 就好了,完全不需要動 mongod 本身的設定
services:
mongo:
image: mongo
restart: always
ports:
- "12345:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
大部分時候,我們的資料庫上了雲端之後幾乎只有應用程式會直接存取他,所以比起讓任何人都可以從外部接觸到資料庫,不如就聽在某幾個特定的 IP 就好了,一種白名單的概念
譬如說我希望只有自己跟同一個子網路的機器可以連進來,那就可以只監聽 127.0.0.1
跟 192.168.128.1
這兩個 IP 位址,如此一來外部的駭客就沒辦法直接接觸到資料庫,雖然這也代表想在自己電腦上查 DB 時就需要先 ssh 上機器再連進 127.0.0.1
,但其實現在大部分 MongoDB 的 GUI client 也都支援這功能了,只要簡單設定一下 ssh key 讓他自動連進去就好了,所以還是非常推薦這種做法
net:
bindIp: 127.0.0.1, 192.168.128.1
而 Docker 的話也很簡單,只要你在 docker-compose.yml
裡面設定一下想要 bind 到哪個 IP 就好了,譬如說下面的設定檔就是只監聽 127.0.0.1
跟 192.168.128.1
這兩個 IP 位址的 12345 port,也是完全不需要動到 MongoDB 裡面的設定,所以哪天想改就改非常有彈性
services:
mongo:
image: mongo
restart: always
ports:
- "127.0.0.1:12345:27017"
- "192.168.128.1:12345:27017"
MongoDB 身為最熱門的 NoSQL 資料庫之一,如果不花點時間搞懂他的設定的話一不小心就可能會讓資料庫暴露在危險之中,尤其是 mongod 在啟動時不會自動加上 --auth
簡直是智障到不行,據我所知每年都有不少這類忘記開 Access Control 的 MongoDB 被攻擊,真心覺得應該要預設開啟 --auth
,如果不想要的話才手動下指令 mongod --no-auth
才對
今天已經是資料庫安全的第三天了,跟資料庫相關的內容就到這,如果對於這幾天的內容有問題的話歡迎在下方留言,我很樂意大家討論討論,都沒問題的話明天就要來講近年來大容器時代的霸主 Docker 了~