私はここで激しく反対投票されたコメントに気づきました: http://php.net/manual/en/function.php-check-syntax.php
_function eval_syntax($code)
{
$braces = 0;
$inString = 0;
// We need to know if braces are correctly balanced.
// This is not trivial due to variable interpolation
// which occurs in heredoc, backticked and double quoted strings
foreach (token_get_all('<?php ' . $code) as $token)
{
if (is_array($token))
{
switch ($token[0])
{
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case T_START_HEREDOC: ++$inString; break;
case T_END_HEREDOC: --$inString; break;
}
}
else if ($inString & 1)
{
switch ($token)
{
case '`':
case '"': --$inString; break;
}
}
else
{
switch ($token)
{
case '`':
case '"': ++$inString; break;
case '{': ++$braces; break;
case '}':
if ($inString) --$inString;
else
{
--$braces;
if ($braces < 0) return false;
}
break;
}
}
}
// If $braces is not zero, then we are sure that $code is broken.
// We run it anyway in order to catch the error message and line number.
// Else, if $braces are correctly balanced, then we can safely put
// $code in a dead code sandbox to prevent its execution.
// Note that without this sandbox, a function or class declaration inside
// $code could throw a "Cannot redeclare" fatal error.
echo "Braces: ".$braces."\r\n";
$braces || $code = "if(0){{$code}\n}";
if (false === eval($code)) {}
}
eval_syntax("file_put_contents('/home/yourname/Desktop/done.txt', 'OVERWRITTEN');");
_
コードをバイパスしてeval
を使用した悪意のあるユーザー入力の実行を引き起こそうとしましたが、できませんでした。なぜ反対票が投じられたのかしら。
中括弧が一致していないかどうかを確認できるように、'if(0){' . $code . '}
を追加せず、中括弧が一致しない状態でユーザー入力をそのまま実行し、例外をスローして実際には実行されません。
中括弧が一致する場合はeval
を呼び出しますが、その内部は_if {0}
_ "sandbox"であるため、何も実行しません。どうすればこれをバイパスできますか?
私はevalが安全でないことを知っていますが、ここでトリックが何であるか知りたいです。上記のコードでif(0)と中括弧のチェックのセキュリティをバイパスするにはどうすればよいですか
// {を追加しようとしたので、中括弧が不均衡になり、if(0)が追加されてevalが呼び出されなくなりますが、token_get_allはそれを台無しにします。
あなたが投稿したコードからのこのコメントは私の考えを要約していると思います:
// We need to know if braces are correctly balanced. // This is not trivial due to variable interpolation // which occurs in heredoc, backticked and double quoted strings
コードチェックを不適切に実行すると、リモートでコードが実行される脆弱性があることに注意してください。重要な項目での作業はもちろんエンジニアにとって標準ですが、非常に困難なタスクで作業している場合and間違いは最も深刻な種類のセキュリティの脆弱性につながります-まあ、明らかに災害のレシピです。実際、あなたが投稿したコメントが著者のこれに対する2回目の試みであったことを指摘する価値があります。彼の最初の試みには、(おそらく)「サンドボックスのエスケープ」に対して脆弱であり、最初からやり直すことを要求した少なくとも1つの間違いが含まれていました。確かに、アプリケーションのセキュリティを、Web上のランダムなページのコメントボックスに書かれた1回限りのスクリプトに信頼するつもりはありません。特に(私が何かを見落としているのでない限り)このコメントは、まったく同じことをする組み込み言語を説明するページに偶然あります。私はインターネット上のランダムな男の前に組み込まれた言語を信頼します。
誰もがエクスプロイトを見つけたかどうかに関係なく、そもそもこれが一般的に悪い考えであるという事実は変わりません。著者が考えていない他のエスケープオプションがある場合はどうなりますか?たとえば、さまざまなエクスプロイトがさまざまなエンコーディングの混乱に依存しています。攻撃者がファイル内のエンコーディングとは異なるエンコーディングを使用してブレースを挿入する可能性がありますが、PHPによってサポートされているため、チェックではブレースとして登録されませんが、PHPによってブレースとして認識され、攻撃者がブレースバランスチェックを突破します。確かに、その特定の攻撃手段は実際にはは可能ではないかもしれませんが、私は主に一般的なポイントを強調しようとしています。このような状況では、捕捉が困難な「問題」が多数発生する可能性があり、このコードでそれらの1つが欠落している結果、リモートコード実行の脆弱性が生じます。
「完璧に仕上げるか、非常に脆弱になるか」に直面したとき、私の最初の好みは「ただやらない」です。その後、特に「インターネット上のランダムなコメントを信用しないでください」という強力なメッセージが続きます。特に、同じことを(ただし)安全に実行できる、簡単にアクセスできる言語が組み込まれている場合は特にそうです。
追加して編集。 eval
についてコメントする価値があります。あなたは「私はevalが安全でないことを知っています」と言いました...これは厳密には真実ではありません。 eval
の使用は、いくつかの理由で一般に嫌われています:
ただし、他のツールと同様に、時間と場所を設定できます。つまり、問題を明確にすることは、eval
が安全でないということではありません。問題は、ここでeval
が安全に(かつ適切に)使用されているかどうかです。上記で概説したすべての理由から、ここでは適切に使用されているとは思いませんが、それは包括的な「評価は安全ではない」という記述とは異なります。