1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SQLインジェクションが話題になってるけど

Posted at

SQLインジェクションが話題になっている。多分あの話題はデマだとは思うが、それが何なのかの知識はあったほうが良いと思う

SQLインジェクションとは

まず、以下のようなテーブルが存在するとする。

CREATE TABLE `table` (
  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `content` VARCHAR(255) NOT NULL
) Engine=InnoDB;

次に、以下のようなコードを考える。

<?php
$conn = new mysqli('localhost', 'username', 'password');
$sql = "SELECT * FROM table WHERE content LIKE '%" . $_GET[
  'q'] . "%'";
$res = $conn->query($sql);
// 以下、$resを使って処理を行う

これを使うと何が起きるか説明すると、qパラメータにA%' OR '%' = 'と指定すると、全部の行が取得できてしまうのである。これがSQLインジェクションである。

では、どのような対策をすれば良いのだろうか。以下のようにすれば良い。

<?php
$conn = new mysqli('localhost', 'username', 'password');
$eq = $conn->real_escape_string('%' . preg_replace(
  '/([%_#])/', '#\\1', $_GET['q']) . '%');
$sql = "SELECT * FROM table WHERE content LIKE '" .
  $eq . "' ESCAPE '#'";
$res = $conn->query($sql);
// 以下、$resを使って処理を行う

やっているエスケープ処理は2つ。

  1. LIKE節のために文字列をエスケープし、%および_に意味を持たせないようにする。その際、 https://www.websec-room.com/2013/12/17/1339 にあるように、ESCAPEを明示的に指定することにより、他のSQLエンジンとの互換性を担保する。
  2. mysqli::real_escape_stringを呼び出して、SQLで意味のある文字列をエスケープして、SQLに組み込んだ時に無害になるようにする

一応、これで脆弱性を受けるリスクは大幅に減少するが、都度このような記述を考えるのは面倒である。なので、既存のライブラリを使って書くのが一番楽であるのは言うまでもない。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?