繁体   English   中英

从PHP安全地编译,运行和返回C ++程序的输出

[英]Compile, Run, and Return output of C++ program, securly from PHP

我正在制作一个程序,它将从PHP运行个人C ++代码。 我如何安全地编译,运行和返回C ++程序的输出? 毫无疑问,我的意思是在不使我的系统容易受到黑客攻击的情况下该怎么做? 我想我只会在GCC中使用exec comman来编译程序,然后使用exec运行程序。 但是我该如何安全地执行此操作?

这比使用非定制服务器可以执行的操作稍微先进一点。 最有可能的。 因为大多数服务器提供程序都不允许您执行进程,即使这样做,他们也肯定不会允许您在此处安装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(仅具有OS)一起复制到一个临时目录中,并在完成后在其中运行-删除

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

查看http://codepad.org ,尤其是。 “工作原理”部分http://codepad.org/about

检查项目。 简而言之,整个项目就是您要实现的目标(而我给您的svn子目录是您需要的沙箱部分。如果您要自己完成此工作,则应该从这里开始: chroot 。 Windows需要严重依赖Windows API,请在msdn中搜索。

我之前已经做过,但是运行生成的二进制文件却将二进制文件输出下载。 用户可以编译,但是他们需要下载二进制文件并在计算机上运行它。 允许用户在服务器上编译和运行任意代码是一个很大的漏洞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文件),并将生成的二进制文件下载给用户。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM