UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

危険な危険なSQLインジェクション

エンジニアのspin13です。

今回はSQLインジェクションについてです。

SQLインジェクションとは

入力パラメータの検証不備等の原因で、予期せぬSQL文が発行されてしまう 予想していないパラメータが注入(inject)される

SQLインジェクションで何が起こるのか

  • データの窃盗
  • データの改変 SQL文で書けるようなことはなんでも起こり得る

<?php
if(!empty($_POST)){
    $db =  new PDO('mysql:dbname=test_db;host=localhost', 'user', 'password');
    $user = $_POST["user"];
    $pass = $_POST["pass"];
    echo "発行クエリ<br>";
    $query = "SELECT * FROM users WHERE name='{$user}' AND pass='{$pass}'";
    echo $query;
    echo "<br>";
    $result = $db -> query($query) -> fetchAll();
    echo "<br>";
    if($result){
        echo "成功";
    }else{
        echo "失敗";
    }
}
?>

上記はPOSTでユーザとパスワードを受け取ってDBに該当ユーザのレコードが存在するかどうかを確認するSQL文を発行します。

ユーザに user1
パスワードに password
と入力してsubmitしてみます。 出来上がるSQL文は、
SELECT * FROM users WHERE name='user1' AND pass='password' です。

[test_db]> select * from users;
+------+-------+-----------+
| id   | name  | pass      |
+------+-------+-----------+
|    1 | user1 | password  |
|    2 | user2 | changed   |
|    3 | user3 | password3 |
+------+-------+-----------+

このDBに対してSQLを実行します。

[test_db]> SELECT * FROM users WHERE name='user1' AND pass='password';
+------+-------+----------+
| id   | name  | pass     |
+------+-------+----------+
|    1 | user1 | password |
+------+-------+----------+
1 row in set (0.01 sec)

データが存在するのでログインに成功します。

[test_db]> SELECT * FROM users WHERE name='hoge' AND pass='fuga';
Empty set (0.00 sec)

存在しないユーザとパスワードの組み合わせではもちろんレコードが存在しないので失敗します。

次にSQLインジェクションで強制的にログインしてみます。

ユーザに user1 ' AND 1=1 -- '
パスワードに hoge
と入力してsubmitしてみます。 出来上がるSQL文は
SELECT * FROM users WHERE name='user1 ' AND 1=1 -- '' AND pass='hoge'

さてDBで叩いてみましょう。

[test_db]> SELECT * FROM users WHERE name='user1 ' AND 1=1 -- '' AND pass='hoge';
    -> ;
+------+-------+----------+
| id   | name  | pass     |
+------+-------+----------+
|    1 | user1 | password |
+------+-------+----------+

user1のレコードが返ってきてしまうんです!

なぜこのようなことが起きてしまうのでしょう。

解説

受け取ったパラメータをPHPのプログラム側で $query = "SELECT * FROM users WHERE name='{$user}' AND pass='{$pass}'";

として展開しています。

userに user1 ' AND 1=1 -- ' と入れると、
name = ' user1 ' AND 1=1 -- '
SQLでは -- 以降はコメントとして扱われるので、 AND pass='{$pass}'" が無視されてしまうのでパスワードに何が入っていても関係なくなってしまうんですね。

対策

プレースホルダを使いましょう

$state = $db-> prepare("SELECT * FROM users WHERE name=? AND pass=?");
$state-> execute(array($user, $pass));

このようにすればSQLの本体部分とパラメータ部で切り離されて、プレースホルダで与える部分は値としてしか解釈されないのでSQLインジェクションで不正なパラメータを注入するのが困難になります。

不正な値を受け取って実行できる状態でなくするのが大切です。 最近ではライブラリ側が自動でエスケープ処理等をしてくれるので意識することは少なくなっていますが、原理を知っておくときっと何か役に立ちます。

おまけ

user: aaaaaa' ;UPDATE users SET pass=‘’ – ‘ pass: aaaa

SELECT * FROM users WHERE name='aaaaaa' ;UPDATE users SET pass='' -- '' AND pass='aaa'
[test_db]> select * from users;
+------+-------+------+
| id   | name  | pass |
+------+-------+------+
|    1 | user1 |      |
|    2 | user2 |      |
|    3 | user3 |      |
+------+-------+------+
3 rows in set (0.00 sec)

▂▅▇█▓▒░(’ω’)░▒▓█▇▅▂

Datadog の導入がめっちゃ楽だった話

こんにちは、新人エンジニアのハトネコエです。
気付いたらプログラミングを始めて2年が経ちました。

みなさまはゴールデンウィークをいかがお過ごしでしたでしょうか?
私は人生初めてVPSを契約しました。

Ansible でサーバー構築のレシピを四苦八苦しながら作り、アプリケーションを動かせるまで至ると、
今度はサーバーの監視をしたくなってきます。

(↓なお、Ansibleについては以前、弊社のナカハシがこちらの記事で取り上げました)

サーバー監視のクラウドサービスと言えば Mackerel がおなじみです。
見やすいグラフが印象的で、弊社でも一部利用させていただいております。

Mackerel が便利なのは知っているので、
今回は異なるクラウドサービスを使おうと考えました。 Datadog です。

f:id:nekonenene:20170508180215p:plain

続きを読む

Railsアプリ開発中に思い出す、StrategyとRackミドルウェア

こんにちは、エンジニアのナカハシです。

最近は、しばらくRailsでのWebアプリ開発に勤しんでいる毎日です。

開発中にStrategyとRackミドルウェアを復習したので、軽くまとめてみました。

