Gigagineで比較的珍しいバグが見つかったことを記事にしています。
「%p%s%s%s%s%n」というSSIDのネットワークに接続すると、iPhoneのすべてのWi-Fi関連機能が無効になってしまう
https://gigazine.net/news/20210620-specific-network-name-disable-wi-fi-iphone/
「セキュリティって難しいんだな」と感じるニュースではなく「大手でも基本が出来てないんだな」と思えれば、似たような問題で困ることが無くなります。
問題の原因
問題の原因は引用記事の予想通りだと思います。フォーマット文字列を使ったデータ出力関数の出力処理が問題のはずです。
上記のようなフォーマット文字列を使ったAPIを使用する箇所で「エスケープ無し文字列」、記事の問題の場合はSSID、がフォーマット文字列に使われてしまい、処理がおかしくなってしまった事が原因でしょう。
対策はエスケープです。%を特殊文字とするprintf系のフォーマット文字列のエスケープは一般に%で行えます。例: %を出力する為には%%を利用する
こういった問題を作らない考え方
「printf系APIのフォーマット文字列にリテラル以外の文字列を使う場合は%のエスケープ処理を行う」と覚えるのは無駄です。考え方がブラックリスト型(ダメなモノを定義する考え方)で穴だらけになるからです。「printf系APIには%が入っているとダメなので無害化する」と覚えてしまうと、printf系APIにしか利用できないノウハウになってしまうからです。
効率良い考え方は「一文字でも出力先が意味がある文字として取り扱う文字がある場合、出力対策の3原則を適用する」です。
「(エスケープは忘れられることが多いのでエスケープ以外のAPIを利用した無害化やバリデーションを行い)エスケープは無い方が良い」といった考え方は間違いではないのですが、()の部分が忘れられた「エスケープは無いほうが良い」と単純化してしまうと間違いです。エスケープ(=無害化)は必須の出力対策であると覚えておかないと、紹介したiOSのようなバグを作ってしまう原因になります。
セキュアコーディング原則では「”全て”の出力を無害化する」としています。APIへの出力、printf系APIへの出力や正規表現APIへの出力など、も「”全て”の出力」の一つです。
おまけ
ソースコード検査をしているとよく見つかるエスケープ漏れの一つが SQLのLIKEクエリーの % エスケープ です。
大抵の場合、LIKEクエリーの実行結果がおかしくなるだけで済みますが稀に正規表現インジェクションと同じく不正なデータ取得を可能にする問題になります。
「プログラムのデータに一文字でも間違いがあると正しく動作しない」と意識していると、どんなデータ問題にも対応できる考え方になります。
Leave a Comment