https://zenn.dev/tenntenn/articles/b452911b4200ff

og-base_z4sxah.png

はじめに

2022年のセキュリティ・キャンプ全国大会講師として参加しました。その際に、Goにおける脆弱性への対策はどうなっているのか調べました。この記事では、github.com/google/go-safeweb/safesqlがどのようにSQLインジェクションを防いでるのかについて解説します。

なお、@rungさん文書を多いに参考にしております。また、セキュリティ・キャンプで用いた資料はこちらから閲覧できます。

SQLインジェクションとは?

独立行政法人情報処理推進機構(IPA)が公開している安全なウェブサイトの作り方を見ると、SQLインジェクションは以下のように説明されています。

データベースと連携したウェブアプリケーションの多くは、利用者からの入力情報を基にSQL文(データベースへの命令文)を組み立てています。ここで、SQL文の組み立て方法に問題がある場合、攻撃によってデータベースの不正利用をまねく可能性があります。このような問題を「SQLインジェクションの脆弱性」と呼び、問題を悪用した攻撃を、「SQLインジェクション攻撃」と呼びます。

問題のあるSQL文の組み立て方法とは、プレースホルダーを用いずに文字列結合などでSQL文を構成することです。たとえば、次のようなSQL文の組み立て方はSQLインジェクションの対象となり得ます。

query := "SELECT * FROM users WHERE user_id = '" + req.FormValue("user_id") + "'"

req.FormValue("user_id")は、*http.Request型のFormValueメソッドの呼び出しであり、リクエストから取得した文字列になります。そのため、"1' OR '1' = '1"のような値が送られてくるとすべてのユーザの情報が取得できてしまいます。

そのため、問題のある文字列結合を避ける方法が必要となり、静的解析ツールなどが作成されています。

go-safeweb

go-safewebは、GoogleがOSSとして公開しているセキュアプログラミングを行うためのライブラリです。go-safewebはGoogle公式の製品ではないことがREADMEに記載してあります。

go-safewebは、secure-by-defaultを掲げており、セキュアな状態をデフォルトとしたnet/httpパッケージやdatabase/sqlパッケージの代替になるパッケージを公開しています。

safesqlとSQLインジェクションを防ぐしくみ

go-safewebにある、safesqlはdatabase/sqlパッケージのラッパーのようなパッケージです。しかし、SQLインジェクションがなるべく起きないように設計されています。

たとえば、(*sql.DB).QueryContextに該当する(*safesql.DB).QueryContextが存在します。シグネチャはほとんど同じように見えますが、第2引数のクエリ文字列がsafesqlの場合は、TrustedSQLString型になっています。

TrustedSQLString型は次のように定義されている構造体です。