最終改訂日 (yy/mm/dd):2014/11/21
はじめに
SQL インジェクションは、最も危険度が高い Web 脆弱性の 1 つです。その危険性の高さから、SQL インジェクションは OWASP トップ 10 の最上位項目となっています。SQL インジェクションが重大な脅威である理由は、この攻撃の場合、悪意のある攻撃者のコードにより 、データの窃盗やデータの変更、さらに場合によっては基礎の OS へのコマンドインジェクションができるように、Web アプリケーションの SQL ステートメントの構造を変えてしまうことが可能だからです。このチートシートは、「SQL インジェクション対策に関するチートシート」の派生著作物です。
パラメーター化されたクエリの例
SQL インジェクションを防止する最良の方法は、パラメーター化されたクエリを使用することです。次の表に、ほとんどの一般的な Web 開発言語でパラメーター化されたクエリを構築する方法を実際のコードサンプルによって示します。以下のコードサンプルは、Web アプリケーション内でのデータベースクエリ構築時の SQL インジェクション防止方法を Web 開発者向けに示すことを目的とするものです。
プリペアドステートメントの例
言語 - ライブラリ
|
パラメーター化されたクエリ
|
Java - Standard
|
String custname = request.getParameter("customerName");
String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";
PreparedStatement pstmt = connection.prepareStatement( query );
pstmt.setString( 1, custname);
ResultSet results = pstmt.executeQuery( );
|
Java - Hibernate
|
//HQL
Query safeHQLQuery = session.createQuery("from Inventory where productID=:productid");
safeHQLQuery.setParameter("productid", userSuppliedParameter);
//Criteria API
String userSuppliedParameter = request.getParameter("Product-Description"); // これも絶対に検証すべき
// 入力値検証を実行して攻撃を検出
Inventory inv = (Inventory) session.createCriteria(Inventory.class).add
(Restrictions.eq("productDescription", userSuppliedParameter)).uniqueResult();
|
.NET/C#
|
String query = "SELECT account_balance FROM user_data WHERE user_name = ?";
try {
OleDbCommand command = new OleDbCommand(query, connection);
command.Parameters.Add(new OleDbParameter("customerName", CustomerName Name.Text));
OleDbDataReader reader = command.ExecuteReader();
// …
} catch (OleDbException se) {
// エラー処理
}
|
ASP.NET
|
string sql = "SELECT * FROM Customers WHERE CustomerId = @CustomerId";
SqlCommand command = new SqlCommand(sql);
command.Parameters.Add(new SqlParameter("@CustomerId", System.Data.SqlDbType.Int));
command.Parameters["@CustomerId"].Value = 1;
|
Ruby - ActiveRecord
|
# 作成
Project.create!(:name => 'owasp')
# 読み取り
Project.all(:conditions => "name = ?", name)
Project.all(:conditions => { :name => name })
Project.where("name = :name", :name => name)
# 更新
project.update_attributes(:name => 'owasp')
# 削除
Project.delete(:name => 'name')
|
Ruby
|
insert_new_user = db.prepare "INSERT INTO users (name, age, gender) VALUES (?, ?,?)"
insert_new_user.execute 'aizatto', '20', 'male'
|
PHP - PDO
|
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
|
Cold Fusion
|
<cfquery name = "getFirst" dataSource = "cfsnippets">
SELECT * FROM #strDatabasePrefix#_courses WHERE intCourseID =
<cfqueryparam value = #intCourseID# CFSQLType = "CF_SQL_INTEGER">
</cfquery>
|
Perl - DBI
|
my $sql = "INSERT INTO foo (bar, baz) VALUES ( ?, ?)";
my $sth = $dbh->prepare( $sql );
$sth->execute( $bar, $baz );
|
ストアドプロシージャの例
SQL インジェクションの脆弱性が発生する可能性がある場所は、Web アプリケーション内に記述された SQL だけではありません。ストアドプロシージャを使用しており、この中で SQL を動的に作成している場合も、SQL インジェクションの脆弱性が発生する可能性があります。このような動的 SQL をセキュリティで保護するために、このような動的 SQL についても、バインド変数を使用してパラメーター化してください。さまざまなデータベースにおけるストアドプロシージャでのバインド変数の使用例をいくつか以下に示します。
言語 - ライブラリ
|
パラメーター化されたクエリ
|
Oracle - PL/SQL
|
通常のストアドプロシージャ。動的な SQL は作成されない。ストアドプロシージャに渡されるパラメーターは、必然的にクエリ内の該当の場所にバインドされるため、特別な措置は不要。
PROCEDURE SafeGetBalanceQuery(
UserID varchar, Dept varchar) AS BEGIN
SELECT balance FROM accounts_table WHERE user_ID = UserID AND department = Dept;
END;
|
Oracle - PL/SQL
|
EXECUTE による SQL 実行でバインド変数を使用したストアドプロシージャ。この動的 SQL への入力が "データ" であり、コードではありえないことを、バインド変数の使用によりデータベースに示す。
PROCEDURE AnotherSafeGetBalanceQuery(
UserID varchar, Dept varchar) AS
stmt VARCHAR(400); result NUMBER;
BEGIN
stmt := 'SELECT balance FROM accounts_table WHERE user_ID = :1
AND department = :2';
EXECUTE IMMEDIATE stmt INTO result USING UserID, Dept;
RETURN result;
END;
|
SQL Server - Transact-SQL
|
通常のストアドプロシージャ。動的な SQL は作成されない。ストアドプロシージャに渡されるパラメーターは、必然的にクエリ内の該当の場所にバインドされるため、特別な措置は不要。
PROCEDURE SafeGetBalanceQuery(
@UserID varchar(20),
@Dept varchar(10)) AS BEGIN
SELECT balance FROM accounts_table WHERE user_ID = @UserID AND department = @Dept
END
|
SQL Server - Transact-SQL
|
EXEC による SQL 実行でバインド変数を使用したストアドプロシージャ。この動的 SQL への入力が "データ" であり、コードではありえないことを、バインド変数の使用によりデータベースに示す。
PROCEDURE SafeGetBalanceQuery(@UserID varchar(20),
@Dept varchar(10)) AS BEGIN
DECLARE @sql VARCHAR(200)
SELECT @sql = 'SELECT balance FROM accounts_table WHERE '
+ 'user_ID = @UID AND department = @DPT'
EXEC sp_executesql @sql,
'@UID VARCHAR(20), @DPT VARCHAR(10)',
@UID=@UserID, @DPT=@Dept
END
|
参考資料
Authors and Primary Editors
Jim Manico - jim [at] owasp.org
Dave Wichers - dave.wichers [at] owasp.org
Neil Matatal - neil [at] owasp.org
Other Cheatsheets
Developer Cheat Sheets (Builder)
Assessment Cheat Sheets (Breaker)
Mobile Cheat Sheets
OpSec Cheat Sheets (Defender)
Draft Cheat Sheets
|