2010-05-05 85 views
18

我想通過JSONP提供一個web服務,並想知道,如果我需要清理回調參數的值。我是否需要清理JSONP調用中的回調參數?

我目前的服務器端腳本看起來像這樣目前(或多或少代碼是在PHP,但可以是任何東西真的。):

header("Content-type: application/json; charset=utf-8"); 
echo $_GET['callback'] . '(' . json_encode($data) . ')'; 

這是一個經典的XSS-漏洞。

如果我需要清潔它,那麼如何?我無法找到有關可能允許回調字符串的足夠信息。我從Wikipedia引述如下:

儘管填充(前綴)典型地是在瀏覽器的執行上下文中定義的回調函數的名稱,它也可以是一個變量賦值,if語句,或者任何其他Javascript語句前綴。

回答

10

是的,當callback就像

(function xss(x){evil()}) 

當你從PHP回顯,將貌似

(function xss(x){evil()})(json) 

功能XSS將運行與邪惡()可以進行一些代碼發送的cookie到別的地方。

所以,消毒,以唯一有效的功能名稱,例如,限制它爲字符

+0

看起來不錯。我會試試這個。 – 2010-05-07 13:33:42

+3

如果您使用的是英語語言環境,則可以使用ctype_alpha($ _ GET ['callback'])輕鬆檢查此情況,否則過濾器函數可以很好地工作。另請注意,標題應設置爲'content-type:application/json; charset = utf-8'時返回一個jsonp響應。 – Josh 2011-01-23 23:07:57

+0

固定。並感謝您的信息。 – 2011-01-25 09:01:52

3

是。由於JSONP基本上是一種自我造成的XSS攻擊(不管是否臨時)將腳本標記插入到不同的主機名並讓它調用全局函數或全局對象的方法),至少要採取一些預防措施你將「回調」限制爲一個回調。

所以基本上任何有效的標識符。你可以爲對象成員制定一個例外。我不建議讓括號保持簡單,因爲它允許函數調用,而不是。

以下是我將如何創建支持JSON和JSONP的基本API的示例。下面的例子是在PHP中(從MediaWiki的API工作方式來簡化),但是可以用其他編程語言創建類似的結構。

<?php 

$responseData = array(
    'foo' => 'bar', 
    'count' => array('one', 'two', 'three'), 
    'total' => 3, 
); 

$prefix = $suffix = ''; 
$ctype = 'application/json'; 

if (isset($_GET['callback'])) { 
    $ctype = 'text/javascript'; 
    // Sanitize callback 
    $callback = preg_replace("/[^][.\\'\\\"_A-Za-z0-9]/", '', $_GET['callback']); 

    $prefix = $callback . '('; 
    $suffix = ')'; 
} 

header('Content-Type: ' . $ctype . '; charset=UTF-8', true); 

print $prefix . json_encode($responseData) . $suffix; 

exit; 
11

您希望確保回調是有效的標識符,可以是字母數字,下劃線或$。它也不能是一個保留字(只是爲了徹底,我會確保它不是undefined,NaNInfinity)。這是我使用的測試:

function valid_js_identifier($callback){ 
    return !preg_match('/[^0-9a-zA-Z\$_]|^(abstract|boolean|break|byte|case|catch|char|class|const|continue|debugger|default|delete|do|double|else|enum|export|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|var|volatile|void|while|with|NaN|Infinity|undefined)$/', $callback); 
} 

許多保留字是毫無意義的,但其中一些可能會導致錯誤或無限循環。

重要提示:不只是通過替換字符來消毒輸入;修改後的回調可以無誤地運行,並且返回的數據將不會被正確處理(甚至可能由錯誤的函數處理)。你想測試輸入是否有效,如果不是,則拋出錯誤。這將避免意外的行爲,並通知開發人員需要不同的回調。

注意:這是一個更安全但限制的JSONP版本,不允許表達式或細化。我發現它適用於大多數應用程序,特別是如果您使用jQuery和$.getJSON

4

是的。

正如@YOU所描述的,攻擊者可以製作一個回調參數,評估爲惡意JavaScript,或者更糟糕的是,malicious Flash

確認回調不是保留字並且是字母數字,如@ Brett-Wejrowski所述是一個好的開始。 Google,Facebook和Github正在通過向jsonp回調預先發布空的評論(如/ ** /)來緩解Rosetta Flash漏洞。

另一種方法是像ExpressJS確實返回一個更安全的JavaScript表達式:

typeof callbackstring === 'function' && callbackstring(.....); 
相關問題