PHP バグ・脆弱性の温床10連発

公開日:

札幌市中央区札幌市民交流プラザで開催された『PHPカンファレンス北海道2019』でアンカンファレンス(20分)として発表しました。

Download PDF

スライドテキスト

Page 1

PHP

バグ・脆弱性の温床10連発

Kill your PHP code by hitting 10 combos

[2019-09-21]

PHPカンファレンス北海道2019

#phpcondo

Page 2

お前誰よ
うさみけんた (@tadsan)

/ Zonu.EXE

  • GitHub/Packagistでは id: zonuexe
    • ピクシブ株式会社 pixiv事業本部
  • Emacs Lisper, PHPer
  • Emacs PHP Modeのメンテナ引き継ぎました
    • 好きなリスプはEmacs Lispです
    • Qiitaに記事を書いたり変なコメントしてるよ

Page 3

Page 4

Page 5

Page 6

実家は近所

です!!!

Page 7

Page 8

前回のぺちこん

北海道2016が

カンファレンス

デビュー戦

Page 9

ついでにその前 は札幌市中央区
Ruby会議01

Page 10

さて

Page 11

PHPカンファレンス は楽しかったですか!

Page 12

ここで学んだことは
今後の仕事に活か

していきましょう

Page 13

本題

Page 14

Page 15

Page 16

ということで

クイックに

いきましょう

Page 17

10連発

Page 18

ただしタイトルの 「10連発」は任意 の進数表記とする

Page 19

クイック

PHP

バグ・脆弱性の温床10連発

Kill your PHP code by hitting 10 combos

[2019-07-31]

第140回 PHP勉強会@東京

#phpstudy

Page 20

例題1

<?

$id = $_REQUEST['id']; if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");
?>,

Page 21

short open

例題1

tagはphp.iniの設定依存なので、

基本は <?php または <?=

<?

$id = $_REQUEST['id']; if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");
?>,

Page 22

short open

例題1

tagはphp.iniの設定依存なので、

php.ini依存かつ、

基本は <?php または <?=

$_GETと$_POSTが混ざると不適切な取り扱

<?

いされる傾向がある

$id = $_REQUEST['id']; if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");
?>,

Page 23

short open

例題1

tagはphp.iniの設定依存なので、

php.ini依存かつ、

基本は <?php または <?=

$_GETと$_POSTが混ざると不適切な取り扱

<?

いされる傾向がある

$id = $_REQUEST['id']; if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");
?>,

何を期待するのか

不明瞭だがMySQLのAUTO_INCREMENT

なサロゲートキーなら不適切

Page 24

short open

例題1

tagはphp.iniの設定依存なので、

php.ini依存かつ、

基本は <?php または <?=

$_GETと$_POSTが混ざると不適切な取り扱

<?

いされる傾向がある

$id = $_REQUEST['id']; if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");
?>,

何を期待するのか

不明瞭だがMySQLのAUTO_INCREMENT

なサロゲートキーなら不適切

printfフォーマットに

変数埋め込みをしない (入力値に%が含まれる

とWarningが発生)

Page 25

short open

例題1

tagはphp.iniの設定依存なので、

php.ini依存かつ、

基本は <?php または <?=

$_GETと$_POSTが混ざると不適切な取り扱

<?

いされる傾向がある

$id = $_REQUEST['id']; if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");
?>,

何を期待するのか

不明瞭だがMySQLのAUTO_INCREMENT

なサロゲートキーなら不適切

printfフォーマットに

脆弱性ではないが変な文字が混

変数埋め込みをしない (入力値に%が含まれる

ざってるので ?> は消す

とWarningが発生)

Page 26

short open

例題1

tagはphp.iniの設定依存なので、

php.ini依存かつ、

基本は <?php または <?=

$_GETと$_POSTが混ざると不適切な取り扱

<?

いされる傾向がある

$id = $_REQUEST['id'];

