https://zenn.dev/tenntenn/articles/b452911b4200ff
2022年のセキュリティ・キャンプ全国大会に講師として参加しました。その際に、Goにおける脆弱性への対策はどうなっているのか調べました。この記事では、github.com/google/go-safeweb/safesqlがどのようにSQLインジェクションを防いでるのかについて解説します。
なお、@rungさんの文書を多いに参考にしております。また、セキュリティ・キャンプで用いた資料はこちらから閲覧できます。
独立行政法人情報処理推進機構(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は、GoogleがOSSとして公開しているセキュアプログラミングを行うためのライブラリです。go-safewebはGoogle公式の製品ではないことがREADMEに記載してあります。
go-safewebは、secure-by-defaultを掲げており、セキュアな状態をデフォルトとしたnet/httpパッケージやdatabase/sqlパッケージの代替になるパッケージを公開しています。
go-safewebにある、safesqlはdatabase/sqlパッケージのラッパーのようなパッケージです。しかし、SQLインジェクションがなるべく起きないように設計されています。
たとえば、(*sql.DB).QueryContextに該当する(*safesql.DB).QueryContextが存在します。シグネチャはほとんど同じように見えますが、第2引数のクエリ文字列がsafesqlの場合は、TrustedSQLString
型になっています。
TrustedSQLString
型は次のように定義されている構造体です。