続きを読む

Rails5で手早くCMS開発をするのに便利なgem7選

エンジニアのタナカです。

4月から新しくサイト開発に携わる方も多いのではないでしょうか?
サイト開発では殆どの場合、CMS機能を用意する必要がありますが、このCMS機能をどう実現するのかというのが最初に検討することだと思います。

CMSといえばWordPressが有名ですが、WordPressも一長一短なので、 様々な理由によりCMSのスクラッチ開発を行う場合も多いと思います。
とはいえスクラッチ開発となると開発コスト等が問題になる場合もあります。 けれども、Railsを以ってすればWordPressと同等以上のCMSを効率よく開発する事も可能です。

ということで、Rails5でのCMS開発に役立つgemを紹介したいと思いますが、 その前にまずはCMSに必要な機能を定義してみます。
CMSと言っても様々なタイプがありますが、今回はニュース・メディア系のCMSを想定しています。

ニュース・メディア系CMSでよくある機能

  • ニュース(ブログ)記事投稿・編集
  • 固定ページ投稿・編集
  • Slug(カスタムURL)の設定
  • 画像投稿
  • タグ付け
  • 予約投稿
  • 履歴管理
  • ユーザー管理

これらの機能を意識しながら、使えそうなgemを紹介いきたいと思います。
これから紹介するgemはいずれも定番のものなので、ぜひ抑えておきたいところです。

ActsAsList

github.com

記事等の並び順を管理することができ、順番の入れ替えが簡単に行えるようになります。
元々Railsに組み込まれていた機能がgemとして切りだされたものですが、Rails5でももちろん使用可能です。

FriendlyId

github.com

たとえばIDが含まれるような以下のようなURLをフレンドリーなURLにしてくれるものです。

http://example.com/states/4323454

このような人間に理解しやすいURLに置き換えることができます。

http://example.com/states/washington

WordPressではslugという機能で提供されています。

Paperclip

github.com

フォームから画像ファイルをアップロードを行う際に便利なgemで、リサイズやサムネイル作成も行ってくれます。
アップロードされた画像をS3に書き出すことも可能なので、画像まわりの処理をこのgemに任せることができます。

ActsAsTaggableOn

github.com

記事などにタグ付けを行えるgemです。 タグの追加削除が簡単に行え、タグでの検索も可能です。

予約投稿

Rails5で利用できるgemは無さそうですが、記事のモデルにpublished_atカラムを追加し、公開日時をセットする方法がよくとられています。
同モデルに以下のようなscopeを定義することで公開済みのものを簡単に取得できるようになります。

scope :published, -> { where("published_at IS NOT NULL").where("published_at <= ?", Time.now) }
scope :draft, -> { where("published_at IS NULL OR published_at > ?", Time.now) }

PaperTrail

github.com

記事の履歴管理に利用できます。
記事を編集した際に、前の状態に戻すといった操作が行えるようになります。

devise

github.com

ユーザー登録やログイン認証といった機能を簡単に組み込むことができます。
アクセス権限を設定することが可能なので、adminユーザーの管理だけでなく、一般ユーザー向けにSNS的な機能を提供したい場合にも利用できます。

Storytime

github.com

これまでに上げたgemの機能を全て実現できるCMS機能が丸ごと入りのgemです。
これらの機能に加え、マルチサイトやナビゲーションの管理など、WordPressとほぼ同等の機能があり、管理画面も付いてきます。

CMSのgemはほかにもいくかリリースされていますが、Rails5対応で多機能なものはStorytime以外に無いと思います。
(固定ページの投稿、編集だけが必要であれば、ComfortableMexicanSofaもお勧めです。)

ただし残念なことに、最近はメンテナンスがあまりされていません。そのため、不具合があった場合は自分で対応することになる可能性が高いです。 (私は自分でメンテすることを前提に利用していますが、Storytimeのソースが読みやすいので問題が発生してもパッチの作成等で対応しています。)

まとめ

gemをうまく組み合わせることでCMSを効率よく開発することができます。(CMSに限った話ではないですが)
また、条件があえば、CMS全部入りのgemを利用することで、開発工数を大幅に削減することも可能です。
WordPressを独自プラグイン等で無理に拡張する前に、Railsでの開発を検討してみてはいかがでしょうか?

PHPなチームがRuby on Railsでの開発を行って得られたもの

3日連続 nazoです。

昨年から行っているチャレンジとして、Ruby on RailsによるWebサービスの開発があり、それが一段落しましたので、経緯と結果について報告させて頂きたいと思います。

続きを読む

CircleCIでRailsのDockerコンテナをECSにデプロイする

nazoです。

Graceful RestartによるRailsアプリのデプロイ を行っていたのですが、もっと手軽に環境ごとデプロイをしたいという需要もあって、Dockerを採用したデプロイも行っています。

CircleCI(1.0)では辛うじてDockerのサポートがありますが、いくつか癖があるので、ECSと含めて運用まで踏まえた手順について紹介したいと思います。

続きを読む

Docker?Vagrant?個人PCのWebアプリケーション開発環境においての環境分離方法

nazoです。

個人PC上では、複数の開発環境が同居することは珍しくありません。その際に、複数のバージョンの同一のソフトウェアが混在することもあります。 それらを切り替える度にアンインストール・インストールを繰り返すのは非効率なので、同居させつつ自動的に切り替わるような状況が最適かと思われます。

これを実現するには様々な方法がありますが、一長一短あるため、具体的にどう違うのか見ていきたいと思います。特にmacOSを中心とした話になります。

続きを読む