Reputation: 294
I am making a program that will run a persons C++ code from PHP. How can I compile, run, return the output of a C++ program securly? By securly I mean how can I do it without making my system vulnerable to hackers? I guess I would just use the exec comman to GCC to compile the program then run the program using exec. But how can I do this securly?
Upvotes: 0
Views: 2973
Reputation: 53940
check out http://codepad.org, esp. the "how it works" section http://codepad.org/about
Upvotes: 1
Reputation: 131
I've done it before, but instead running the resulting binary it output the binary as download. The user can compile but they need to download the binary and run it in their computer. Letting users compile and run arbitrary code on your server is a big vulnerability IMO.
Anyway, this is my quick implementation:
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>
compiler-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;
}
?>
Basically it compile the code written in the text area, save it into a temporary file in a temporary folder, compile it (I use mingw compiler), read the resulting binary, remove all temporary files (including *.o and the binary *.exe files) and offer the resulting binary as download to user.
Upvotes: 0
Reputation: 8280
Check this project. In short, that entire project is what you are trying to achieve (and the svn subdir I gave you is the sandbox part you need. If you want to do it on your own this is where you should start: chroot. If you are on the windows you need to rely heavily on the windows API. Search msdn for that.
Upvotes: 0
Reputation: 7973
This is something just a little bit more advanced that something you would be able to do with a non-custom server. Most likely. Because most server providers won't let you execute processes, and even if, they SURELY won't let you install GCC there and run potentially unsafe code on their machine (executing processes, remember?)...
I thought of doing something like this (online development tools with multi-language compilers, sandboxes, SVC...) someday, but just because I have a lot of space as well as a custom server right next to my normal computer.
IF you've got a custom server (supposing it's Linux, and most likely LAMP):
proc_open - http://php.net/manual/en/function.proc-open.php
Upvotes: 2