https://twitter.com/flatt_security/status/1529416984785752065
方針 jsonの仕様でUnicode文字列が展開されるので、それを使ってフィルタリングを回避します。 次にphp://filter/convert.base64-encodeを使ってLocal File Inclusion(LFI)をします。
file_get_contents(“php://input”) 以下のphp://inputはリクエストのbodyから生のデータを読み込むことができ、 file_get_contents()はファイルの内容を文字列に読み込むます。
$query = file_get_contents("php://input"); フィルタリングの回避方法の検討 次の$filter_listでフィルタリングされている文字列は、 PHPのwrapperというものに含まれています。 このフィルタをjsonのUnicode文字列を使って回避します。
また、以下のようにstripos()が使われているので、 大文字で回避することもできません。
stripos — Find the position of the first occurrence of a case-insensitive substring in a string
foreach ($filter_list as $filter) { if(stripos($query, $filter) !== false) { exit("Filtered!"); } } LFIの検討 次のjson_decode($query, true)['fn']の部分は、 {"fn": "hoge"}のようなjson形式を求められています。 "hoge"の部分にphp://...というPHPのsupported protocol/wrapperを与えて、 LFIするというのが、この問題の解法です。
$output = file_get_contents(json_decode($query, true)['fn']); また、LFIで読み込んだファイルに<?phpという文字列があると終了してしまうので、 php://filter/convert.base64-encodeを使ってbase64でエンコードした文字列を出力します。
フィルタリングの回避とLFI Using php://filter for local file inclusionを参考にして次のようなURLを考えます。
php://filter/convert.base64-encode/resource=index.php このURLにはフィルタリングされている文字が含まれるので、それをUnicode文字列に置き換えます。...