I was searching around Packet Storm today and wanted to add there new files as a RSS/ATOM feed on my browser. I didn't find a link for this, so I created one in PHP. Below is the code that creates the atom.xml file.
Click Here To View
<?php
/
Connects to packstormsecurity.org and created a
atom feed of the last 20 uploaded files.
@requires php-curl php-tidy
@author Tully Rankin
@url http://www.TullyRankin.com
/
$ch = curlinit();
$url = 'http://www.packetstormsecurity.org/last20.html';
$site = 'http://www.packetstormsecurity.org';
curlsetopt($ch, CURLOPTURL, $url);
curlsetopt($ch, CURLOPTHEADER, 0);
curlsetopt($ch, CURLOPTRETURNTRANSFER, 1);
$data = curlexec($ch);
curlclose($ch);
$tidyconfig = array(
'clean' => true,
'output-xhtml' => true,
'show-body-only' => false,
'wrap' => 0
);
$tidy = tidyparsestring($data, $tidyconfig, 'UTF8');
$tidy->cleanRepair();
$xhtml = pregreplace('/\<spacer.*\>/','',$tidy);
$xml = new DOMDocument();
$xml->loadHTML($xhtml);
$body = $xml->getElementsByTagName("body")->item(0);
$links = $body->getElementsByTagName("a");
$x = 0;
foreach($links as $link)
{
if ($link->getAttribute("class") == "fname")
{
$files[$x]['name'] = $link->nodeValue;
$files[$x]['link'] = $link->getAttribute("href");
$x++;
}
}
$tables = $body->getElementsByTagName("table");
foreach ($tables as $table)
{
if ($table->getAttribute("class") != "fbox2") continue;
$tRows = $table->getElementsByTagName("tr");
foreach($tRows as $row)
{
if ($row->getAttribute("class") == "finfo")
{
if ($row->getElementsByTagName("td")->item(1) != null &&
$row->getElementsByTagName("td")->item(1)->getAttribute("valign") == "top")
{
$td = $row->getElementsByTagName("td")->item(1);
$text[] = $td->nodeValue;
}
}
}
}
$x = 0;
$fileNames = array();
foreach ($files as $file)
{
if (substr($file['link'],0,1) == "/")
{
$content[$x]['name'] = $file['name'];
$content[$x]['link'] = $site.$file['link'];
$content[$x]['text'] = $text[$x];
$x++;
}
}
$result = '<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>PacketStorm Security</title>
<link rel="alternate" type="text/html" href="http://www.tullyrankin.com/" />
<link rel="self" type="application/atom+xml" href="http://www.tullyrankin.com/atom.xml" />
<id></id>
<updated>2010-03-03</updated>
<subtitle>Security Feed</subtitle>
';
foreach ($content as $node)
{
$result .= "<entry>";
$result .= "<title>{$node['name']}</title>";
$result .= "<link href=\"{$node['link']}\" />";
$result .= "<summary>{$node['text']}</summary>";
$result .= "</entry>";
}
$result .= "</feed>";
$conn = @fopen('packetstorm.xml','w+');
if (@fwrite($conn, $result) === false)
{
die('<h1>Could Not create feed</h1>');
}
else
{
echo '<h1>Created new packetstorm.xml file!</h1>';
}
fclose($conn);
/**
* Class is used to read, search, and manipulate linux passwd file.
*
* @author Tully Rankin
* @website www.tullyrankin.com
*/
class ReadPasswd {
private $file;
private $fileData;
private $error;
/*
* Initialize the class and add contents of
* the password file into the variable file.
*/
function __construct($file) {
try{
if (is_file($file))
{
$this->fileData = file($file);
$this->file = $file;
}
else
{
throw new Exception("Couldn't open file.");
}
} catch (Exception $e) {
$this->error[] = $e->getMessage();
}
}
/*
* Returns string of all rows of data from the passwd file.
* Use this file if your trying to display in the browser.
*
* @type Public
* @return String
*/
public function getAllHTML() {
foreach ($this->fileData as $content)
{
$temp = explode(':', $content);
$output .= "<b>Username: {$temp[0]} </b><br />";
$output .= "Validation: {$temp[1]} <br />";
$output .= "User Identifier: {$temp[2]} <br />";
$output .= "Group Identifier: {$temp[3]} <br />";
$output .= "Gecos Field: {$temp[4]} <br />";
$output .= "Home Directory: {$temp[5]} <br />";
$output .= "Shell: {$temp[6]} <br />";
$output .= "<br />";
}
return $output;
}
/*
* Returns string of all rows of data from the passwd file. This is
* used if running the command from the command line.
*
* @type Public
* @return String
*/
public function getAllCLI() {
foreach ($this->fileData as $content)
{
$temp = explode(':', $content);
$output .= "Username: {$temp[0]} \n";
$output .= "Validation: {$temp[1]} \n";
$output .= "User Identifier: {$temp[2]} \n";
$output .= "Group Identifier: {$temp[3]} \n";
$output .= "Gecos Field: {$temp[4]} \n";
$output .= "Home Directory: {$temp[5]} \n";
$output .= "Shell: {$temp[6]} \n";
$output .= "\n";
}
return $output;
}
/*
* Searches for a user. Will return an array with
* the users credentials unless the second param is set.
* If true is set on the second parameter then the function
* will withold add the the user information to the returned array.
*
* @type Public
* @params String, Boolean
* @return Array
*/
public function searchUser($user,$data=0) {
try{
$data = array();
if (is_string($user))
{
foreach($this->fileData as $line)
{
$temp = explode(':', $line);
if (in_array($user,$temp))
{
if ($data) return 1;
$data['username'] = $temp[0];
$data['validation'] = $temp[1];
$data['user_identifier'] = $temp[2];
$data['group_identifier'] = $temp[3];
$data['gecos'] = $temp[4];
$data['home_directory'] = $temp[5];
$data['shell'] = $temp[6];
}
}
}
else
{
throw new Exception('A search error has occured.');
}
} catch (Exception $e) {
$this->error[] = $e->getMessage();
}
return $data;
}
/*
* Getter for Error Exception Array
* @type Public
* @return Array
*/
public function getError() {
return $this->error;
}
/*
* Removes user from passwd file
* @type public
* @return Boolean
*/
public function deleteUser($user) {
try{
if ($this->searchUser($user,1))
{
foreach ($this->fileData as $line)
{
$lines = explode(":",$line);
if (!in_array($user,$lines))
{
$final .= $line;
}
}
if(!file_put_contents($this->file,$final))
{
throw new Exception("Could not delete user.");
}
}
else
{
throw new Exception("User doesn't exist.");
}
} catch (Exception $e) {
echo $this->error[] = $e->getMessage();
}
}
}
I started re-writing a lot of my old code today to use AJAX. AJAX
stands for (Asynchronous Javascript and XML) and is a way of making
your web applications more interactive. So for example, you can refresh
results on the page from a form without having to reload the page. The
example that I'm going to show you is a name suggestion form. It will
display a html form input and will return results from a mysql database
that start with whatever char/chars you type in real time.
The form page looks like the following...
<html>
<head>
<title>Simple Ajax Example</title>
<script type="text/javascript">
var xmlhttp;
function showUser(str) {
xmlhttp=GetXmlHttpObject();
if (xmlhttp==null)
{
alert ("Browser does not support HTTP Request");
return;
}
var url="getNames.php";
url=url+"?name="+str.value;
url=url+"&nocache="+Math.random();
xmlhttp.onreadystatechange=stateChanged;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function stateChanged() {
if (xmlhttp.readyState==4)
{
document.getElementById("nameHint").innerHTML=xmlhttp.responseText;
}
}
function GetXmlHttpObject() {
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject)
{
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
</script>
</head>
<body>
<form name="formName" id="formName">
<input type="text" name="name" id="name" onKeyUp="showUser(this)">
</form>
<span id="nameHint" name="nameHint"></span>
</body>
</html>
The form calls getNames.php with the params name=[Input Field Value].
The Input field value is the value of whatever you type into the form
text input. The code that processes this request is below:
<?php
$name = striptags($GET['name']);
if (!empty($name))
{
if ($con = mysqlconnect('127.0.0.1', 'root', '1234'))
{
if (!mysqlselectdb('test'))
{
echo 'Could not connect to database';
exit;
}
$sql = sprintf("SELECT name FROM names WHERE name like '%s'",
mysqlrealescapestring($name.'%'));
$result = mysqlquery($sql,$con);
if (!$result)
{
echo 'Bad Query';
}
$rowCount = mysqlnumrows($result);
while ($row = mysqlfetch_assoc($result))
{
$names[] = $row['name'];
}
}
}
if (count($names) > 0)
{
echo '<ul>';
foreach ($names as $name)
{
echo "<li>$name</li>";
}
echo '</ul>';
}
As you can see, the getNames.php file first looks at the GET value for the name Parameter. I also have it wrapped in the striptags function
which will eliminate the chance of a user entering any kind of tags
that may end up breaking or altering the script. Next, I check to see
if the $name value is empty. The script will not display anything if the $name value is empty or there is no results. Now the script can connect to a mysql server and select the correct DB. Now I write
the query using the sprintf function. This allows me to alter multiple
variables in the string. I use the %s for string and have
mysqlrealescapestring function return the $name variable. The
mysqlrealescape_string prepends backslashes to the following
characters "\x00, \n, \r, \, ', " and \x1a".
I now query the database with the $sql string that I just created. I
create the variable rowCount which will return the # of rows returned
from the query. Next we loop through the results and add each name to
the $names variable.
We now have all the results in an array and need to display the result. I first check to see if the array is not empty. I do this by using the count() function on the $names array. If the count is greater then 0 we will display each of the rows returned in a unordered list <ul> tag.
This is by far the simplest AJAX example. We could have returned the results as JSON and looped through them better in the index.php page. I will write a more technical and more advanced example in the near future.
So I am now on my second week of learning the C language. I have been writing a lot of small programs just to get the hang of the code. I have written simple calculators, guess my number games, and simple quizzes. Tonight I was working on code that could parse a apache config and only display the DocumentRoot. The code I wrote to do this is shown below.
include <stdlib.h>
#include <string.h>
#define MAXLINE 128
FILE file;
int main(int argc, char argv[])
{
int i,x;
char line[MAXLINE];
char temp;
if (argc == 1)
{
puts("You must enter a file/files to search.");
exit(1);
}
for (i=1; i<argc;i++)
{
file = fopen(argv[i], "r");
if (file == NULL)
{
puts("Could'nt open file");
exit(1);
}
while ( (fgets(line, MAXLINE, file)) != NULL)
{
temp = malloc(sizeof (char) 128);
for (i=0; i<MAXLINE; i++)
{
do
{
temp[i] = line[i];
i++;
} while (line[i] != '\n');
temp[i] = '\0';
break;
}
if (strstr(temp, "DocumentRoot") != NULL) {
printf("%s\n", temp);
}
free(temp);
}
}
}
Working on a new site and wanted to add a function to add embed code from YouTube. I am limiting the amount of html that is allowed to be posted by the users. I also wanted to make sure the user could only embed a video from YouTube. The function I'm working on takes the URL of the YouTube page and parses the source for the embed code. Below is an example on how I am getting the data. The actual function does a lot more filtering of the URL string.
<p>
<form action="#" method="get">
<input type="text" name="url" value="YOUTUBE URL">
<input type="submit" name="submit" value="Get Embed Code">
</form>
</p>
<?php
if ($GET['url'] != "") {
$url = filegetcontents($GET['url']);
$url = pregmatch('/(input id="embed).*(\/>)/', $url, $arr);
$url = pregmatch('/(<).(\/object>)/',$arr[0], $result);
$result = html_entity_decode($result[0]);
echo '<b>The Video...</b><br />';
echo $result . '<br /><br />';
echo '<b>The embed code...</b><br />';
echo htmlentities($result) . '<br /><br />';
}
?>
<br />
<b>How to get the embed code from the linux Command line.</b>
<br />curl 'http://www.youtube.com/watch?v=vFMh2oeob18' | egrep '((input id="embed)./>)' | egrep -o '(<).*(/object>)'
I read "PHP Objects, Patterns, and Practice, Second Edition" a while back but nothing really kicked in. I have yet again started studying various design patterns. I have started reading "Head First Design Patterns" and feel this book is easier to understand. I also recently finished the "Head Fist SQL" book which was written very well.
So today I have been studying the Decorator Pattern. Wiki defines it as follows: "In object-oriented programming, the decorator pattern is a design pattern that allows new/additional behaviour to be added to an existing object dynamically". Basically what it allows is for you to extend a class without being part of that "family". You create a Decorator class and then extend onto that class. Below is a simple example in PHP of the pattern
<?php
/
Example of Decorator Pattern in PHP
/
class ReadStr {
protected $str;
function construct($str) {
$this->str = $str;
}
function display() {
return $this->str;
}
}
class StrDecorator extends ReadStr {
protected $str;
protected $readStr;
function construct(ReadStr $readStr) {
$this->readStr = $readStr;
$this->str = $this->readStr->display();
}
function display() {
return $this->str;
}
}
class StrToUpperDecorator extends StrDecorator {
private $strDecorator;
function construct(StrDecorator $strDecorator) {
$this->strDecorator = $strDecorator;
$this->stringToUpper();
}
function stringToUpper() {
$this->strDecorator->str = strtoupper($this->strDecorator->str);
}
}
class StrReverseDecorator extends StrDecorator {
private $strDecorator;
function construct(StrDecorator $strDecorator) {
$this->strDecorator = $strDecorator;
$this->stringReverse();
}
function stringReverse() {
$this->strDecorator->str = strrev($this->strDecorator->str);
}
}
$readStr = new ReadStr('Decorator Pattern!');
$decorator = new StrDecorator($readStr);
echo $decorator->display() . "\n";
$strToUpper = new StrToUpperDecorator($decorator);
echo $decorator->display() . "\n";
$strReverse = new StrReverseDecorator($decorator);
echo $decorator->display();
So today I was reading up on some SQL injection techniques, and came across one that I had not seen before. I found out that it is possible to use a UNION SELECT with the built-in MYSQL LOADFILE function, to read the contents of any file on the system. This only works if the user has been granted permission to use the LOADFILE function, and of course MYSQL DAEMON must have permission to read the file. Also, I found out that the LOADFILE function can read use with HEX decimal characters.
Example Injection: www.example.com/article.php?id=1+union+select+LOADFILE(0x2f6574632f706173737764)
This will return the contents of the /etc/passwd on a linux machine.
I also came across a handy perl script today that will encode a given string into HEX.
Perl HEX converter:
Note: There is a underscore between LOAD and FILE.
print "Enter string to encode:";
$str=<STDIN>;chomp $str;
$enc = encode($str); print "Hex Encoded value: 0x$enc\n";
sub encode{ #Sub to encode
@subvar=@;
my $sqlstr =$subvar[0];
@ASCII = unpack("C*", $sqlstr);
foreach $line (@ASCII) {
$encoded = sprintf('%lx',$line);
$encodedcommand .= $encoded;
}
return $encoded_command;
}
Today I wrote a command line PHP mail script. You are able to do this manually with programs such as Netcat or Telnet, but this just makes it easier and quicker. Once you run the script from the command line it will ask you for the host, recipient, email to mail from, subject, and message. This can be used quickly to test out a mail server.
<?php
if ($argc > 1) {
echo "This script does not take any arguments.\n";
exit;
}
function read ($length='255') {
if (!isset ($GLOBALS['StdinPointer'])) {
$GLOBALS['StdinPointer'] = fopen ("php://stdin","r");
}
$line = fgets ($GLOBALS['StdinPointer'],$length);
return trim ($line);
}
echo "\n";
echo "Enter Mail Server IP Address: ";
$host = read(30) . "\n";
echo "RCPT: ";
$rcpt = read(40) . "\n";
echo "Mail From: ";
$from = read(40) . "\n";
echo "Subject: ";
$subject = read(25) . "\n";
echo "Message: ";
$message = read(500) . "\n";
if ( (strlen($host) < 5) || (strlen($rcpt) < 10) ||
(strlen($from) < 10) || (strlen($subject) < 2) ||
(strlen($message) < 5) ) {
echo "You need to enter all fields properly.\n";
exit;
}
$fp = fsockopen($host,25,$errstr,$errno,100);
if (!$fp) {
echo "$errstr ($errno)";
} else {
$out = "helo h4x0r\r\n";
$out .= "mail from:$from\r\n";
$out .= "rcpt to:$rcpt\r\n";
$out .= "data\r\n";
$out .= "Subject:$subject\r\n\r\n";
$out .= "$message\r\n.\r\n";
fwrite($fp, $out);
fclose($fp);
}
?>
This is a simple script I wrote to do GET/OPTIONS/HEAD requests to a website. It's a command line PHP script which uses fsockopen to connect to the server. This comes in handy when you need to see headers received from a website. Also, it's good to see what is returned by the OPTIONS directive.
<?php
if ($argc < 4) {
echo "
---------------------------------------------------\n
HTTP Check Headers Script (Written by Tully Rankin)\n
Usage: headers.php [site] [get|head|options] file\n
Example: headers.php www.example.com get /\n
---------------------------------------------------
";
exit;
} else {
$site = $argv[1];
}
$request = strtolower($argv[2]);
$file = $argv[3];
if ($request == "get") {
$out = "GET $file HTTP/1.1\r\n";
$out .= "Host: $site\r\n";
$out .="Connection: Close\r\n\r\n";
} else if ($request == "options") {
$out = "OPTIONS $file HTTP/1.1\r\n";
$out .= "Host: $site\r\n";
$out .="Connection: Close\r\n\r\n";
} else if ($request == "head") {
$out = "HEAD $file HTTP/1.1\r\n";
$out .= "Host: $site\r\n";
$out .="Connection: Close\r\n\r\n";
} else {
echo "Incorrect Request Type\n";
exit;
}
$fp = fsockopen($site,80,$errstr,$errno,30);
if (!$fp) {
echo "$errstr ($errno)";
} else {
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 1024);
}
fclose($fp);
}
?>
This is a script I wrote to go through a list of URLS and return the Server Response code. This can be used to look for site vulnerabilities such as hidden directories. This example only has a few pages in the array. If you have a big list of common directories, the best way would be to have the script load those directories line by line from the file. Also, if you were looking for a particular response code you could either pipe the output to grep, or add the response code after the "HTTP/1.1" in the strstr function.
<?php
$host = "www.google.com";
$port = 80;
$pages = array("/cgi-bin","/admin","/test","/beta");
foreach ($pages as $page) {
$fp = fsockopen($host,$port,$errno,$errstr,30);
if (!$fp) {
echo "$errstr ($errno)";
} else {
$out = "GET $page HTTP/1.1\r\n";
$out.= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp,$out);
while (!feof($fp)) {
$data = fread($fp, 20);
if (strstr($data,'HTTP/1.1')) {
echo " Site: $host \n Page: $page \n Code: $data \n\n";
}
}
unset($data);
unset($out);
fclose($fp);
}
}
?>