Jump to content


Photo

i got hacked


  • Please log in to reply
6 replies to this topic

#1 someone1

someone1
  • New Members
  • Pip
  • Newbie
  • 5 posts

Posted 22 March 2006 - 04:25 PM

Hello all,
My Host has recently emailed me explaining to me that my website has been hacked. I use the simpiliest form of PHP on my website, an ALL html layout with a simple inlcude statement for my content area. It seems that when the include variable is set equal to "http://fanklinsys.nm...orship_api.php" that the user has full access to my files and MySQL db's. They can delete files, folder, CHMOD them, upload files (and i've tested these all) and some things more. My host is requesting that a security update be made to the script but i'm not sure how to prevent this completely other than blocking that URL (which won't stop them from uploading the script somewhere else or renaming the file).

If anybody is familiar with this exploit, please help me out with a way to block it!

<?php  if (isset($_GET['page'])) {include($page); }  else {include('news/news.php'); }; ?>


#2 kenrbnsn

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

Posted 22 March 2006 - 04:39 PM

Do not, in any circumstances, include a file where the name comes from the URL without checking that it is a file you know about.

You wrote that your code looks like:
<?php  if (isset($_GET['page'])) {include($page); }  else {include('news/news.php'); }; ?>
This means that a hacker could do
[a href=\"http://your.domain.here/yourfile.php?page=../../../../.passwd\" target=\"_blank\"]http://your.domain.here/yourfile.php?page=..../../../.passwd[/a]
and you would display your host's password file or they could enter a URL that points to a shell script and really screw you up.

Here are a few things you should check for before including the file:
  • Does the filename contain the string "http://", if so reject it
  • Does the filename contain the string "../", if so reject it
  • Does the filename contain an extension? Accept only strings with no extensions. Your script should always provide the extension.
  • Have a predetermined list of files that are acceptable and only allow those.
Go to the PHP Security Consortium's [a href=\"http://phpsec.org/\" target=\"_blank\"]web site.[/a] There is a lot of very good information there. Always program defensively -- assume someone is going to try to break you code.

Ken

#3 obsidian

obsidian
  • Staff Alumni
  • Advanced Member
  • 3,202 posts
  • LocationSeattle, WA

Posted 22 March 2006 - 05:01 PM

another point to add, although, this does limit the flexibility of the code somewhat: instead of allowing the script to read the full include path from the QUERY_STRING, have all your valid options in a database table and simply pass a reference to that item from the database or even a flat text file. this way, you always have a control setup over what pages are allowed. it's much easier to try to list ALLOWED arguments than to try to come up with an exhaustive list of those pages that ARE NOT allowed.
You can't win, you can't lose, you can't break even... you can't even get out of the game.

<?php
while (count($life->getQuestions()) > 0)
{   $life->study(); } ?>
  LINKS: PHP: Manual MySQL: Manual PostgreSQL: Manual (X)HTML: Validate It! CSS: A List Apart | IE bug fixes | Zen Garden | Validate It! JavaScript: Reference Cards RegEx: Everything RegEx

#4 redbullmarky

redbullmarky
  • Staff Alumni
  • Advanced Member
  • 2,863 posts
  • LocationBedfordshire, England

Posted 22 March 2006 - 07:47 PM

obsidian, apologies if this is covering what you were getting at.

in my opinion, $_GET, $_POST and $_COOKIE (GPC) are the three to really be super-paranoid about if you want a secure site, as they're the 3 php superglobals that primarily deal with input from the user.

if you're not doing some sort of processing, no matter how simple the script is, on these three, then you're asking for trouble as either can be exploited with certain code to either make your script act erratically or reveal/do things that you don't want. whilst 'SQL Injection' is mainly aimed at people dealing with mysql databases, the principles involved and the methods to cut out injection relate to scripting whether you use a database or not.

if your system is kinda like a templating system, then use an array/mysql/flatfile system to store and retrieve the information you need rather than allowing a user to get 'straight to the heart' of your code'. so if you had a templating system, you might have something like:

$module = $_GET['action'];

$all_actions = array('thisone'=>'thisone.php', 
                          'thatone'=>'thatone.php',
                          'theother'=>'theother.php');


if (isset($all_actions[$module]))
{
   include($all_actions[$module]);
}
else
{
   echo 'get out of here!!!!!!';
   exit;
}

obviously there is more to consider, like checking for invalid characters in the URL parameter, but what the above does is puts a barrier or two in between the user and the script.

from my old college teacher:
a bouncer at the door of a night club will stop most under-age drinkers getting in, but there's always one that can get through. put an extra one or two on the door, who all ask for age identification, and things get much harder for them. it's not much different in web security. stop everything that comes through, check it thoroughly, etc, and maybe your site won't get shut down like a club that lets under-age drinkers in.
"you have to keep pissing in the wind to learn how to keep your shoes dry..."

I say old chap, that is rather amusing!

#5 someone1

someone1
  • New Members
  • Pip
  • Newbie
  • 5 posts

Posted 23 March 2006 - 02:57 AM

thank you all for the helpful responses

i have one last question:

Is there a way i can make an array of all strings that if found in the include path to be blocked?

right now, i'm doing this to block all http:// and ftp:// attempts, but i have a list of strings to search for, and if found, to not load a page, but i'd rather not make a million if statements:

<?php 
$findme  = "://";
$pos = strpos($page, $findme);
if($pos === false)
{
 if (isset($_GET['page'])) {include($page); }  else {include('news/news.php'); }; } ?>


#6 ToonMariner

ToonMariner
  • Members
  • PipPipPip
  • Advanced Member
  • 3,342 posts
  • LocationNewcastle upon Tyne, UK

Posted 23 March 2006 - 04:25 AM

I have tried this approach (and would be greatful for any comment).

Firstly where possible avoid includes from any user dictated flow control...

If unavoidable I prepend every path in the include with $_SERVER['DOC_ROOT']; hopefully forcing it to only include a file that is on this server.....
follow me on twitter @PHPsycho

#7 btherl

btherl
  • Staff Alumni
  • Advanced Member
  • 3,893 posts
  • LocationAustralia

Posted 23 March 2006 - 07:57 AM

You can do this:

$page = $_GET['page'];
$bad_strings = array(
  "://",
  "../",
);
foreach ($bad_string as $b) {
  if (strpos($page, $b) !== false) {
    die("I'm not including that!!");
  }
}

Another thing you can do is:

$page = $_GET['page'];
if (ereg("[^a-zA-Z0-9]", $page)) {
  die("I'm not including that!!");
}

That will reject anything which is not a letter or a number. If you want to allow other characters, you can include them in that regexp. In particular, this rejects ".", "/", and anything else needed to include something from another directory.

Even better is:

$page = $_GET['page'];
$allowed = array(
  "news",
  "forum",
);
if (!in_array($page, $allowed)) {
  die("no no no no no, a million times no!");
}

These are all implementations of kenrbnsn's suggestions.

Toonmariner, you may have a problem with files like "../../../../../etc/passwd".




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users