2013-02-27 109 views
25

這個問題最初是在註釋here中提問的。什麼時候可以使用filter_input()

是否filter_input()在打印任何用戶提供的數據之前仍需要參數化查詢和htmlspecialchars()

對我來說似乎沒有必要,但我總是被告知「過濾輸入,轉義輸出」。因此,除了數據庫(或其他形式的存儲)之外,是否需要過濾輸入的數據?

+2

無論如何對於格式規範化。如果您已經對查詢和輸出進行上下文轉義,則防止XSS和SQL漏洞是多餘的。不傷害他們所屬的實際/經過驗證的電子郵件地址,網址或純文本。 – mario 2013-02-27 02:03:04

+0

@mario你能解釋一下「格式規範化」的含義嗎? – Jonathan 2013-02-27 19:10:32

回答

27

那麼,會有不同的意見。

我的意思是你應該總是使用它(或者一般的filter擴展名)。有至少3個原因:

  1. 消毒輸入是你應該始終做的事。由於該功能爲您提供了這種功能,因此實際上沒有理由找到其他消毒輸入方式。由於它是一個擴展,過濾器也將比大多數PHP解決方案更快更安全,這當然不會造成傷害。唯一的例外是如果您需要更專業的過濾器。即使這樣你也應該使用FILTER_UNSAFE_RAW過濾器來獲取數值(參見#3)。

  2. filter擴展中有很多好東西。它可以節省你編寫消毒和驗證代碼的時間。當然,它並沒有涵蓋每一個案例,但有足夠的東西可以讓你更專注於特定的過濾/驗證代碼。

  3. 使用該函數對於調試/審計代碼時非常有用。當使用函數時,您確切知道輸入是什麼。例如,如果您使用FILTER_SANITIZE_NUMBER_INT篩選器,那麼您可以確保輸入將是一個數字 - 不需要SQL注入,也不需要HTML或Javascript代碼等。另一方面,如果您使用類似FILTER_UNSAFE_RAW的東西,則您知道應該認真對待它,並且它很容易引起安全問題。

+0

雖然我希望在這個問題上有更多的意見(答案),但你的回答非常明確,而且很有意義。謝謝! – Jonathan 2013-03-04 15:43:21

+0

這不是特定的,它沒有例子。爲什麼它是好的,什麼會出問題?這是一個問題,這個答案不適合。 – 2018-01-16 23:23:05

23

正如Sverri M. Olsen所說,對此有不同看法。

我非常同意這個理念Filter Input,Escape Output

如果在打印任何用戶提供的數據之前使用參數化查詢和htmlspecialchars(),filter_input()仍然是必需的嗎?

簡短的回答: IMO,不,這是沒有必要的,但在某些情況下是有用的。


filter_input功能有許多有用的過濾器,和我使用它們中的一些(即FILTER_VALIDATE_EMAIL)。 validate filters對於驗證輸入有用。但是,國際海事組織,那些只能在輸出上使用的數據應該只用於轉換

有些人鼓勵逃避投入。事實上,filter_input手冊頁上給出的例子似乎也鼓勵這一點。

$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS); 
$search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED); 

唯一的例子是逃逸。結合函數的名稱(filter_ 輸入)似乎暗示轉義輸入是很好的做法。轉義是必要的,但IMO應該在輸出之前完成,而不是輸入。至少返回值被存儲在適當命名的變量中。

我強烈不同意轉義輸入。我已經遇到了現實世界的情況,即過早地轉換數據是一個問題。

例如,Google Analytics處理輸入的方式會導致在排除查詢參數之前解碼我的編碼符號(%26)。結果是我的查詢參數的統計信息實際上甚至不存在於我的URL中。有關此問題尚未解決,請參閱my question

您可能還想看看Why escape-on-input is a bad idea。以下是我同意的一些摘錄,以防文章消失[原文重點]。

[...]逃生的輸入是錯誤 [...]這是一個分層衝突 - 它混合輸出格式化關注到輸入處理。分層違規使您的代碼難以理解和維護,因爲您必須考慮其他層,而不是讓每個組件和層都完成自己的工作。

你已經默認損壞您的數據。該系統[...]現在躺在什麼數據已經進來了。

逃離輸入不但不能處理多個輸出的問題,它會實際上使您的數據對許多輸出不正確

PHP曾經有一個叫魔術引號功能。這是一個輸入逃生功能,導致各種問題。 [...]根據Lerdorf,更新的PHP'filter'擴展名是「magic_quotes done right」。但它仍然遭受這裏描述的幾乎所有問題的困擾。

因此,如何是過濾延伸比魔術引號(不是事實,它有許多不同的過濾器等)更好? 這些過濾器會導致許多與魔術引號相同的問題。


這裏是編碼約定我使用:在$ _ POST

  • 值,$ _GET,$ _REQUEST等不應逃脫,應始終被視爲不安全
  • 在寫入數據庫或存儲在$ _SESSION中之前,值應該被驗證
  • 預期爲數字或布爾值的值應該被消毒之前被寫入到數據庫或存儲在$ _SESSION
  • 信任,從數據庫中使用數字和布爾值和$ _SESSION確實是數字或布爾
  • 字符串值應該是SQL轉義被直接用於任何SQL查詢之前, (非字符串值應該被消毒),或使用準備的語句在HTML輸出被使用之前
  • 字符串值應HTML轉義(非字符串值應該被消毒)
  • 字符串值應在用於查詢字符串之前進行百分比編碼(非字符串值應當被消毒)
  • 使用一個變量命名約定(如* _url,* _html,* _SQL)來存儲變換的數據

術語

對於我的這裏的目的,這是我如何定義上面使用的術語。

  1. 驗證手段來確認任何假設正在作出關於具有值
  2. 數據,例如具有特定的格式或所需的字段來淨化裝置,以確認值是恰好如預期(即$ ID_NUM應僅僅包含數字)

摘要

一般(有一些例外),我會建議下列關於輸出

  • validate filters輸入
  • 使用sanitize filters

    • 使用記住TIMTOWDI - 例如,我更喜歡用htmlspecialchars()(其具有更多的選項)在FILTER_SANITIZE_FULL_SPECIAL_CHARS或FILTER_SANITIZE_SPECIAL_CHARS(從而避免了換行符)
  • +0

    我花了這麼多時間閱讀本文,並且只查找了一個非常具體的google api示例。謝謝你的回答,但問題是 - 「爲什麼」,這個答案沒有回答。 – 2018-01-16 23:21:04