node.jsでMySQLの疑問符プレースホルダによるSQLインジェクション対策

提供: Node.js/JavaScript入門
2014年9月2日 (火) 01:38時点におけるDaemon (トーク | 投稿記録)による版 (ページの作成:「node.jsでMySQLサーバに接続し、SQLを実行するときにSQLインジェクション対策を忘れてはいけません。SQLインジェクション対策...」)

(差分) ←前の版 | 最新版 (差分) | 次の版→ (差分)
移動: 案内検索
スポンサーリンク

node.jsでMySQLサーバに接続し、SQLを実行するときにSQLインジェクション対策を忘れてはいけません。SQLインジェクション対策として、ここでは、疑問符プレースホルダを使用します。

読み方

SQLインジェクション
えすきゅーえる いんじぇくしょん
疑問符プレースホルダ
ぎもんふ ぷれーすほるだ

概要

以下は、任意の番号を受け取って、その番号と一致するidのuserのデータを引っ張るときのSQLの例です。

SELECT * FROM USER WHERE id=番号

番号をSQL文と単純に連結するには、適切にエスケープしなければなりません。

var sql = 'select * from user where id=' + number;

エスケープをプログラマが意識せずに扱うには、疑問符プレースホルダが簡単です。 疑問符というのは、記号 ? のことです。

SELECT * FROM USER WHERE id=?

このSQLを実行するときに、? に部分に値をバインドして、SQLを実行します。自動的にSQLは、エスケープされます。

コードを部分的に抜粋すると、以下のようなコードになります。 query()の第2引数に、渡したい値を指定します。

var sql = 'select * from user where id=?';
var id = 1;
var e = my_client.query(sql, [id], function (err, rows, fields) {

前提となるデータベースのテーブル

CREATE DATABASE test;
USE test;
CREATE TABLE test.USER (id INT, name VARCHAR(20));
INSERT INTO USER VALUES(1,'a');
INSERT INTO USER VALUES(2,'b');

ソースコード

/*
 * mysql_query1.js
 * Copyright (C) 2014 kaoru <kaoru@bsd>
 */
var db_host = '127.0.0.1';
var db_user = 'root';
var db_pw = '';
var db_name = 'test';
 
var mysql = require('mysql');
var mysql_options = {
        host: db_host,
        user: db_user,
        password: db_pw,
        database: db_name
};
var my_client = mysql.createConnection(mysql_options);
my_client.connect();
 
var sql = 'select * from user where id=?';
 
var id = 1;
var e = my_client.query(sql, [id], function (err, rows, fields) {
        if (err) {
                console.log('can not connect');
                console.log(err);
                return;
        }
 
        console.log('-- 1 --');
        for (var i in rows) {
                console.log(rows[i].name);
        }
});
 
id = 2;
my_client.query(sql, [id], function (err, rows, fields) {
        if (err) {
                console.log('can not connect');
                console.log(err);
                return;
        }
 
        console.log('-- 2 --');
        for (var i in rows) {
                console.log(rows[i].name);
        }
});
my_client.end();

実行例

$ node sql_query1.js
-- 1 --
a
-- 2 --
b

SQLインジェクションっぽい値を入れる

このSQLの番号、というところに 0 or 1=1 を入れて、

SELECT * FROM USER WHERE id=番号

以下のSQL文を組みたてることができると

SELECT * FROM USER WHERE id=0 OR 1=1;

以下のような結果になります。

MariaDB [test]> SELECT * FROM USER WHERE id=0 OR 1=1;
+------+------+
| id   | name |
+------+------+
|    1 | a    |
|    2 | b    |
+------+------+
2 ROWS IN SET (0.00 sec)

たとえば、上のコードを id を以下のようにします。

var sql = 'select * from user where id=?';
var id = '0 or 1=1';
var e = my_client.query(sql, [id], function (err, rows, fields) {

実際に、query()が作成したSQLを確認してみると

sql: 'select * from user where id=\'0 or 1=1\,

となります。結果、テーブルのデータ的には、何もマッチしなくなります。

以下、query()の戻り値の抜粋です。

{ domain: null,
  _events:
   { error: [Function],
     packet: [Function],
     end: [Function],
     timeout: [Function],
     'start-tls': [Function] },
  _maxListeners: 10,
  _callback: [Function],
  _callSite: [Error],
  _ended: false,
  _timeout: undefined,
  _idleNext: null,
  _idlePrev: null,
  _idleStart: null,
  _idleTimeout: undefined,
  _repeat: null,
  sql: 'select * from user where id=\'0 or 1=1\'',

このように、疑問符プレースホルダを使用すると、自動的に値がエスケープされます。

関連項目




スポンサーリンク