2010-11-06 43 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文件),并将生成的二进制文件作为下载文件提供给用户。

相关问题