我开始使用 Common Lisp 玩一些业余爱好 webdev 项目。
对于数据库访问,我计划使用 mito 和 sxql。我试图找出是否需要做任何额外的事情来保护自己免受 SQL 注入,但我无法找到任何相关资源。不幸的是,我的 CL 和 SQL 知识不足以评估这一点。
在这个答案中提到,将
mito:retrieve-by-sql
与:binds
一起使用可以“编写原始sql查询并安全地绑定值”。我相信这个例子会使用 prepared statements,但是用其他方法来编写像 mito:retrieve-dao
或 mito:retrieve-by-sql
这样的查询,以及使用 sxql:select
和其他 sxql
助手构建的查询呢?
它们的设计也是安全的吗?我很高兴看到上面的库是如何解决这个问题的。
我们一起尝试一下 SQL 注入吗?
(defun connect ()
"Connect to the DB."
(mito:connect-toplevel :sqlite3 :database-name "myapp.db"))
(connect) ;; creates myapp.db on the current working directory
(mito:deftable user ()
((name :col-type (:varchar 64))
(email :col-type (or (:varchar 128) :null))))
(mito:ensure-table-exists 'user) ;; creates a table
(mito:create-dao 'user :name "me") ;; creates a user
(mito:find-dao 'user) ;; retrieves our user
此 SQL 命令会删除并丢失用户表:
$ sqlite3 myapp.db
sqlite> .tables
user
sqlite> drop table user ;
sqlite> .tables
<<nothing>>
我们可以根据用户提交的值安全地创建新行吗?
(mito:create-dao 'user :name "; drop table user;")
;; => #<USER {1007585063}>
(inspect *)
The object is a STANDARD-OBJECT of type USER.
0. CREATED-AT: @2024-10-15T17:18:32.148719+02:00
1. UPDATED-AT: @2024-10-15T17:18:32.148719+02:00
2. SYNCED: T
3. ID: 1
4. NAME: "; drop table user"
5. EMAIL: NIL
> q
创建了一个新用户,名称为“; drop table user;”,表未删除。
这表明您可以安全地从 Web 表单输入创建对象。
现在想象一下您将用户输入提供给
mito:select-by-sql
:
(mito.dao:select-by-sql 'user "drop table user;")
这会掉落桌子。呃。
WDYT?