昨天讲了在各个资料库中都通用的权限管理,而今天要则是要谈谈所有 SQL 的头号公敌:SQL injection
虽然大部分人都已经知道 SQL injection 的原理了,不过这边还是再简单说明一下,所谓的 SQL injection 就是在 SQL 里面插入一些怪怪的东西,藉以达到攻击的效果
譬如说这是一个用 Node.js 写成的 API Server,使用者输入帐号密码後,程序就会用使用者输入的帐号密码组合出 SQL statement 到资料库中捞看看有没有对应的使用者
const express = require("express")
const app = express()
app.post('/api/login', (req, res) => {
// 使用者输入的帐号密码
const { email, password } = req.body
// 用帐号密码组出 sql statement
const statement = `SELECT * FROM users WHERE email='${email}' AND pass='${hash(password)}'`
const user = await db.query(statement);
// 有捞到东西就代表登入成功
if (user) {
res.json('login success')
}
})
但因为使用者可以自己决定要输入什麽资料,只要懂一些 SQL 语法,就可以输入 1' OR '1'='1' --
作为 email,然後把整个 SQL statement 变成 SELECT * FROM users WHERE email='1' OR '1'='1'
,让他百分之百登入成功
要防范这类的攻击,要做的第一件事情就是之前在 Day2 讲的格式验证,如果你有去检查使用者输入的 email 格式是不是怪怪的,那像 1' OR '1'='1' --
这种奇怪的输入在第一时间就会马上被拒绝掉,完全没有通过的可能
虽然格式验证并不是正规用来防御 SQL injection 的做法,而且厉害的骇客还是可以想其他方法既通过验证又达成 injection,但假如你的 API Server 真的有 SQL injection 的漏洞,那有一些基本的验证也会让这些漏洞更难被触发,因此我个人建议格式验证还是要有,反正安全性这种东西当然是越高越好,而且格式验证的成本也满低的不至於拖慢 Server 的速度
除了格式验证之外,正规的做法是使用资料库中 Prepared Statement 的功能,这样就可以预先把变数的位置保留下来,等真正要进行 query 才把那些变数以「值」的方式丢给 SQL Server
如此一来资料库在处理时就知道 email
跟 hash(password)
这两个字串并不是语法而是单纯的值,所以如果攻击者使用 1' OR '1'='1' --
作为 email 想要进行 SQL injection,资料库就不会把它当成语法来看待,而是会真的到 table 里面去找找看有没有谁的 email 是 1' OR '1'='1' --
(当然不会有XD),所以就不会找到任何使用者,也就不会让攻击者成功登入
app.post('/api/login', (req, res) => {
// 使用者输入的帐号密码
const { email, password } = req.body
// 用 ? 把变数的位置保留下来,在 query 时才把值给 SQL Server
const statement = `SELECT * FROM users WHERE email=? AND pass=?`
const user = await db.query(statement, [email, hash(password)]);
if (user) { res.json('login success') }
})
今天讲了怎麽透过格式验证及 Prepared Statement 来防范 SQL injection,虽然这已经是业界常识所以大家应该都已经很熟了XD,不过还是不厌其烦的帮大家复习一下
关於今天的内容有什麽问题欢迎在下方留言,没问题的话明天就要来讲讲 NoSQL 的部分了~
今天来用 Cloudflare Workers 写个有趣的东西吧! 你的 IP 是不是 ? 很酷吧!...
▉补一下,昨天说的,不知道怎麽评弱点跟威胁分数的话 技服中心 教材下载 共通性规范| https:/...
昨天稍微提了一些我切画面时, 对 HTML 的规划, 今天就来讲 CSS 的部分啦! (铁人赛剩一天...
Photo by KOBU Agency on Unsplash 文章同步发布於:https://...
本篇文章实现从本地端的 K8s 群集操作 GKE。先从 GKE 上的群集 .kube/config ...