Difference between revisions of "Secure coding guidelines/zh-tw"
From Joomla! Documentation
(Created page with "{| class="wikitable" border="1" | INT, INTEGER || 相當於 JInput->getInt. |- | UINT || Get an unsigned integer. Equiv...") |
(Created page with "// 將上傳的檔案移動到常駐位置 if (isset( $file['name'] )) {") |
||
(35 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
Joomla 包含了很多特色,可以協助在其上開發應用和擴充套件時的安全性。您應該要盡可能地一直使用這些特色功能,因為它們是已經被開發社群嘗試過、檢查過;而且可能還會在未來需要被更新。以下是關於使用 Joomla API最佳實踐的描述,確保您的擴充套件是盡可能安全的。 | Joomla 包含了很多特色,可以協助在其上開發應用和擴充套件時的安全性。您應該要盡可能地一直使用這些特色功能,因為它們是已經被開發社群嘗試過、檢查過;而且可能還會在未來需要被更新。以下是關於使用 Joomla API最佳實踐的描述,確保您的擴充套件是盡可能安全的。 | ||
− | == | + | ==使用 request 來獲取資料== |
{{JVer|3.x}} 從Joomla 3.0 版本開始, 應該停止使用[https://api.joomla.org/cms-3/classes/JRequest.html JRequest],改成使用[[Retrieving_request_data_using_JInput|JInput]] | {{JVer|3.x}} 從Joomla 3.0 版本開始, 應該停止使用[https://api.joomla.org/cms-3/classes/JRequest.html JRequest],改成使用[[Retrieving_request_data_using_JInput|JInput]] | ||
− | 所有來自使用者發起的輸入都必須要被視為具有潛在危險的,並且必須要在使用前先做過清理。您應該總是使用 Joomla [[Retrieving_request_data_using_JInput|JInput]] class 來從請求擷取資料,而不是赤裸裸的 $_GET, $_POST 或是 $_REQUEST | + | 所有來自使用者發起的輸入都必須要被視為具有潛在危險的,並且必須要在使用前先做過清理。您應該總是使用 Joomla [[Retrieving_request_data_using_JInput|JInput]] class 來從請求擷取資料,而不是赤裸裸的 <code>$_GET</code>, <code>$_POST</code> 或是 <code>$_REQUEST</code> 變項,因為 <code> JInput </code> method 預設會過濾用戶的輸入。<code> JInput </code> 會處理所有方面的用戶請求,讓它獨立於使用的 request method。<code> JInput </code> 也可以用於獲取 cookie資料,甚至是伺服器和環境變數。然而,非常重要的是,使用正確的[[Retrieving_request_data_using_JInput|JInput]] method,來確保最大的安全性。使用<code> [[Retrieving_request_data_using_JInput#Getting_Values|JInput->get]] </code> method ,輔以預設參數是十分容易的,儘管在很多案例中,還可以對使用者的輸入套用更加嚴格的規範。 |
− | + | 非常重要的是,要了解 <code> [[Retrieving_request_data_using_JInput|JInput]] </code>方法並非 SQL-aware,而且需要額外作業來防範 SQL Injection。如果沒有在呼叫 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->get]] 當中指定預設,並沒有預設的值會被取回。假如沒有指定預設的話,而且沒有在請求變數當中顯示 argument,就會取回未定義(undefined)。 | |
− | 使用 [[Retrieving_request_data_using_JInput|JInput]] 也可以消除您需要留意 magic_quotes_gpc | + | 使用 [[Retrieving_request_data_using_JInput|JInput]] 也可以消除您需要留意 <code>magic_quotes_gpc </code> 設定的麻煩。無論您的 <code>magic_quotes_gpc </code> 有沒有打開,[[Retrieving_request_data_using_JInput|JInput]] 都恪盡職守。請查閱[http://php.net/manual/en/security.magicquotes.php security.magicquotes.php] 以獲得更多資訊。 |
− | 考慮到用戶的輸入內容,您需要思考關於您要獲取的資料類型,並套用最嚴謹的[[Retrieving_request_data_using_JInput#Getting_Values|JInput]] | + | 考慮到用戶的輸入內容,您需要思考關於您要獲取的資料類型,並套用最嚴謹的 [[Retrieving_request_data_using_JInput#Getting_Values|JInput]] 類型,依照每個不同的案例來應用。特定地說,避免使用像是[[Retrieving_request_data_using_JInput#Getting_Values|JInput->get]] 的懶惰蟲手段,因為它會取回陣列,當中可能包含您不想要顯示的。儘管這些內容會被清理,它們經常在某些個別 argument 中,被額外的過濾器找到。例如,get 方法會把所有的 arguments 當成字串(string) 來處理,然而它們是可以被限制為整數之類的。 |
− | JInput | + | JInput 方法中頭三個參數 (parameter) 是相同的,只有頭一項 parameter 是強制的。一般而言,格式是 |
<source lang="php"> | <source lang="php"> | ||
JFactory::getApplication->input-><data-source>->get<type>( <name>, <default> ) | JFactory::getApplication->input-><data-source>->get<type>( <name>, <default> ) | ||
Line 21: | Line 21: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
− | | <type> || | + | | <type> || 可以獲取的資料類型 (在底下查可以使用的類型)。 |
|- | |- | ||
− | | <name> || | + | | <name> || 要獲取的變數(variable)的名稱(name) (例如,在 URL 當中 argument 的名稱name). |
|- | |- | ||
− | | <default> || | + | | <default> || 預設的值 |
|- | |- | ||
− | | <data-source> || | + | | <data-source> || 指定變數要從何處來獲取 (見底下). |
|} | |} | ||
− | + | 底下的 <data-source> 值是支援的: | |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
− | | get || | + | | get || 由 URL 中 query 的部分送出的資料 |
|- | |- | ||
− | | post || | + | | post || 從欄位 (field) 送出的資料。 |
|- | |- | ||
| method || The same as either GET or POST depending on how the request was made. | | method || The same as either GET or POST depending on how the request was made. | ||
|- | |- | ||
− | | cookie || | + | | cookie || 在 cookies 中送出的資料。 |
|- | |- | ||
− | | request || | + | | request || 所有的 GET, POST 以及 COOKIE 合併資料。這是預設的。 |
|- | |- | ||
− | | files || | + | | files || 關於 POST request 檔案上傳的資訊 |
|- | |- | ||
− | | env || | + | | env || 環境變數 (platform-specific) |
|- | |- | ||
− | | server || | + | | server || 網站伺服器變數 (platform-specific) |
|} | |} | ||
− | + | 請注意預設會使用 REQUEST,其中包含了 cookie 資料。 | |
以下的段落深入解釋每種資料類型。 | 以下的段落深入解釋每種資料類型。 | ||
===整數=== | ===整數=== | ||
− | + | 以下會接受整數。整數型可以包含一個前導的負號(<code> - </code>),但正號(<code> + </code>)是不允許的。 | |
<source lang="php"> | <source lang="php"> | ||
$integer = JFactory::getApplication->input->getInt( 'id' ); | $integer = JFactory::getApplication->input->getInt( 'id' ); | ||
</source> | </source> | ||
− | + | 會從 request 回傳 value of the "id" argument from the request (which by default includes all GET, POST and COOKIE data). The default value is zero. | |
<source lang="php"> | <source lang="php"> | ||
$integer = JFactory::getApplication->input->cookie->getInt( 'myId', 12 ); | $integer = JFactory::getApplication->input->cookie->getInt( 'myId', 12 ); | ||
</source> | </source> | ||
− | + | 會從 cookie 回傳 value of the "myId" variable, with a default value of 12. | |
===浮點數=== | ===浮點數=== | ||
− | + | 浮點數型可以包含一個前導的負號(<code> - </code>),但正號(<code> + </code>)是不允許的。如果數字包含了千分位號,那千分位號前頭必須要至少有一個數字。例如, | |
<source lang="php"> | <source lang="php"> | ||
$float = JFactory::getApplication->input->getFloat( 'price' ); | $float = JFactory::getApplication->input->getFloat( 'price' ); | ||
</source> | </source> | ||
− | + | 會回傳 the value of the 'price' argument from the request. 預設的值是 "0.0" | |
<source lang="php"> | <source lang="php"> | ||
$float = JFactory::getApplication->input->post->getFloat( 'total', 100.00 ); | $float = JFactory::getApplication->input->post->getFloat( 'total', 100.00 ); | ||
</source> | </source> | ||
− | + | 會從 POST (而非 GET) 請求回傳 'total' 值。預設的值是 100.00 | |
===布林值=== | ===布林值=== | ||
− | + | 所有「非零」的值都會被視為 'true'。zero 是 'false' | |
<source lang="php"> | <source lang="php"> | ||
$boolean = JFactory::getApplication->input->getBool( 'show' ); | $boolean = JFactory::getApplication->input->getBool( 'show' ); | ||
</source> | </source> | ||
− | + | 會回傳 false if the value of the 'show' argument in the request is zero, or 1 (true) if the argument is anything else. 預設的值是 false. Note that any string argument will result in a return value of true, so calling the above with a URL containing "?show=false" 事實上會回傳 true! | |
<source lang="php"> | <source lang="php"> | ||
$boolean = JFactory::getApplication->input->get->getBool( 'hide', true ); | $boolean = JFactory::getApplication->input->get->getBool( 'hide', true ); | ||
</source> | </source> | ||
− | + | 會獲取 the value of the 'hide' argument from a GET request (but not a POST)。預設的值是 true. | |
===Word=== | ===Word=== | ||
− | + | Word 的定義是指使用A到Z組成的字段。在 word 中使用部分小寫的字母是允許的。 | |
<source lang="php"> | <source lang="php"> | ||
$word = JFactory::getApplication->input->cookie->getWord( 'search-word' ); | $word = JFactory::getApplication->input->cookie->getWord( 'search-word' ); | ||
</source> | </source> | ||
− | + | 會獲取由request送出的 'search-word' 的值。預設是空白字串。 | |
<source lang="php"> | <source lang="php"> | ||
$word = JFactory::getApplication->input->cookie->getWord( 'keyword', '' ); | $word = JFactory::getApplication->input->cookie->getWord( 'keyword', '' ); | ||
</source> | </source> | ||
− | + | 會獲取 cookie 中 'keyword' 變數的值。預設是空白字串。 | |
===指令(Command)=== | ===指令(Command)=== | ||
− | + | 指令(Command) 類似 word 但是允許的字元是更廣泛的。允許的字元包含:all alphanumeric characters, dot, dash (hyphen) and underscore. | |
<source lang="php"> | <source lang="php"> | ||
$command = JFactory::getApplication->input->getCmd( 'option' ); | $command = JFactory::getApplication->input->getCmd( 'option' ); | ||
</source> | </source> | ||
− | + | 會獲取由 request 請求回傳的 "option" 值。預設值是空字串。 | |
<source lang="php"> | <source lang="php"> | ||
$command = JFactory::getApplication->input->post->getCmd( 'controller', 'view' ); | $command = JFactory::getApplication->input->post->getCmd( 'controller', 'view' ); | ||
</source> | </source> | ||
− | + | 會獲取由 POST 請求(而非 GET) "controller" 參數的值。預設值是 'view' | |
===字串=== | ===字串=== | ||
− | + | 字串型允許更廣泛的字元輸入 It also takes an optional fourth argument specifying some additional mask options. 請查看 [[#Filter options]] for information on the available masks. | |
<source lang="php"> | <source lang="php"> | ||
$string = JFactory::getApplication->input->getString( 'description' ); | $string = JFactory::getApplication->input->getString( 'description' ); | ||
</source> | </source> | ||
− | + | 會獲取從 request 回傳 "description" 參數的值。預設的值是空字串。輸入的值會清除前後的空白,以及 HTML 標籤。 | |
<source lang="php"> | <source lang="php"> | ||
$string = JFactory::getApplication->input->getString( 'text', '' ); | $string = JFactory::getApplication->input->getString( 'text', '' ); | ||
</source> | </source> | ||
− | + | 會獲取從 request 回傳 "text" 參數的值。預設的值是空字串。 | |
<source lang="php"> | <source lang="php"> | ||
$string = JFactory::getApplication->input->getString( 'template', '<html />' ); | $string = JFactory::getApplication->input->getString( 'template', '<html />' ); | ||
</source> | </source> | ||
− | + | 會從 request 回傳"佈景主題"參數的值。預設的值是 '<html />'. | |
===JSON 字串=== | ===JSON 字串=== | ||
Line 151: | Line 151: | ||
| INT, INTEGER || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getInt]]. | | INT, INTEGER || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getInt]]. | ||
|- | |- | ||
− | | UINT || Get an unsigned integer. | + | | UINT || Get an unsigned integer. 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getUint]]. |
|- | |- | ||
| FLOAT, DOUBLE || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getFloat]]. | | FLOAT, DOUBLE || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getFloat]]. | ||
Line 159: | Line 159: | ||
| WORD || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getWord]]. | | WORD || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getWord]]. | ||
|- | |- | ||
− | | ALNUM || | + | | ALNUM || 僅允許 alphanumeric characters (a-z, A-Z, 0-9). 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getAlnum]]. |
|- | |- | ||
| CMD || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getCmd]]. | | CMD || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getCmd]]. | ||
|- | |- | ||
− | | BASE64 || | + | | BASE64 || 僅允許 those characters that could be present in a base64-encoded string (ie. a-z, A-Z, 0-9, /, + and =). 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getBase64]]. |
|- | |- | ||
| STRING || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getString]]. | | STRING || 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getString]]. | ||
Line 169: | Line 169: | ||
| ARRAY || Source is not filtered but is cast to array type. When using this type you should use JFilterInput directly to filter the values in your data array. | | ARRAY || Source is not filtered but is cast to array type. When using this type you should use JFilterInput directly to filter the values in your data array. | ||
|- | |- | ||
− | | HTML || A sanitised string. | + | | HTML || A sanitised string. 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getHtml]]. |
|- | |- | ||
− | | PATH || Valid pathname regex that filters out common attacks. For example, any path beginning with a "/" will return an empty string. Simliarly, any path containing "/./" or "/../" will return an empty string. Dots within filenames are okay though. | + | | PATH || Valid pathname regex that filters out common attacks. For example, any path beginning with a "/" will return an empty string. Simliarly, any path containing "/./" or "/../" will return an empty string. Dots within filenames are okay though. 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getPath]]. |
|- | |- | ||
− | | USERNAME || | + | | USERNAME || 移除 control characters (0x00 - 0x1F), 0x7F, <, >, ", ', % and &. 相當於 [[Retrieving_request_data_using_JInput#Getting_Values|JInput->getUsername]]. |
|} | |} | ||
− | === | + | ===過濾選項=== |
− | + | 所有的輸入值都應該要用 JFilterInput->clean 來過濾 | |
− | + | 過濾值矩陣 | |
<source lang="php"> | <source lang="php"> | ||
$data = JFactory::getApplication()->input->post->get('data', array(), 'array'); | $data = JFactory::getApplication()->input->post->get('data', array(), 'array'); | ||
Line 189: | Line 189: | ||
} | } | ||
</source> | </source> | ||
− | + | 要看更多的過濾類型,請看 [https://github.com/joomla/joomla-cms/blob/master/libraries/joomla/filter/input.php#L115 JFilterInput source]. | |
− | + | 底下列出的選項是過時的 [[JRequest]] library. | |
− | + | 允許的 <options> 值羅列如下 (預設並不會套用任何一項): | |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
− | | JREQUEST_NOTRIM || | + | | JREQUEST_NOTRIM || 並不會移除字串前後的空白 |
|- | |- | ||
− | | JREQUEST_ALLOWRAW || | + | | JREQUEST_ALLOWRAW || 不會套用任何的過濾條件,請絕對謹慎使用! |
|- | |- | ||
− | | JREQUEST_ALLOWHTML || | + | | JREQUEST_ALLOWHTML || 不會移除字串中的 HTML |
|} | |} | ||
Line 217: | Line 217: | ||
defined('_JEXEC') or die( 'Restricted access' ); | defined('_JEXEC') or die( 'Restricted access' ); | ||
− | // | + | // 從 request 獲得檔案資料矩陣 |
$file = JFactory::getApplication->input->get( 'Filedata', '', 'files', 'array' ); | $file = JFactory::getApplication->input->get( 'Filedata', '', 'files', 'array' ); | ||
− | // | + | // 讓檔案名稱安全無害 |
jimport('joomla.filesystem.file'); | jimport('joomla.filesystem.file'); | ||
$file['name'] = JFile::makeSafe($file['name']); | $file['name'] = JFile::makeSafe($file['name']); | ||
− | // | + | // 將上傳的檔案移動到常駐位置 |
if (isset( $file['name'] )) { | if (isset( $file['name'] )) { | ||
Latest revision as of 20:46, 13 January 2021
Joomla 包含了很多特色,可以協助在其上開發應用和擴充套件時的安全性。您應該要盡可能地一直使用這些特色功能,因為它們是已經被開發社群嘗試過、檢查過;而且可能還會在未來需要被更新。以下是關於使用 Joomla API最佳實踐的描述,確保您的擴充套件是盡可能安全的。
使用 request 來獲取資料
從Joomla 3.0 版本開始, 應該停止使用JRequest,改成使用JInput
所有來自使用者發起的輸入都必須要被視為具有潛在危險的,並且必須要在使用前先做過清理。您應該總是使用 Joomla JInput class 來從請求擷取資料,而不是赤裸裸的 $_GET
, $_POST
或是 $_REQUEST
變項,因為 JInput
method 預設會過濾用戶的輸入。 JInput
會處理所有方面的用戶請求,讓它獨立於使用的 request method。 JInput
也可以用於獲取 cookie資料,甚至是伺服器和環境變數。然而,非常重要的是,使用正確的JInput method,來確保最大的安全性。使用 JInput->get
method ,輔以預設參數是十分容易的,儘管在很多案例中,還可以對使用者的輸入套用更加嚴格的規範。
非常重要的是,要了解 JInput
方法並非 SQL-aware,而且需要額外作業來防範 SQL Injection。如果沒有在呼叫 JInput->get 當中指定預設,並沒有預設的值會被取回。假如沒有指定預設的話,而且沒有在請求變數當中顯示 argument,就會取回未定義(undefined)。
使用 JInput 也可以消除您需要留意 magic_quotes_gpc
設定的麻煩。無論您的 magic_quotes_gpc
有沒有打開,JInput 都恪盡職守。請查閱security.magicquotes.php 以獲得更多資訊。
考慮到用戶的輸入內容,您需要思考關於您要獲取的資料類型,並套用最嚴謹的 JInput 類型,依照每個不同的案例來應用。特定地說,避免使用像是JInput->get 的懶惰蟲手段,因為它會取回陣列,當中可能包含您不想要顯示的。儘管這些內容會被清理,它們經常在某些個別 argument 中,被額外的過濾器找到。例如,get 方法會把所有的 arguments 當成字串(string) 來處理,然而它們是可以被限制為整數之類的。
JInput 方法中頭三個參數 (parameter) 是相同的,只有頭一項 parameter 是強制的。一般而言,格式是
JFactory::getApplication->input-><data-source>->get<type>( <name>, <default> )
其中
<type> | 可以獲取的資料類型 (在底下查可以使用的類型)。 |
<name> | 要獲取的變數(variable)的名稱(name) (例如,在 URL 當中 argument 的名稱name). |
<default> | 預設的值 |
<data-source> | 指定變數要從何處來獲取 (見底下). |
底下的 <data-source> 值是支援的:
get | 由 URL 中 query 的部分送出的資料 |
post | 從欄位 (field) 送出的資料。 |
method | The same as either GET or POST depending on how the request was made. |
cookie | 在 cookies 中送出的資料。 |
request | 所有的 GET, POST 以及 COOKIE 合併資料。這是預設的。 |
files | 關於 POST request 檔案上傳的資訊 |
env | 環境變數 (platform-specific) |
server | 網站伺服器變數 (platform-specific) |
請注意預設會使用 REQUEST,其中包含了 cookie 資料。
以下的段落深入解釋每種資料類型。
整數
以下會接受整數。整數型可以包含一個前導的負號( -
),但正號( +
)是不允許的。
$integer = JFactory::getApplication->input->getInt( 'id' );
會從 request 回傳 value of the "id" argument from the request (which by default includes all GET, POST and COOKIE data). The default value is zero.
$integer = JFactory::getApplication->input->cookie->getInt( 'myId', 12 );
會從 cookie 回傳 value of the "myId" variable, with a default value of 12.
浮點數
浮點數型可以包含一個前導的負號( -
),但正號( +
)是不允許的。如果數字包含了千分位號,那千分位號前頭必須要至少有一個數字。例如,
$float = JFactory::getApplication->input->getFloat( 'price' );
會回傳 the value of the 'price' argument from the request. 預設的值是 "0.0"
$float = JFactory::getApplication->input->post->getFloat( 'total', 100.00 );
會從 POST (而非 GET) 請求回傳 'total' 值。預設的值是 100.00
布林值
所有「非零」的值都會被視為 'true'。zero 是 'false'
$boolean = JFactory::getApplication->input->getBool( 'show' );
會回傳 false if the value of the 'show' argument in the request is zero, or 1 (true) if the argument is anything else. 預設的值是 false. Note that any string argument will result in a return value of true, so calling the above with a URL containing "?show=false" 事實上會回傳 true!
$boolean = JFactory::getApplication->input->get->getBool( 'hide', true );
會獲取 the value of the 'hide' argument from a GET request (but not a POST)。預設的值是 true.
Word
Word 的定義是指使用A到Z組成的字段。在 word 中使用部分小寫的字母是允許的。
$word = JFactory::getApplication->input->cookie->getWord( 'search-word' );
會獲取由request送出的 'search-word' 的值。預設是空白字串。
$word = JFactory::getApplication->input->cookie->getWord( 'keyword', '' );
會獲取 cookie 中 'keyword' 變數的值。預設是空白字串。
指令(Command)
指令(Command) 類似 word 但是允許的字元是更廣泛的。允許的字元包含:all alphanumeric characters, dot, dash (hyphen) and underscore.
$command = JFactory::getApplication->input->getCmd( 'option' );
會獲取由 request 請求回傳的 "option" 值。預設值是空字串。
$command = JFactory::getApplication->input->post->getCmd( 'controller', 'view' );
會獲取由 POST 請求(而非 GET) "controller" 參數的值。預設值是 'view'
字串
字串型允許更廣泛的字元輸入 It also takes an optional fourth argument specifying some additional mask options. 請查看 #Filter options for information on the available masks.
$string = JFactory::getApplication->input->getString( 'description' );
會獲取從 request 回傳 "description" 參數的值。預設的值是空字串。輸入的值會清除前後的空白,以及 HTML 標籤。
$string = JFactory::getApplication->input->getString( 'text', '' );
會獲取從 request 回傳 "text" 參數的值。預設的值是空字串。
$string = JFactory::getApplication->input->getString( 'template', '<html />' );
會從 request 回傳"佈景主題"參數的值。預設的值是 '<html></html>'.
JSON 字串
$json = JFactory::getApplication->input->json->get( 'var_name' );
通用及其他資料類型
If the above methods do not meet your needs, there is a small number of additional filter types which you can use by calling the JInput->get method directly. The syntax is:
JFactory::getApplication->input->get( <name>, <default>, <type> );
where:
<name> | the name of the variable to be retrieved (for example, the name of an argument in a URL). |
<default> | the default value. There is no default value that will be returned if no default is specified in the call the JInput->get. If no default is specified and the argument is not present in the request variable then it will return undefined. |
<type> | specifies the data type expected (see below). |
The first three arguments are the same as for the more specific methods described earlier. Only the first argument is mandatory.
Allowed values of the <type>, which is case-insensitive, are as follows:
INT, INTEGER | 相當於 JInput->getInt. |
UINT | Get an unsigned integer. 相當於 JInput->getUint. |
FLOAT, DOUBLE | 相當於 JInput->getFloat. |
BOOL, BOOLEAN | 相當於 JInput->getBool. |
WORD | 相當於 JInput->getWord. |
ALNUM | 僅允許 alphanumeric characters (a-z, A-Z, 0-9). 相當於 JInput->getAlnum. |
CMD | 相當於 JInput->getCmd. |
BASE64 | 僅允許 those characters that could be present in a base64-encoded string (ie. a-z, A-Z, 0-9, /, + and =). 相當於 JInput->getBase64. |
STRING | 相當於 JInput->getString. |
ARRAY | Source is not filtered but is cast to array type. When using this type you should use JFilterInput directly to filter the values in your data array. |
HTML | A sanitised string. 相當於 JInput->getHtml. |
PATH | Valid pathname regex that filters out common attacks. For example, any path beginning with a "/" will return an empty string. Simliarly, any path containing "/./" or "/../" will return an empty string. Dots within filenames are okay though. 相當於 JInput->getPath. |
USERNAME | 移除 control characters (0x00 - 0x1F), 0x7F, <, >, ", ', % and &. 相當於 JInput->getUsername. |
過濾選項
所有的輸入值都應該要用 JFilterInput->clean 來過濾
過濾值矩陣
$data = JFactory::getApplication()->input->post->get('data', array(), 'array');
$filter = JFilterInput::getInstance();
foreach ($data as $value)
{
$array[] = $filter->clean($value, 'string');
}
要看更多的過濾類型,請看 JFilterInput source.
底下列出的選項是過時的 JRequest library. 允許的 <options> 值羅列如下 (預設並不會套用任何一項):
JREQUEST_NOTRIM | 並不會移除字串前後的空白 |
JREQUEST_ALLOWRAW | 不會套用任何的過濾條件,請絕對謹慎使用! |
JREQUEST_ALLOWHTML | 不會移除字串中的 HTML |
Masks can be combined by logically OR'ing them. If no filter options are specified, then by default, whitespace is trimmed and HTML is removed.
上傳檔案
關於檔案上傳的安全性,網站伺服器已經提供了不錯的想法,然而,還是需要有些額外的手續,來確保檔案名稱以及路徑不會被濫用。一個簡化過的請求上傳檔案表單看起來像這樣:
<form action="index.php?option=com_mycomponent/form_handler.php" method="post" enctype="multipart/form-data">
<input type="file" name="Filedata" />
<input type="submit" />
</form>
按下送出按鈕後,瀏覽器將會使用POST請求來上傳檔案,呼叫 Joomla! 的 "components/com_mycomponent/form_handler.php" 來傳送控制項目這包含了像是以下的程式碼。變項 $somepath 必須要被設定到路徑中,讓網頁伺服器有權限可以建立檔案。
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );
// 從 request 獲得檔案資料矩陣
$file = JFactory::getApplication->input->get( 'Filedata', '', 'files', 'array' );
// 讓檔案名稱安全無害
jimport('joomla.filesystem.file');
$file['name'] = JFile::makeSafe($file['name']);
// 將上傳的檔案移動到常駐位置
if (isset( $file['name'] )) {
// Make sure that the full file path is safe.
$filepath = JPath::clean( $somepath.'/'.strtolower( $file['name'] ) );
// Move the uploaded file.
JFile::upload( $file['tmp_name'], $filepath );
}
Saving a request variable into user state
Because setting a user state variable from a variable in the request is such a common operation, there is an API method to make the task easier. This is generally safe to use because it calls JInput->get to obtain the input from the request, but remember that none of the input filtering calls will protect against SQL injection attempts.
$app = JFactory::getApplication();
$app->getUserStateFromRequest( <key>, <name>, <default>, <type> );
where
<key> | the name of the variable in the user state. |
<name> | the name of the request variable (same as the first argument of a JInput->get call). |
<default> | the default value to be assigned to the user state variable if the request variable is absent. The default is null. |
<type> | the type of variable expected. |
For example, getting an integer variable called 'id' from the request with a default value of 0, then saving it into a session variable called 'myid' can be done like this:
$app = JFactory::getApplication();
$app->getUserStateFromRequest( 'myid', 'id, 0, 'int' );
instead of something like this:
$app = JFactory::getApplication();
$app->setUserState( 'myid', $app->input->getInt( 'id', 0 ) );
Constructing SQL queries
SQL Injection 是常見的網站攻擊類型之一,攻擊者會對輸入值管控不良的資料庫,修改資料庫請求的語法來破壞資料庫。攻擊結果會造成資料庫內容被破壞,或是隱私資料外洩。因此,確保SQL語法結構被送出時,能夠被正確地使用 escape 以及 quote 過濾,是很重要的,這樣惡意輸入才不會構成惡意的 SQL 語法。您將不能倚靠JInput 方法來完成這件事,因為它並非 SQL-aware。
強化整數以及其他數字值的安全
在 MySQL 資料庫中,數字欄位不應該被 quote,因此,將它們做類型轉換是很重要的。若是沒有這樣處理,您的程式碼會暴露於風險之下,讓駭客在 SQL 資料中存放字串。
依照其類型,數值類型看起來像這樣:
// For SQL data types: INT, INTEGER, TINYINT, SMALLINT, MEDIUMINT, BIGINT, YEAR
$query = 'SELECT * FROM #__table WHERE `id`=' . (int) $id;
// For SQL data types: FLOAT, DOUBLE
$query = 'SELECT * FROM #__table WHERE `id`=' . (float) $id;
It's a good idea to get into the habit of always typecasting integers like this even if the variable was previously obtained using JInput->getInt. Further information on SQL injection attacks can be found here: http://php.net/manual/en/security.database.sql-injection.php and here: Retrieving_request_data_using_JInput#Getting_Values.
強化字串安全
In the examples that follow it is assumed that $db is an instance of a Joomla database object. This can always be obtained from JFactory using
$db = JFactory::getDBO();
Strings should always be escaped before being used in an SQL statement. This is actually very simple as the JDatabase->quote method escapes everything for you. You can also use the JDatabase->escape method directly. The following statements are equivalent:
$query = 'SELECT * FROM #__table WHERE `field` = ' . $db->quote( $db->escape( $field ), false );
$query = 'SELECT * FROM #__table WHERE `field` = ' . $db->quote( $field );
強化搜尋安全
Special attention should be paid to LIKE clauses which contain the % wildcard character as these require special escaping in order to avoid possible denial of service attacks. LIKE clauses can be handled like this:
// Construct the search term by escaping the user-supplied string and, if required, adding the % wildcard characters manually.
$search = '%' . $db->escape( $search, true ) . '%';
// Construct the SQL query, being careful to suppress the default behaviour of Quote so as to prevent double-escaping.
$query = 'SELECT * FROM #__table WHERE `field` LIKE ' . $db->quote( $search, false );
Secure dates
If data is to be entered into a datetime column then you can use the Joomla API to ensure a valid date format:
$date = JFactory::getDate( $mydate );
$query = 'UPDATE #__table SET `date` = ' . $db->quote( $date->toMySQL(), false );
Note that it is necessary to suppress database escaping as legitimate dates may contain characters that should not be escaped.
Secure field names
In the comparatively rare case where a field name is a variable, that should also be quoted using an API call:
$query = 'SELECT * FROM #__table WHERE ' . $db->quoteName( $field->name ) . '=' . $db->quote( $field->value );
Secure arrays of integers
When you have an array of ids, typically used for IN() queries, you have to sanitise it also with JArrayHelper::toInteger($cid); before imploding:
...
$catId = JArrayHelper::toInteger($catId);
$query->where($db->quoteName('x.category_id') . ' IN (' . implode(',', $catId) . ')');
Short aliases of Quote and QuoteName
Shorter alternatives to the quote methods may also be used. The following statements are equivalent:
$query = 'SELECT * FROM #__table WHERE ' . $db->quoteName( $field->name ) . '=' . $db->quote( $field->value );
$query = 'SELECT * FROM #__table WHERE ' . $db->qn( $field->name ) . '=' . $db->q( $field->value );
Securing forms
Apart from cleaning input variables as described above, you can also implement a simple technique which makes it more difficult for a cross-site request forgery attack (CSRF) to succeed. This involves adding a randomly-generated unique token to the form which is checked against a copy of the token held in the user's session. By checking that the submitted token matches the one contained in the stored session, it is possible to tie a rendered form to the request variables presented.
In POST forms you should add a hidden token field using:
echo JHTML::_( 'form.token' );
This outputs the token as a hidden form field looking like this:
<input type="hidden" name="8cb24ae69ffd7828ccecbcf06056e6fc" value="1" />
and places a copy of the token into the user's session, for later checking.
If you need to add the token to a URL rather than a form then you can use something like this:
echo JRoute::_( 'index.php?option=com_mycomponent&' . JSession::getFormToken() . '=1' );
In the most common scenario, you will want to check the token following a POST to the form handler. This can be done by adding this line of code to form handler:
JSession::checkToken() or die( JText::_( 'Invalid Token' ) );
If you need to pass the token in a GET request then you can check it like this:
JSession::checkToken( 'get' ) or die( JText::_( 'Invalid Token' ) );
In both cases the code will die if the token is omitted from the request, or the submitted token does not match the session token. If the token is correct but has expired, then JSession::checkToken will automatically redirect to the site front page.
清理檔案的系統路徑
If there is any possibility that a filesystem path might be constructed using data that originated from user input, then the path must be cleaned and checked before being used. 只要像這樣做,很容易就可以:
JPath::check( $path );
This will raise an error and terminate Joomla if the path contains a ".." or leads to a location outside the Joomla root directory. If you want to deal with the error yourself without terminating the application, then you can use code like this:
$path = JPath::clean( $path );
if (strpos( $path, JPath::clean( JPATH_ROOT ) ) !== 0) {
// Handle the error here.
}
The JPath:clean method can be used in your own code too. It merely removes leading and trailing whitespace and replace double slashes and backslashes with the standard directory separator.
清理檔案路徑檔案名稱
As with filesystem paths, if there is any possibility that a file name might be constructed using user-originated data, then the file name must be cleaned and checked before use. 像這樣做就可以完成:
jimport('joomla.filesystem.file');
$clean = JFile::makeSafe( $unclean );
This method removes sequences of two or more "." characters and any character that is not alphabetic, numeric or a dot, dash or underscore character. If there is a leading dot then that is removed too.