Go对抗黑客:SQL注入与XSS防御实战

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么即使是Go开发者也会落入黑客的圈套?

\n\n

Go以其速度、简洁性和内置安全工具而闻名。但用“我用Go写代码,所以我很安全”这样的话来自我安慰,是一种危险的错觉。SQL注入和XSS攻击并非过去式。它们至今仍在每天搞垮网站、泄露数据库,而Go也不例外。

\n\n

问题在于,Go为开发者提供了强大的工具,但并不会替你使用它们。你可能会无意中通过fmt.Sprintf拼接SQL查询,或者输出未经转义的用户评论——于是攻击者就能访问你的数据库或窃取访客的Cookie。

\n\n

在本文中,我们将剖析两种最危险的攻击类型——SQL注入和跨站脚本攻击(XSS)——并展示如何利用原生Go及流行库来防范它们。你将获得的不是理论,而是可以直接插入到当前项目中的现成代码模板。

\n\n

Go中的SQL注入:如何产生以及如何彻底消灭

\n\n

典型错误:字符串拼接

\n\n

假设你有一个根据ID获取用户的端点。编写查询最幼稚(也最危险)的方式如下:

\n\n
package main\n\nimport (\n    "database/sql"\n    "fmt"\n    "log"\n    _ "github.com/lib/pq"\n)\n\nfunc getUserByID(db *sql.DB, userID string) {\n    // 危险!字符串拼接\n    query := fmt.Sprintf("SELECT id, name, email FROM users WHERE id = '%s'", userID)\n    rows, err := db.Query(query)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer rows.Close()\n    // ... 处理逻辑\n}
\n\n

如果攻击者向userID传入字符串1' OR '1'='1,查询将变成:

\n\n
SELECT id, name, email FROM users WHERE id = '1' OR '1'='1'
\n\n

瞧——他将获取数据库中的所有用户。而如果他输入1'; DROP TABLE users; --,你将丢失整个表。

\n\n

解决方案:参数化查询(预处理语句)

\n\n

Go的PostgreSQL、MySQL和SQLite驱动程序都支持预处理语句。它们将SQL代码与数据分离,驱动程序会自动转义危险字符。

\n\n
func getUserByIDSafe(db *sql.DB, userID string) {\n    // 安全:参数化查询\n    query := "SELECT id, name, email FROM users WHERE id = $1"\n    rows, err := db.Query(query, userID)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer rows.Close()\n    // ... 处理逻辑\n}
\n\n

注意$1——这是第一个参数的占位符。在MySQL中使用?符号。现在,即使userID包含1' OR '1'='1,驱动程序也会将其视为字符串值,而不是SQL代码的一部分。

\n\n

使用sqlx包

\n\n

github.com/jmoiron/sqlx库让代码更加简洁。它支持命名参数并自动扫描到结构体:

\n\n
import "github.com/jmoiron/sqlx"\n\ntype User struct {\n    ID    int    `db:"id"`\n    Name  string `db:"name"`\n    Email string `db:"email"`\n}\n\nfunc getUserByIDSqlx(db *sqlx.DB, userID string) (*User, error) {\n    user := &User{}\n    // 命名参数 :id\n    err := db.Get(user, "SELECT * FROM users WHERE id = :id", sqlx.Named("id", userID))\n    if err != nil {\n        return nil, err\n    }\n    return user, nil\n}
\n\n

重要提示:即使你使用GORM或Ent等ORM,也请确保其配置为使用预处理语句。某些旧版本的ORM可能允许“原始”查询。

\n\n

Go中的XSS:当你的网站搬起石头砸自己的脚

\n\n

XSS攻击是如何发生的

\n\n

XSS(跨站脚本攻击)发生在你将用户内容插入页面而未进行转义时。恶

博客

书籍推荐