2010-11-06 7 views
0

Я делаю программу, которая будет запускать код C++ для людей с PHP. Как я могу скомпилировать, запустить, вернуть вывод программы на C++? Посредственно я имею в виду, как я могу это сделать, не делая мою систему уязвимой для хакеров? Думаю, я просто использовал бы комманд exec для GCC для компиляции программы, а затем запустил программу с помощью exec. Но как я могу сделать это в безопасности?Компилировать, запускать и возвращать вывод программы на C++, от PHP

+3

Вопрос: «Как вы позволяете кому-то безопасно запускать произвольный код на вашем компьютере? – thetaiko

+0

Все, что меньше, чем компиляция и запуск кода внутри не-сетевой виртуальной машины, вероятно, можно считать« вероятной чтобы быть небезопасным "и" относительно опасным ". Особенно, если вы недостаточно разбираетесь в техническом уровне, чтобы понять точные шаги, необходимые для песочницы, используя подход без VM. –

ответ

2

Это что-то еще более продвинутое, что вы могли бы сделать с нестандартным сервером. Скорее всего. Поскольку большинство поставщиков серверов не позволят вам выполнять процессы, и даже если они SURELY не позволят вам устанавливать GCC там и запускать потенциально опасный код на своей машине (выполнение процессов, помните?) ...

Я думал что-то вроде этого (инструменты онлайн-разработки с многоязычными компиляторами, песочницами, SVC ...), но только потому, что у меня много места, а также собственный сервер рядом с моим обычным компьютером.

Если у вас есть собственный сервер (предположим, что это Linux, и, скорее всего, ЛАМПЫ):

  • имеют GCC или даже лучше г ++ установлен
  • имеют виртуальную машину (например, Bochs), а также базовую установку любой Linux (другой платформы) - это только для шагов C и D
  • положить файлы на некоторое временное место
  • proc_open начать г ++ с файлами в списке, но убедитесь, что вы запустите это как специальный пользователь - например, gccuser - пользователь с NO разрешений, но для чтения из каталога, в котором хранятся файлы
  • A) оглашает выход (успех или ошибки/предупреждения) от г ++
  • B) позволяет пользователю скачать файл результатов
  • с) поместить файл результата через линкер, а затем записать этот файл на жестком диске виртуальной машины - THEN запустите его, и вы можете показать результат пользователю
  • D) (самый продвинутый) - создать GUI-функцию (терминал) в JavaSc ript/AS, чтобы поговорить с текущим файлом в режиме реального времени - добавьте ограничение по времени ... это, однако, также означает, что вам нужно несколько одновременно работающих Bochs (больше пользователей) - это означает, что вам нужно скопировать Bochs в temp каталог вместе с пустой HDD (только с ОС), запустить его на том, когда закончил - удалить

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

+1

Даже тогда это не очень безопасно. Что вы действительно хотите сделать, это запустить объектный код внутри виртуальной машины, которая не имеет доступа к сети. – Gabe

+0

Да, я просто подумал о BOCHS ... Но опять же - добавление виртуальной машины во весь процесс делает ее намного сложнее. Установка другого Linux на виртуальную машину ... Тот факт, что эта ВМ может быть повреждена в любое время - означает ее поддержание ... Хм ... Если я думаю, что это не так сложно просто сохранить «пустой» (только установленный Linux) файл жесткого диска и всегда заменять «использованный» с резервной копией при завершении. Но хорошо. Это уже что-то довольно большое. –

+0

Добавил VM ... –

0

Проверка this проекта. Короче говоря, весь этот проект - это то, что вы пытаетесь достичь (и svn subdir, который я вам дал, - это часть песочницы, в которой вы нуждаетесь. Если вы хотите сделать это самостоятельно, вам нужно начать: chroot. Если вы на окнах вам нужно в значительной степени полагаться на API Windows. Найти msdn для этого.

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([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 ler), прочитайте полученный двоичный файл, удалите все временные файлы (включая * .o и двоичные * .exe-файлы) и предложите результирующий двоичный файл для загрузки пользователю.

Смежные вопросы