脆弱性じゃないけど { は一文で

if (!is_numeric($id))

は正しい ではありません

printf("<p>{$id} ID </p>");

も几帳面に付ける方がオススメ

?>,

何を期待するのか

不明瞭だがMySQLのAUTO_INCREMENT

なサロゲートキーなら不適切

printfフォーマットに

脆弱性ではないが変な文字が混

変数埋め込みをしない (入力値に%が含まれる

ざってるので ?> は消す

とWarningが発生)

Page 27

改善案は各自へ の宿題とします

Page 28

例題2

const VALIDATE_PATTERN = "/
^ # begin
([a-zA-Z0-9])+([a-zA-Z0-9\._-])* # localpart
@ # at mark
([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+ # host $ # end
/x";

$email = filter_input(INPUT_GET, 'email');
if (!preg_match(VALIDATE_PATTERN, $email)) {
echo "Bad mail address!!";
}
register_account(strtolower($email), $password);

Page 29

PCRE正規表現は /x 修飾子を付ける

例題2

と空白が無視されるので、これはGood

const VALIDATE_PATTERN = "/
^ # begin
([a-zA-Z0-9])+([a-zA-Z0-9\._-])* # localpart
@ # at mark
([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+ # host $ # end
/x";

$email = filter_input(INPUT_GET, 'email');
if (!preg_match(VALIDATE_PATTERN, $email)) {
echo "Bad mail address!!";
}
register_account(strtolower($email), $password);

Page 30

PCRE正規表現は /x 修飾子を付ける

例題2

と空白が無視されるので、これはGood

だが、バリデーション(妥当性検証)の

const VALIDATE_PATTERN = "/

ために正規表現で判定するのはだめ!!!

^ # begin
([a-zA-Z0-9])+([a-zA-Z0-9\._-])* # localpart
@ # at mark
([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+ # host $ # end
/x";

$email = filter_input(INPUT_GET, 'email');
if (!preg_match(VALIDATE_PATTERN, $email)) {
echo "Bad mail address!!";
}
register_account(strtolower($email), $password);

Page 31

PCRE正規表現は /x 修飾子を付ける

例題2

と空白が無視されるので、これはGood

だが、バリデーション(妥当性検証)の

const VALIDATE_PATTERN = "/

ために正規表現で判定するのはだめ!!!

^ # begin
([a-zA-Z0-9])+([a-zA-Z0-9\._-])* # localpart
@ # at mark

FILTER_VALIDATE_EMAILという

([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+ # host $ # end

フラグを使えば取得と同時に検証できる

/x";

$email = filter_input(INPUT_GET, 'email');
if (!preg_match(VALIDATE_PATTERN, $email)) {
echo "Bad mail address!!";
}
register_account(strtolower($email), $password);

Page 32

PCRE正規表現は /x 修飾子を付ける

例題2

と空白が無視されるので、これはGood

だが、バリデーション(妥当性検証)の

const VALIDATE_PATTERN = "/

ために正規表現で判定するのはだめ!!!

^ # begin
([a-zA-Z0-9])+([a-zA-Z0-9\._-])* # localpart
@ # at mark

FILTER_VALIDATE_EMAILという

([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+ # host

Bad って表示してるだけで、処理は

$ # end

フラグを使えば取得と同時に検証できる

/x";

停止できてない!!!!

$email = filter_input(INPUT_GET, 'email');
if (!preg_match(VALIDATE_PATTERN, $email)) {
echo "Bad mail address!!";
}
register_account(strtolower($email), $password);

Page 33

PCRE正規表現は /x 修飾子を付ける

例題2

と空白が無視されるので、これはGood

だが、バリデーション(妥当性検証)の

const VALIDATE_PATTERN = "/

ために正規表現で判定するのはだめ!!!

^ # begin
([a-zA-Z0-9])+([a-zA-Z0-9\._-])* # localpart
@ # at mark

FILTER_VALIDATE_EMAILという

([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+ # host

Bad って表示してるだけで、処理は

$ # end

フラグを使えば取得と同時に検証できる

/x";

停止できてない!!!!

$email = filter_input(INPUT_GET, 'email');
if (!preg_match(VALIDATE_PATTERN, $email)) {
echo "Bad mail address!!";

正規化

}

は検討が必要(本来ローカルパートは大文

register_account(strtolower($email), $password);

字小文字区別するが、実際はサービスの実

装依存)

Page 34

例題2++
これならどうだ!

//
$email = filter_input(INPUT_GET, 'email',
FILTER_VALIDATE_EMAIL);
if ($email !== false) {
echo "Bad mail address!!";
exit;
}

[$local, $host] = explode('@', $email);
$normalized = $local . '@' . strtolower($host);

register_account($email, $password);

Page 35

例題2++
これならどうだ!

//
$email = filter_input(INPUT_GET, 'email',
FILTER_VALIDATE_EMAIL);
if ($email !== false) {

これでも

echo "Bad mail address!!";
exit;

良くないことがあるので続きは懇親

}

会で!!!!!!!!

[$local, $host] = explode('@', $email);
$normalized = $local . '@' . strtolower($host);

register_account($email, $password);