LoginSignup
30
24

More than 5 years have passed since last update.

バイナリセーフってなんだよ!?

Last updated at Posted at 2018-10-11

PHPの本を読んでいたらバイナリセーフって単語が出てきてバイナリセーフなんだよ!? っとなりました。
よくわからないので自分なりに調べてみました。

バイナリセーフな関数

バイナリデータを正しく扱うことができる関数

バイナリセーフでない関数

バイナリデータを正しく扱うことができない関数

そもそもバイナリデータとは?

コンピュータが扱えるよう2進法に則って0と1の羅列(ビット列)として表現されたデータうち、テキスト(文字)形式ではない任意のデータ形式のこと。
http://e-words.jp/w/%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA.html より引用

結局、気をつけることは何?

バイナリセーフでない関数を使用するとNULLバイト攻撃にあう

Nullバイト攻撃とは?

nullバイト(「\0」、「\x00」などの終端文字とされている文字列)を含めることでセキュリティチェックをくぐり抜けてしまう。
ロケールに基づく文字列比較の関数(strcoll、strcmp)を使用して確認してみる。
返り値はstr1 が str2 よりも小さければ < 0 を、str1が str2よりも大きければ > 0 を、 等しければ 0 を返します。 ※strcmpの公式リファレンスより

サンプルコード

<?php

// ロケールを日本語にする
// ※strcollはロケールが C または POSIX の場合、strcmpと等価なのでロケールの設定をする
setlocale (LC_COLLATE, 'ja_JP.UTF-8');

// 現在のロケールを表示する
echo setlocale(LC_ALL, 0) . PHP_EOL . PHP_EOL;

// 比較対象の文字列をセットする
$str1 = 'こんにちわ\x00ゴリラくん';
$str2 = 'こんにちわゴリラくん';

// strcoll ※バイナリセーフでない関数を使用
// 結果として、「2147483647」を返す(str1の方が大きいと判断している)
echo 'strcoll:' . strcoll($str1, $str2);

echo PHP_EOL;

// strcmp ※バイナリセーフな関数を使用
// 結果として、「-1」を返す(str2の方が大きいと判断している)
echo 'strcmp:' . strcmp($str1, $str2);

出力結果

LC_COLLATE=ja_JP.UTF-8;LC_CTYPE=Japanese_Japan.932;LC_MONETARY=C;LC_NUMERIC=C;LC_TIME=C

strcoll:2147483647
strcmp:-1

strcollの時は「\x00」が終末文字として認識されないため、str1が大きいと判断されるがstrcmpの時は「\x00」が終末文字として認識されるため、str2の方が大きいと判断される

気をつけないとNULLバイト攻撃された時にプログラムが意図しない挙動をしそうです。

上記コードはここにあります

参考サイト

30
24
1

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
30
24