system()
からの電話libc
は安全ではないと誰かが言っているのを耳にしました。
私が考えることができる理由の1つは、シェルユーティリティを起動することです。たとえば/bin/bash
、system("rm -rf $input")
が開始され、$ inputがサニタイズされていないユーザー入力である場合、$ input = "/"の場合、大混乱を引き起こす可能性があります。他の理由は何ですか?
ハードドライブを消去するために悪意のある入力のためにrmを呼び出す必要はありません。を実行するsystem("harmless_command $input")
と、$input
が; rm -rf /
実行harmless_command
され、その後に。が続きrm -rf /
ます。したがって、コマンドのユーザー入力を補間する必要があり、悪意のある入力が問題になる場合¹、システムを使用することはお勧めできません。
セキュリティ上の懸念に加えて、システムを使用するとバグが発生する可能性もあります。たとえば、system("some_command $filename")
そうして$ filenameにスペース(または他のシェルメタ文字)が含まれている場合、最初にファイル名を適切にエスケープしない限り、コマンドは爆発します。
exec *ファミリーの関数(シェルを通過する単一の文字列ではなく、コマンドの引数を含む配列または可変個引数の引数リストを取得する)を使用する場合、これらの問題は発生しません。
¹コードがユーザーのアクセス許可を持つユーザーのコンピューターで実行される場合、悪意のある入力は問題にならないだろうと主張することができます。ユーザーが悪意のある入力を入力してハードドライブが消去された場合、それは実際にはユーザー自身の責任です。ただし、コードがリモートサーバー上で実行されている場合、またはアクセス許可が強化されたローカルで実行されている場合は、別の問題になります。
一般に、「安全」とはexec
、システムコールのファミリー(execve()
最低レベルの標準コール)と比較した場合です。シェルを含むことは、サニタイズされていないデータの問題だけでなく、$PATH
(実行しているものを知っていますか?)および$IFS
(これは楽しいものです:誰かがあなたを変更できる場合$IFS
、シェルは期待どおりに物事を解析しません)の問題を意味します)。
これは、入力の健全性チェックの一般的なケースです。使用する文字列には、エスケープシーケンスなどを除外する汎用パーサーが必要です。たとえば、すべての適切なPHPアプリケーションは、SQLデータベースを呼び出す前にこれを実行します。
あなたが言及したこの最初のケースは非常に明白です:誰かがあなたのシステムを破壊する可能性があります。もう1つは、コード内の命令/関数を上書きする一連のバイナリコードを与えられ、プログラムにまったく異なることをさせることができる場合です(つまり、これが脱獄/ルート攻撃の仕組みです)。この特定の脅威の詳細については、バッファオーバーフローとコードインジェクションのエクスプロイトについて調べる必要があります:http: //en.wikipedia.org/wiki/Code_injection
また、ここにコードインジェクションを行う例があります: Cでのコードインジェクションの理解と実行
「誰か」が何を考えているかを知ることは不可能ですが、おそらくsystem()がシェルを介してコマンドを実行するため、最終的なコマンドの実行が計画とは異なる可能性があります。たとえば、PATH環境変数が何に設定されるか、およびその他の無数の変更可能なものがわかりません。
execのバリエーションに固執しますが、それでも、それらに渡すものには十分注意してください。