2010-01-12 97 views
1
echo "sed -i 's/NULL/\\N/g' ".$_REQUEST['para'].".sql"; 

上述說明適用。但它失敗,當我在這樣的exec使用它...sed不能與PHP執行功能配合使用

exec("sed -i 's/NULL//\/\/\N/g' ".$_REQUEST['para'].".sql"); 
+0

如果這就是你的意思,它們就不一樣了。在NULL之後,第二個有兩個正斜槓。 – 2010-01-12 12:49:42

+7

如果你在'exec()'調用中放置'$ _REQUEST ['para']',上帝會幫助你! – 2010-01-12 12:54:27

+2

看起來你可能有一個shell命令注入漏洞。 – 2010-01-12 12:56:19

回答

5

你應該逃避反斜槓反斜槓,而不是正斜槓,像這樣:

exec("sed -i 's/NULL/\\\\N/g' ".$_REQUEST['para'].".sql"); 

編輯我寫的答案而無需查看代碼的實際功能。不要這樣做,因爲$_REQUEST['para']可以是用戶想要的任何東西,可以用於code injection。按照其他答案的建議使用PHP函數。

+0

那些包含NULL的單詞正在被替換。對於。例如TNULLL成爲TNL如何添加單詞邊界? – shantanuo 2010-01-14 11:13:50

3

儘管完全取決於你,但我的建議是不要不必要地調用系統命令。在PHP中,您可以使用preg_replace()來執行sed的功能。

preg_replace("/NULL/","\\N",file_get_contents("$_REQUEST['para']"."sql")) 
+0

我想你錯過了一個報價。 – 2010-01-12 12:57:54

+1

我認爲替換的主題不是文件名,而是文件本身。但是你的想法更好更安全。 – stefita 2010-01-12 13:02:31

+0

@mark,thks。固定 – ghostdog74 2010-01-12 13:53:47

1

大廈ghostdog的想法,這裏的代碼實際上將你想要做什麼(他張貼實際上並沒有讀取該文件的內容的原始代碼):

//basename protects against directory traversal 
//ideally we should also do a is_writable() check 
$file = basename($_REQUEST['para'].".sql"); 
$text = file_get_contents($file); 
$text = str_replace('NULL', '\\N', $text); //no need for a regex 
file_put_contents($file, $text); 

不可否認,但是,如果有問題的文件超過幾兆,這是不可取的,因爲整個文件將被讀入內存。你可以在塊讀取它,但會得到一個比較複雜一點:

$file = basename($_REQUEST['para'].".sql"); 
$tmpFile = tempnam("/tmp", "FOO"); 
$in = fopen($file, 'r'); 
$tmp = fopen($tmpFile, 'w'); 
while($line = fgets($in)) { 
    $line = str_replace('NULL', '\\N', $line); 
    fputs($tmp, $line); 
} 
fclose($tmp); 
fclose($in); 
rename($tmpFile, $file); 

如果該文件是100+兆,說實話,稱SED直接像你這樣會更快。當涉及到大型文件時,試圖像sed/grep一樣重新生成一個類似於PHP的工具是不值得的。但是,你至少需要採取一些措施來保護自己,如果你打算這麼做:

採取一些基本的步驟,以確保amnom代碼:

$file = basename($_REQUEST['para'].".sql"); 
if(!is_writable($file)) 
    throw new Exception('bad filename'); 
exec("sed -i 's/NULL/\\\\N/g' ".escapeshellarg($file)); 
  1. 首先,我們稱之爲基本名稱,這 從我們的文件名 (去掉任何路徑例如,如果一個攻擊者提交的 字符串「/ etc/passwd文件」,我們希望至少 現在他們當前的工作目錄 限制
  2. 到文件 「passwd文件」
  3. 接下來,我們確保該文件在 其實是可寫的。如果不是,我們 不應該繼續
  4. 最後,我們escapeshellarg()在文件上。如果不這樣做,則允許執行任意的命令。例如,如果攻擊者提交了字符串/etc/passwd; rm -rf /; #,那麼您最終會收到命令sed 's/blah/blah/' /etc/passwd; rm -rf /; #.sql。應該清楚的是,雖然這個確切的命令可能不起作用,但找到一個實際上是微不足道的。
+0

致命錯誤:允許的內存大小20971520字節用盡(試圖分配7444267字節)在somefile.php行號123 我試圖通過使用ini_set(「memory_limit」,「20M」)增加分配的內存;但它仍然沒有按預期工作。 – shantanuo 2010-01-16 11:52:36

+0

做了重大修改,以涵蓋其他兩種處理方法。第一種方法適用於小文件;第二,文件超過幾兆,但可能不到100;最後是老實說,最好的方式去文件100兆和更大。 – 2010-01-16 15:24:24

+0

我建議增加內存限制到32或64也許。我必須這樣做才能運行一些腳本。 – JAL 2010-01-16 15:31:40