2010-11-06 96 views
0

安全地發出我正在製作一個程序,它將從PHP運行一個C++代碼。我如何編譯,運行,並返回一個C++程序的輸出securly?我的意思是我怎麼能做到這一點,而不會讓我的系統容易受到黑客的攻擊?我想我只是使用exec comman來編譯程序,然後使用exec運行程序。但我怎麼能這樣做呢?編譯,運行並返回C++程序的輸出,從PHP

+3

是你的問題「你如何讓別人安全地在你的機器上運行任意代碼? – thetaiko 2010-11-06 20:35:26

+0

在非網絡虛擬機內編譯和運行代碼可能被認爲是」可能的不安全「和」相對危險「。特別是如果你在技術上不夠精確,無法理解使用非虛擬機方法的沙盒所需的確切步驟。 – 2010-11-06 21:48:47

回答

2

這只是一些更先進的東西,你可以用非定製服務器來做。最有可能的。因爲大多數服務器提供商不會讓你執行進程,即使他們SURELY也不會讓你安裝GCC並在他們的機器上運行潛在的不安全代碼(執行進程,請記住?)...

我認爲做這樣的事情(帶有多語言編譯器,沙箱,SVC的在線開發工具),但僅僅是因爲我的普通計算機旁邊有很多空間以及自定義服務器。

,如果你有一個自定義服務器(假設它是Linux和最有可能LAMP):

  • GCC甚至更​​好克++安裝
  • 有一個虛擬機(如Bochs)以及任何Linux(其他平臺)的基本安裝 - 這僅適用於C和D步驟
  • 將文件放在一些臨時位置
  • 使用proc_open啓動g ++與列出的文件,但請確保您將其作爲專用用戶運行 - 例如gccuser - 沒有權限的用戶,但要從存儲文件的目錄中讀取
  • A)宣讀輸出(成功或錯誤/警告)G ++
  • B)讓用戶下載結果文件
  • C)把通過連接的結果文件,然後寫上虛擬機的硬盤該文件 - 然後運行它,你可以顯示輸出給用戶
  • D)(最先進的) - 在JavaScale中創建一個GUI有點兒東西(終端) ript/AS實時與正在運行的文件進行交流 - 添加一個時間限制......但這也意味着您需要同時運行多個Bochs(更多用戶) - 這意味着您需要將Bochs複製到temp目錄中,有一個空的HDD(僅OS)一起,在一個運行完的時候 - 刪除

proc_open - http://php.net/manual/en/function.proc-open.php

+1

即使那樣也不是很安全。你真正想要做的是運行對象代碼沒有網絡訪問 – Gabe 2010-11-06 20:51:33

+0

是的,我只是想過BOCHS ......但是再次 - 在整個過程中添加虛擬機使其變得更加困難。這個虛擬機可能會隨時被損壞 - 這意味着要維護虛擬機......嗯......如果我考慮它並不那麼難只保留一個「空的」(只安裝Linux)HDD文件,並在完成後始終用備份替換「已用」的。但是,好吧。這已經很大了。 – 2010-11-06 20:54:16

+0

添加了VM ... – 2010-11-06 20:58:50

0

檢查this項目。簡而言之,整個項目就是你想要實現的目標(我給你的svn subdir就是你需要的沙箱部分)如果你想自己做,你應該從這裏開始:chroot。 如果你是在Windows上,你需要嚴重依賴windows API,搜索msdn。

0

我以前做過,但是運行得到的二進制文件輸出二進制文件作爲下載文件,用戶可以編譯,但他們需要下載二進制文件並在計算機上運行,​​讓用戶編譯並運行服務器上的任意代碼是一個很大的漏洞。

無論如何,這是我的快速實施:

的index.php

<?php 
include 'compiler-gcc-mingw.php'; 

$docompile = intval($_REQUEST['docompile']); 
if($docompile){ 
    //compile 
    setUpDirectory(); 
    compile(); 
    if(IsError()){ 
     // 
     cleanUp(); 
    } 
    else { 
     getExecutable(); 
     cleanUp(); 
     downloadExecutable(); 
     exit(); 
    } 
} 

