Compile C File using PHP

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
adhi91
Forum Newbie
Posts: 22
Joined: Wed Apr 04, 2012 8:54 pm

Compile C File using PHP

Post by adhi91 »

Hi,
I am currently using PHP on windows. I use a wamp server(Easy PHP) and codeblocks.
I already set the path from environment variable to compile a c file on cmd.
I use this command
gcc test.c -O3 -o test.exe
It can produce the test.exe

Now I want to execute it from a php file. I want the user to be able to compile their c file from a submit button.
print('<form action="compiler.php" method="POST"><input type="submit" value="Compile" ></form>');

Inside the compiler.php

Code: Select all

<?php
$output = system("C:\\Program Files\\CodeBlocks\\MinGW\\bin\\gcc.exe C:\\Program Files\\EasyPHP-5.3.9\\www\\upload\\test.c -O3 -o C:\\Program Files\\EasyPHP-5.3.9\\www\\upload\\test.exe");
echo $output;
?>
The result is an empty screen and no exe file produced in the 'upload' folder.

I already try
changing the $output variable to
$output = system('C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe C:\Program Files\EasyPHP-5.3.9\www\upload\test.c -O3 -o C:\Program Files\EasyPHP-5.3.9\www\upload\test.exe");
and
$output = system("C:/Program Files/CodeBlocks/MinGW/bin/gcc.exe C:/Program Files/EasyPHP-5.3.9/www/upload/test.c -O3 -o C:/Program Files/EasyPHP-5.3.9/www/upload/test.exe");
But there is no result.
What am I missing?
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Compile C File using PHP

Post by requinix »

Spaces. You've got spaces in the arguments. The one in the program name might also matter.

Add quotes.

Code: Select all

C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe "C:\Program Files\EasyPHP-5.3.9\www\upload\test.c" -O3 -o "C:\Program Files\EasyPHP-5.3.9\www\upload\test.exe"
And I see you're compiling code directly into a web-accessible folder... You've made sure CGI scripts in the upload/ directory won't be executed, right? Good. Now how about making sure these files can't be downloaded by anybody with simply the URL?
adhi91
Forum Newbie
Posts: 22
Joined: Wed Apr 04, 2012 8:54 pm

Re: Compile C File using PHP

Post by adhi91 »

Thank you very much.

Code: Select all

<?php
$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "C:\Program Files\EasyPHP-5.3.9\www\upload\test.c" -O3 -o "C:\Program Files\EasyPHP-5.3.9\www\upload\test.exe"');
echo $output;
?>
This works.

Sorry, I am quite new to PHP and this is my first time knowing that I need to prevent CGI script not to be executed.
I only set some parameter for uploading and downloading file. So, only file with extension c can be uploaded and exe can be downloaded.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Compile C File using PHP

Post by requinix »

adhi91 wrote:Sorry, I am quite new to PHP and this is my first time knowing that I need to prevent CGI script not to be executed.
Alright. Here's a little story.

Let's say I don't like you. Let's say I also discover this little site of yours where I can upload C code and your server compiles it for me. So now my first thought is, at the very least I can get your server penalized for hosting malware and viruses and all sorts of nasty things; all I have to do is upload a malicious C program, wait for your site to compile it, and distribute the URL of the compiled program. So now your site is a bad place and browsers like Firefox and Chrome, and sites like Google, give all your visitors a mean little warning about how the site can compromise their computer.

Now I get creative. I figure there's a chance of other vulnerabilities on your site. I poke around and find an XSS vulnerability in something user-generated. Maybe a comments page. That means I can get a page on your site showing whatever HTML I want. For that HTML I choose a bit of JavaScript that redirects the browser to the compiled EXE I made earlier, and now your site hosts drive-by downloads. Note that I could have made the browser redirect to a malicious site or include some malicious JavaScript I have hosted somewhere else.

Here's the best part: that's what I could do if you prevent CGI scripts from being executed. If you don't prevent it, and I must admit that your web server probably does, then I could execute whatever code I want on your server. Anything. Since I'm malicious, I'm going to write a virus and your server is going to be so nice as to execute it for me. But I think about it and decide no, not a virus: I'm going to find an exploit on your machine and make use of it. Now I have root access to your computer and you don't even know. Emails, uploads, passwords, configuration... everything is at my fingertips, and as long as I keep my actions conservative, you probably would never find out.

The second-best part is that I might not even have to go through all that work. You're sticking all file uploads in a web-accessible location. Sure, they're supposed to be files with C code, but what if they're not? So I try uploading a PHP script and... it doesn't compile. Of course not, I never expected it to. But I do see that the original file is still around. I browse to it and my script runs. So now we're back to the same situation: I can run arbitrary code on your machine, gain root access, pry into your private files, add the computer to my botnet, and do whatever I want.


After saying all that, know that I'm not malicious (normally). I don't want to scare you. But I do want you to get a glimpse of the bad things that can happen because there are people out there who are malicious.
The good news is that everything I said above can be prevented with a bit of know-how. If you're truly only allowing *.c files then I probably can't upload anything but C code (well, it could be anything, but the file would have a .c extension). But even that depends on your web server. That aside there's still executables floating around. Two basic requirements:
1. Make sure that CGI scripts cannot be executed in that directory. It doesn't hurt to explicitly state so rather than assuming it won't happen by default. This means the server will not execute "programs" in that directory. It will continue to execute PHP scripts and show images and all the things it would normally do.
2. Make sure these executables can't be automatically downloaded. This typically means some kind of authentication but there are alternatives. There are other precautions too like cleaning up old files.

And after all that, I don't recommend you make this available on a public site. It's a cool learning experience, you get to find out about executing programs from PHP and file uploads and things that you might not find on a "normal" website, but it's quite risky if you let just anybody use it.
If you're wondering, if I were doing it I wouldn't make it public either. I just wouldn't be comfortable with it. There's lots of planning and research I'd have to do before I felt knowledgeable enough to be able to prevent any problems.
adhi91
Forum Newbie
Posts: 22
Joined: Wed Apr 04, 2012 8:54 pm

Re: Compile C File using PHP

Post by adhi91 »

Wow, thanks for the explanation.
I get a clearer picture now.
Right now this is only for learning purposes only.

If I want to make the source and the output of the file to have the same name as the uploadedfile. How should I write the code?
Right now, I have

Code: Select all

echo"<input type=file name=uploadedfile onchange=this.form.submit()>";
//process for uploading file

echo"<form action='' method=POST><input type=submit value=Compiler name=compiler></form>";
if(isset($_POST['compiler']))
{
$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "C:\Program Files\EasyPHP-5.3.9\www\upload\test1.c" -O3 -o "C:\Program Files\EasyPHP-5.3.9\www\upload\test.exe"');
echo $output;
}

echo"<form action='' method=POST><input type=submit value=Compile name=compiler></form>";
//download
In the upload, all the variables I use $_FILES["uploadedfile"]. For the name I use $_FILES['uploadedfile']['name']. Why can't I use it in the compiler in order to restrict user. User have to follow the sequence of uploading, compile, then download, all using the same name.
I attempt using

Code: Select all

$source=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
$destination=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "$source" -O3 -o "$destination"');
The error message
Notice: Undefined index: uploadedfile in C:\Program Files\EasyPHP-5.3.9\www\index.php

How should I write the code?
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Compile C File using PHP

Post by requinix »

You're just showing little pieces of code. How about posting the whole thing uninterrupted?
adhi91
Forum Newbie
Posts: 22
Joined: Wed Apr 04, 2012 8:54 pm

Re: Compile C File using PHP

Post by adhi91 »

Here is the whole thing.

Code: Select all

<?php
echo"<html>";
echo"<head>";

//CSS
print('
<style type="text/css" >
input.hide
{
position:absolute;
left:-137px
-moz-opacity:0;
filter:alpha(opacity:0);
opacity:0;
z-index:2;
}
input.seagreen
{
background-color:#C1FFC1;
width:80px;
height:20px;
font-size:10px;
z-index:1;
color:#000000;
font-weight:bold;
}
</style>
');
//END OF CSS

echo"<title>Cloud IDE</title>";

//JAVASCRIPT
print('
<script language="javascript" type="text/javascript" src="/editarea/edit_area/edit_area_full.js"></script>
<script language="javascript" type="text/javascript">
editAreaLoader.init(
{
	id : "textarea_1"		  	// textarea id
	,syntax: "css"				// syntax to be uses for highgliting
	,start_highlight: true		// to display with highlight mode on start-up
}
);
</script>');
//END OF JAVASCRIPT

echo"</head>";
echo"<body>";

echo"<form action='' method=POST enctype=multipart/form-data>";
//method post to make it invisible
echo"<input type=hidden name=MAX_FILE_SIZE value=100000>";
//value is in bytes
echo"<input type=button class=seagreen id=pseudobutton value='Upload'>";
echo"<input type=file class=hide name=uploadedfile onchange=this.form.submit()>";
echo"</form>";

//START OF UPLOAD
$ext="";
if((!empty($_FILES["uploadedfile"])) && ($_FILES['uploadedfile']['error'] == 0))//Check the availability of the file. empty evaluate to true if empty
{
	$filename 	= strtolower(basename($_FILES['uploadedfile']['name']));
	$ext 		= substr	($filename, strrpos($filename, '.') + 1);
	//basename return component name. strtolower change to lowercase.
	//substr return some string after dot
	
	if (($ext=="c") && ($_FILES["uploadedfile"]["size"] < 100000) && ($_FILES["uploadedfile"]["type"] == "text/plain"))
	{
	//Determine the path of temporary file
	$ext=".".$ext;
	//add the dot
	//$newname = dirname(__FILE__).'/upload/'.$newfilename.$ext;
    $newname=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
	//file directory
		if ((move_uploaded_file($_FILES['uploadedfile']['tmp_name'],$newname)))
		//move_uploaded_file is php function for directory
		{
            print('<table>');
			print('<tr><td width=100px>File Name</td><td width=100px>File Size</td><td width=100px>Last Modified</td></tr>');
			print('<tr><td>'. $_FILES['uploadedfile']['name'] . '</td><td>'. round($_FILES['uploadedfile']['size']/1024,4) . ' Kb</td><td>'.date("d F Y H:i:s.", filemtime($newname)).'</td></tr>');
			print('</table>');  
			
			
		}
		else
		{
			print('Error:!');
		}
	} 
	else 
	{
	print('Error: Only .c files <500Kb');
	}	
} 
else 
{
}

//END OF UPLOAD


echo"<form action='' method=POST><input type=submit value=Compiler name=compiler class=seagreen></form>";
if(isset($_POST['compiler']))
{
$source=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
$destination=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
//$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "C:\Program Files\EasyPHP-5.3.9\www\upload\test1.c" -O3 -o "C:\Program Files\EasyPHP-5.3.9\www\upload\test.exe"');

$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "$source" -O3 -o "$destination"');
echo $output;
}

echo"<form action='' method=POST><input type=submit value=Download name=download class=seagreen></form>";

//START OF DOWNLOAD
if(isset($_POST['download']))
{

$file = "test.exe";
//put in directory
$exefile=dirname(__FILE__).'/upload/'.$file;

$filename 	= strtolower(basename($exefile));
$ext 		= substr	($filename, strrpos($filename, '.') + 1);

if ($ext=="exe")
{
    //check file exist
    if (file_exists($exefile))
    {
        //header=send a raw http header
        //will do a download 
        header('Content-Description: File Transfer');
        //tell browser type of file downloaded
        header('Content-Type: application/octet-stream');
        //attachment = tell browser that going to link a file
        //the name will be the same as $file.
        header('Content-Disposition: attachment; filename='.basename($file));
        //to prevent cache either by proxy or client browser
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        //compared it with the original server
        header('Cache-Control: must-revalidate');
        //to make IE accept download
        header('Pragma: public');
        // header('Content-Length: ' . filesize($exefile));
        header('X-Sendfile :'.$file);
        //erase output buffer
        ob_clean();
        //flush output buffer
        flush();
        //set obstacle
        //output a file
        readfile($exefile);
        exit;
    }
    else
    {
        print('<script type="text/javascript">');
        print('window.location="index.php"');
        print('</script>');
    }
}
else
{
    print('error');
}
}
else
{
}
//END OF DOWNLOAD

echo"
<form method=post>
<textarea id=textarea_1 name=content cols=80 rows=30>
content
</textarea>
</form>'";

echo"</body>";
echo"</html>";
?>
adhi91
Forum Newbie
Posts: 22
Joined: Wed Apr 04, 2012 8:54 pm

Re: Compile C File using PHP

Post by adhi91 »

Hi,
Seems that using the css have made the upload button not working

Code: Select all

<?php
echo"<html>";
echo"<head>";

//CSS
print('
<style type="text/css" >
input.hide
{
position:absolute;
left:-137px
-moz-opacity:0;
filter:alpha(opacity:0);
opacity:0;
z-index:2;
}
input.seagreen
{
background-color:#C1FFC1;
width:80px;
height:20px;
font-size:10px;
z-index:1;
color:#000000;
font-weight:bold;
}
</style>
');
//END OF CSS

echo"<title>Cloud IDE</title>";

//JAVASCRIPT
print('
<script language="javascript" type="text/javascript" src="/editarea/edit_area/edit_area_full.js"></script>
<script language="javascript" type="text/javascript">
editAreaLoader.init(
{
	id : "textarea_1"		  	// textarea id
	,syntax: "css"				// syntax to be uses for highgliting
	,start_highlight: true		// to display with highlight mode on start-up
}
);
</script>');
//END OF JAVASCRIPT

echo"</head>";
echo"<body>";

echo"<form action='' method=POST enctype=multipart/form-data>";
//method post to make it invisible
echo"<input type=hidden name=MAX_FILE_SIZE value=100000>";
//value is in bytes
[b]
//echo"<input type=button class=seagreen id=pseudobutton value='Upload'>";
//echo"<input type=file class=hide name=uploadedfile onchange=this.form.submit()>";
echo"<input type=file name=uploadedfile onchange=this.form.submit()>";
[/b]
echo"</form>";

//START OF UPLOAD
$ext="";
if((!empty($_FILES["uploadedfile"])) && ($_FILES['uploadedfile']['error'] == 0))//Check the availability of the file. empty evaluate to true if empty
{
	$filename 	= strtolower(basename($_FILES['uploadedfile']['name']));
	$ext 		= substr	($filename, strrpos($filename, '.') + 1);
	//basename return component name. strtolower change to lowercase.
	//substr return some string after dot
	
	if (($ext=="c") && ($_FILES["uploadedfile"]["size"] < 100000) && ($_FILES["uploadedfile"]["type"] == "text/plain"))
	{
	//Determine the path of temporary file
	$ext=".".$ext;
	//add the dot
	//$newname = dirname(__FILE__).'/upload/'.$newfilename.$ext;
    $newname=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
	//file directory
		if ((move_uploaded_file($_FILES['uploadedfile']['tmp_name'],$newname)))
		//move_uploaded_file is php function for directory
		{
            print('<table>');
			print('<tr><td width=100px>File Name</td><td width=100px>File Size</td><td width=100px>Last Modified</td></tr>');
			print('<tr><td>'. $_FILES['uploadedfile']['name'] . '</td><td>'. round($_FILES['uploadedfile']['size']/1024,4) . ' Kb</td><td>'.date("d F Y H:i:s.", filemtime($newname)).'</td></tr>');
			print('</table>');  
			
			
		}
		else
		{
			print('Error:!');
		}
	} 
	else 
	{
	print('Error: Only .c files <500Kb');
	}	
} 
else 
{
}

//END OF UPLOAD


echo"<form action='' method=POST><input type=submit value=Compiler name=compiler class=seagreen></form>";
if(isset($_POST['compiler']))
{
$source=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
$destination=dirname(__FILE__).'/upload/'.$_FILES["uploadedfile"]["name"];
//$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "C:\Program Files\EasyPHP-5.3.9\www\upload\test1.c" -O3 -o "C:\Program Files\EasyPHP-5.3.9\www\upload\test.exe"');

$output = system('"C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" "$source" -O3 -o "$destination"');
echo $output;
}

echo"<form action='' method=POST><input type=submit value=Download name=download class=seagreen></form>";

//START OF DOWNLOAD
if(isset($_POST['download']))
{

$file = "test.exe";
//put in directory
$exefile=dirname(__FILE__).'/upload/'.$file;

$filename 	= strtolower(basename($exefile));
$ext 		= substr	($filename, strrpos($filename, '.') + 1);

if ($ext=="exe")
{
    //check file exist
    if (file_exists($exefile))
    {
        //header=send a raw http header
        //will do a download 
        header('Content-Description: File Transfer');
        //tell browser type of file downloaded
        header('Content-Type: application/octet-stream');
        //attachment = tell browser that going to link a file
        //the name will be the same as $file.
        header('Content-Disposition: attachment; filename='.basename($file));
        //to prevent cache either by proxy or client browser
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        //compared it with the original server
        header('Cache-Control: must-revalidate');
        //to make IE accept download
        header('Pragma: public');
        // header('Content-Length: ' . filesize($exefile));
        header('X-Sendfile :'.$file);
        //erase output buffer
        ob_clean();
        //flush output buffer
        flush();
        //set obstacle
        //output a file
        readfile($exefile);
        exit;
    }
    else
    {
        print('<script type="text/javascript">');
        print('window.location="index.php"');
        print('</script>');
    }
}
else
{
    print('error');
}
}
else
{
}
//END OF DOWNLOAD

echo"
<form method=post>
<textarea id=textarea_1 name=content cols=80 rows=30>
content
</textarea>
</form>'";

echo"</body>";
echo"</html>";
?>
The code above is working.
This is the adjustment that I made from the previous code.

//echo"<input type=button class=seagreen id=pseudobutton value='Upload'>";
//echo"<input type=file class=hide name=uploadedfile onchange=this.form.submit()>";
echo"<input type=file name=uploadedfile onchange=this.form.submit()>";
Post Reply