Jump to content

i got hacked


someone1

Recommended Posts

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.ru/sponsorship_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!

[code]<?php  if (isset($_GET['page'])) {include($page); }  else {include('news/news.php'); }; ?>[/code]
Link to comment
Share on other sites

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:
[code]<?php  if (isset($_GET['page'])) {include($page); }  else {include('news/news.php'); }; ?>[/code]
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:[list][*] 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.[/list]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
Link to comment
Share on other sites

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.
Link to comment
Share on other sites

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:

[code]
$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;
}
[/code]

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.
Link to comment
Share on other sites

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:

[code]<?php
$findme  = "://";
$pos = strpos($page, $findme);
if($pos === false)
{
if (isset($_GET['page'])) {include($page); }  else {include('news/news.php'); }; } ?>[/code]
Link to comment
Share on other sites

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.....
Link to comment
Share on other sites

You can do this:

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

Another thing you can do is:

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

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:

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

These are all implementations of kenrbnsn's suggestions.

Toonmariner, you may have a problem with files like "../../../../../etc/passwd".
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.