已 經知道了不能信任使用者輸入,還應該知道不應該信任機器上配置 PHP 的方式。例如,要確保禁用 register_globals。如果啟用了 register_globals,就可能做一些粗心的事情,比如使用 $variable 替換同名的 GET 或 POST 字串。通過禁用這個設定,PHP 強迫您在正確的名稱空間中引用正確的變數。要使用來自表單 POST 的變數,應該引用 $_POST['variable']。這樣就不會將這個特定變數誤會成 cookie、會話或 GET 變數。
$sql = "select count(*) as ctr from users where username='".mysql_real_escape_string($username)."' and password='". mysql_real_escape_string($pw)."' limit 1";
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header("index.php");
}else{
header("login.php");
}
?>
//we create an object of a fictional class Page
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
?>
if (is_numeric($pid)){
//we create an object of a fictional class Page
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
}else{
//didn't pass the is_numeric() test, do something else!
}
?>
那 麼,有安全意識的 PHP 開發人員應該怎麼做呢?多年的經驗表明,最好的做法是使用Regex來確保整個 GET 變數由數字組成,如下所示:
清 單 10. 使用Regex限制 GET 變數
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg("^[0-9] $",$pid)){
//do something appropriate, like maybe logging them out or sending them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we create an object of a fictional class Page, which is now
//moderately protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
?>
class Page{
function fetchPage($pid){
$sql = "select pid,title,desc,kw,content,status from page where pid='".mysql_real_escape_string($pid)."'";
}
}
?>
if (strlen($pid)){
if (!ereg("^[0-9] $",$pid) && strlen($pid) > 5){
//do something appropriate, like maybe logging them out or sending them back to home page
}
} else {
//empty $pid, so send them back to the home page
}
//we create an object of a fictional class Page, which is now
//even more protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
?>
現 在,任何人都無法在資料庫應用程式中塞進一個 5,000 位的數值 ?? 至少在涉及 GET 字串的地方不會有這種情況。想像一下駭客在試圖突破您的應用程式而遭到挫折時咬牙切齒的樣子吧!而且因為關閉了錯誤報表,駭客更難進行偵察。
正如您看到的,這種方式與前一節中使用 strlen() 檢查 GET 變數 pid 的長度相似。在這個樣本中,忽略長度超過 5 位的任何輸入值,但是也可以很容易地將值截短到適當的長度,如下所示:
清單 14. 改變輸入的 GET 變數的長度
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg("^[0-9] $",$pid)){
//if non numeric $pid, send them back to home page
}
}else{
//empty $pid, so send them back to the home page
}
//we have a numeric pid, but it may be too long, so let's check
if (strlen($pid)>5){
$pid = substr($pid,0,5);
}
//we create an object of a fictional class Page, which is now
//even more protected from evil user input
$obj = new Page;
$content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page
?>