$defaultSource = " 
#include <iostream> 

using namespace std; 
int main(){ 
    cout<<\"Hello Word!\"<<endl; 
    getchar(); 
    return 0; 
} 
"; 
?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Online C++ Compiler v1.0</title> 
<link href="style.css" rel="stylesheet" type="text/css" />  
</head> 
<body> 
<h1>Online Compiler v1.0</h1> 
<p>Online Windows C++ compiler using Mingw compiler </p> 

<?php 
if(IsError()){ 
    $error = getError(); 
    echo '<p><b>Compilation Error! Check your source code</b></p>'; 
    echo '<p>'.$error.'</p>'; 
} 
?> 
<form name="compile" method="post"> 
<input type="hidden" name="docompile" value="1" /> 
<p><b>Source Code:</b></p> 
<textarea name="source" rows="20" cols="80"><?php 
if($docompile) echo stripslashes($_REQUEST['source']); 
else echo $defaultSource; 
?> 
</textarea> <br /> 
<input type="submit" name="Submit" value="Compile"> 
</form> 

</body> 
</html> 

編譯器GCC-mingw.php

<?php 
    $dir = ''; 
    $exeData; 
    $errorFlag; 
    $errorDetail = array(); 

    function makeDir(){ 
     // 
     global $dir; 
     $count = 0; 
     do{ 
      $count++; 
      $dir = 'source/data'.$count; 
     }while([email protected]($dir)); 
    } 

    function setUpDirectory(){ 
     //make source dir : source001, source 002 etc 
     //make source file 
     global $dir; 
     makeDir(); 
     $source = stripslashes($_REQUEST['source']); 
     file_put_contents($dir.'/source.cpp', $source); 
    } 

    function compile(){ 
     // compile, get error message, assuming the compiler is in the system PATH 
     // cd to compile dir 
     global $dir; 
     $compileString = 'g++ '.$dir.'/source.cpp -o '.$dir.'/a.exe '; 
     global $errorFlag; 
     global $errorDetail; 
     $output = exec($compileString, $errorDetail, $errorFlag); 

    } 

    function isError(){ 
     // if error return true 
     global $errorFlag; 
     return $errorFlag; 
    } 

    function getError(){ 
     // get error detail 
     global $errorDetail; 
     $data = ''; 
     foreach($errorDetail as $key=>$value){ 
      $data .= $value.'<br />'; 
     } 
     return $data; 
    } 

    function getExecutable(){ 
     // retrieve exe data to memory 
     global $exeData; 
     global $dir; 
     $exeData = @file_get_contents($dir.'/a.exe'); 
    } 

    function cleanUp(){ 
     // delete all temporary files 
     global $dir; 
     $alist = scandir($dir); 
     foreach($alist as $key => $value){ 
      if(is_file($dir.'/'.$value)) { 
       unlink($dir.'/'.$value); 
      } 
     } 

     rmdir($dir); 
    } 

    function downloadExecutable(){ 
     // download to browser 
     global $exeData; 
     outputFile('program.exe', $exeData); 
    } 

    /** 
    * download content 
    * return value: false=cannot output the header, true=success 
    */ 
    function outputFile($filename, $data){ 
     //Download file 
     if(ob_get_contents()) 
      return false; 
     if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) 
      header('Content-Type: application/force-download'); 
     else 
      header('Content-Type: application/octet-stream'); 
     if(headers_sent()) 
      return false; 
     header('Content-Length: '.strlen($data)); 
     header('Content-disposition: attachment; filename="'.$filename.'"'); 
     echo $data; 
    } 
?> 

基本上它編譯代碼編寫在文本區域中,將其保存到臨時文件夾中的一個臨時文件中,編譯它(我使用mingw compi ),讀取生成的二進制文件,刪除所有臨時文件(包括* .o和二進制* .exe文件),並將生成的二進制文件作爲下載文件提供給用戶。

相關問題