从PHP开始,编译,运行和返回C ++程序的输出

时间:2010-11-06 20:32:00

标签: php c++ security

我正在制作一个程序,它将运行PHP的人员C ++代码。如何安全地编译,运行,返回C ++程序的输出?我的意思是,如果不让我的系统容易受到黑客攻击,我该怎么办呢?我想我只是使用exec comman到GCC编译程序然后使用exec运行程序。但我怎么能这样做呢?

4 个答案:

答案 0 :(得分:2)

对于非自定义服务器,您可以使用更高级的功能。最有可能的。因为大多数服务器提供商都不允许你执行进程,即使他们也不允许你在那里安装GCC并在他们的机器上运行可能不安全的代码(执行进程,还记得吗?)......

我想有一天会做这样的事情(有多语言编译器,沙盒,SVC等的在线开发工具),但仅仅因为我有很多空间以及我的普通计算机旁边的自定义服务器

如果您有自定义服务器(假设它是Linux,很可能是LAMP):

  • 安装了 gcc 或更好的 g ++
  • 安装了虚拟机(如Bochs),以及任何Linux(其他平台)的基本安装 - 这仅适用于C和D步骤
  • 将文件放在某个临时位置
  • 使用 proc_open 启动带有列出文件的 g ++ ,但请确保将其作为专用用户运行 - 例如gccuser - 没有权限的用户,但是从存储文件的目录中读取
  • A)从 g ++
  • 中读出输出(成功或错误/警告)
  • B)让用户下载结果文件
  • C)将结果文件放入链接器,然后将该文件写入VM的HDD - 然后运行它,然后将输出显示给用户
  • D)(最先进的) - 在JavaScript / AS中创建GUI类似的东西(终端)以实时与正在运行的文件对话 - 添加时间限制......但这也意味着您需要多个Bochs一次运行(更多用户) - 这意味着你需要将一个Bochs复制到一个临时目录,连同一个空HDD(只有操作系统),在那个上运行它,完成后 - 删除

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

答案 1 :(得分:1)

退房http://codepad.org,尤其是“如何运作”部分http://codepad.org/about

答案 2 :(得分:0)

检查this项目。简而言之,整个项目就是你想要实现的目标(我给你的svn子目录是你需要的沙箱部分。如果你想自己这样做,那么你应该从哪里开始:chroot。 如果您在Windows上,则需要严重依赖Windows API。搜索msdn。

答案 3 :(得分:0)

我以前做过,但是运行生成的二进制文件,它输出二进制文件作为下载。用户可以编译,但他们需要下载二进制文件并在其计算机中运行它。让用户在您的服务器上编译和运行任意代码是一个很大的漏洞IMO。

无论如何,这是我的快速实施:

<强>的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(!@mkdir($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编译器),读取生成的二进制文件,删除所有临时文件(包括* .o和二进制* .exe文件)并将生成的二进制文件作为下载提供给用户。