Initial commit. - honeypot - A custom version of kippo used for SSH honeypot analysis and reporting.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 03dc4267c9106f78667c8cefba995d4f74d643b4
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Sat,  1 Sep 2018 22:18:53 +0100
       
       Initial commit.
       
       Diffstat:
         A README                              |      51 +++++++++++++++++++++++++++++++
         A blacklist.rb                        |      49 +++++++++++++++++++++++++++++++
         A current-charts.rb                   |      99 +++++++++++++++++++++++++++++++
         A dump.php                            |      37 +++++++++++++++++++++++++++++++
         A report.php                          |     250 +++++++++++++++++++++++++++++++
         A snippets.php                        |      76 +++++++++++++++++++++++++++++++
       
       6 files changed, 562 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -0,0 +1,51 @@
       +
       +      __        ___      __   __  ___ 
       +|__| /  \ |\ | |__  \ / |__) /  \  |  
       +|  | \__/ | \| |___  |  |    \__/  |  
       +                                      
       +
       +---
       +
       +
       +This is the source code I used for my honeypot project. A lot of it is
       +hacked together but hopefully someone will find it useful! To get the
       +Ruby scripts to work you will need to install mysql and gruff gems.
       +
       +
       +        $ gem install mysql
       +        $ gem install gruff
       +
       +
       +The script to report an IP address uses PEAR mail but this is actually
       +not needed, I only used it to send mail via gmail. You can simply 
       +change this to PHP's mail() function.
       +
       +
       +> blacklist.rb
       +
       +Generates list of IP's that have been carrying out SSH attacks, useful
       +for creating blacklists for IPTables, IOS etc
       +
       +
       +> report.php
       +
       +Gets the IP address from the kippo DB and reports the IP for abuse if
       +certain conditions are met. Then saves the information to a 'report'
       +table for displaying the information at a later date.
       +
       +
       +> dump.php
       +
       +This was used to output the UML blobs in the Kippo DB to a file to be
       +read by ajaxterm.
       +
       +
       +> current-charts.rb
       +
       +Ruby script I used to create the graphs for the front page.
       +
       +
       +> snippets.php
       +
       +This is just wee snippets of code I used through-out my code that
       +I think might be useful to some people :-)
 (DIR) diff --git a/blacklist.rb b/blacklist.rb
       @@ -0,0 +1,49 @@
       +#!/usr/bin/ruby
       +
       +
       +require 'rubygems'
       +require 'mysql'
       +
       +# Set the dates we want to start at
       +date = Time.new
       +
       +# Change pass to your password.
       +con_kippo = Mysql.new('localhost', 'kippo', 'pass', 'kippo')
       +
       +rs_list = con_kippo.query("SELECT ip
       +                FROM sessions
       +                WHERE starttime LIKE '2011-#{date.month}%'
       +                GROUP BY ip
       +                ORDER BY ip")
       +
       +ip_list = Array.new
       +
       +while row = rs_list.fetch_row do
       +    ip_list.push row[0]
       +end
       +
       +rs_list.free
       +
       +# You may want to define the absolute path in the following code blocks.
       +File.open('ip-list.txt', 'w') do |f2|
       +  ip_list.each do|ip|
       +    f2.puts ip
       +  end
       +end
       +
       +File.open('ip-list-iptables.txt', 'w') do |f2|
       +  ip_list.each do|ip|
       +    f2.puts "iptables -A INPUT -s #{ip} -j LOG --log-prefix \"Blocked: JayScott-Honeypot \""
       +    f2.puts "iptables -A INPUT -s #{ip} -j DROP"
       +  end
       +end
       +
       +File.open('ip-list-cisco.txt', 'w') do |f2|
       +  ip_list.each do|ip|
       +    f2.puts "access-list 1 deny host #{ip}"
       +  end
       +  f2.puts "access-list 1 permit any"
       +end
       +
       +
       +con_kippo.close
 (DIR) diff --git a/current-charts.rb b/current-charts.rb
       @@ -0,0 +1,99 @@
       +#!/usr/bin/ruby
       +#
       +# Generates the current graph.
       +#
       +# gem install gruff
       +# gem install mysql
       +#
       +
       +require 'rubygems'
       +require 'gruff'
       +require 'mysql'
       +
       +# Set the dates we want
       +date = Time.new
       +current_date = "#{date.year}-0#{date.month}"
       +string_month = Date::MONTHNAMES[date.month]
       +
       +puts current_date
       +g = Gruff::Line.new("600x300")
       +g.title = "#{string_month} 2012 Attacks"
       +
       +# Set the font options
       +g.font = 'LiberationMono-Regular.ttf'
       +g.marker_font_size = 12
       +g.legend_font_size = 12
       +g.title_font_size = 12
       +
       +# Set the chart colours
       +@green    = '#339933'
       +@purple   = '#cc99cc'
       +@blue     = '#336699'
       +@yellow   = '#a21764'
       +@red      = '#ff0000'
       +@orange   = '#cf5910'
       +@black    = 'black'
       +@colors   = [@yellow, @blue, @green, @red, @black, @purple, @orange]
       +
       +# Set the chart look
       +g.legend_box_size = 12
       +g.marker_count = 12
       +g.line_width = 1
       +g.dot_radius = 2
       +g.theme = {
       +  :colors => @colors,
       +  :marker_color => '#aea9a9',
       +  :font_color => 'black',
       +  :background_colors => 'white'
       +}
       +
       +# Change the password to the kippo DB
       +con_kippo = Mysql.new('localhost', 'kippo', 'your-pass', 'kippo')
       +
       +rs_sensors = con_kippo.query("SELECT id, ip FROM sensors")
       +
       +while row_sensor = rs_sensors.fetch_row do
       +
       +  rs_current = con_kippo.query("SELECT DISTINCT DATE(starttime) AS Date, COUNT(*) AS Total
       +                                FROM sessions
       +                                WHERE starttime
       +                                LIKE '#{current_date}%'
       +                                AND sensor=#{row_sensor[0]}
       +                                GROUP BY Date
       +                                ORDER BY Date")
       +
       +  attack_list = []
       +  total_attacks = 0
       +
       +  puts "Current sensor is #{row_sensor[1]}"
       +  puts "Number of rows #{rs_current.num_rows}"
       +  while row = rs_current.fetch_row do
       +    #puts "Row 1 = #{row[1]} Row 2 = #{row[0]}"
       +    attack_list  << row[1].to_i
       +    total_attacks = total_attacks + row[1].to_i
       +  end
       +
       +  #puts "Attack list is #{attack_list}"
       +
       +  if total_attacks > 0 then
       +    legend = "#{row_sensor[1]} (#{total_attacks})"
       +    g.data(legend, attack_list)
       +  end
       +
       +  rs_current.free
       +
       +end
       +
       +x = 0
       +days_list = {}
       +
       +while x < 31 do
       +  days_list[x] = "#{x +1}"
       +  x =  x + 1
       +end
       +
       +g.labels = days_list
       +g.write('current-month.png')
       +
       +con_kippo.close
       +
 (DIR) diff --git a/dump.php b/dump.php
       @@ -0,0 +1,37 @@
       +<?php
       +
       +/*
       + * Script that I ran on the cron to dump the .log files into a directory for
       + * ajax-term to read.
       + *
       + */
       +
       +# Change to your information.
       +$db = mysql_pconnect("localhost","kippo","your-password");
       +mysql_select_db("kippo",$db);
       +
       +# I found that if the log was < 85 there was normally no command issued.
       +$QUERY_TTY = mysql_query("SELECT id, session FROM ttylog WHERE LENGTH(ttylog) > 85");
       +
       +if($QUERY_TTY)
       +        echo "Query Complete\n";
       +else
       +        echo "Query Failed\n";
       +
       +$num_rows = mysql_num_rows($QUERY_TTY);
       +
       +echo "Rows = $num_rows \n";
       +echo mysql_error();
       +
       +# Change location-to-store-logs to where you want to store the Kippo log files e.g. /var/opt/webroot/logs
       +while($tty_row = mysql_fetch_array($QUERY_TTY)) {
       +  mysql_query("SELECT ttylog FROM ttylog WHERE id=" . $tty_row['id'] . " into dumpfile 'location-to-store-logs" . $tty_row['session'] . ".log'");
       +    if($tty_row){
       +      echo " Command is successful \n";
       +      echo "ttylog = " . $tty_row['id'] . "\n";
       +          }
       +    else
       +      echo " Command not successful \n";
       +}
       +
       +?>
 (DIR) diff --git a/report.php b/report.php
       @@ -0,0 +1,250 @@
       +<?php
       +
       +/*
       + * Gets the IP address from the kippo DB and reports the IP for abuse if certain
       + * conditions are met. Then saves the information to a 'report' table for
       + * displaying information at a later date.
       + *
       + * I still have debugging echo statements etc floating about :p
       + *
       + *
       + * report table - added to kippo database
       + *
       + * CREATE TABLE IF NOT EXISTS `report` (
       + * `id` int(11) NOT NULL AUTO_INCREMENT,
       + * `name` char(50) NOT NULL,
       + * `ip` varchar(15) NOT NULL,
       + * `contact` varchar(200) NOT NULL,
       + * `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
       + * `replied` tinyint(1) NOT NULL DEFAULT '0',
       + * `contacted` tinyint(1) NOT NULL DEFAULT '1',
       + * `notes` text NOT NULL,
       + * PRIMARY KEY (`id`)
       + * );
       + *
       + *
       + * Uses pears Mail script, this can be easily change to PHP's mail().
       + *
       + * pear install Mail
       + *
       + */
       +
       +error_reporting(0);
       +
       +require_once "Mail.php";
       +
       +function attackAttempts($id, $db)
       +{
       +  $result = mysql_query("SELECT COUNT(id) AS IPCOUNT FROM sessions WHERE ip ='" . $id . "'", $db) or die(mysql_error());
       +  if ($row = mysql_fetch_array($result))
       +    return (int) $row['IPCOUNT'];
       +}
       +
       +function attackSuccessful($id, $db)
       +{
       +  $result = mysql_query("SELECT auth.session, auth.success FROM auth
       +                                           INNER JOIN sessions ON auth.session = sessions.id
       +                         WHERE auth.success=1 AND sessions.ip='$id'");
       +
       +  $num_rows = (int) mysql_num_rows($result);
       +  return $num_rows;
       +}
       +
       +/* Change to your Kippo DB password */
       +$db = mysql_pconnect("localhost", "kippo", "yourpassword");
       +mysql_select_db("kippo", $db);
       +
       +$previous_date = date("Y-m-d", strtotime("-1 day"));
       +
       +$QUERY_ATTACKS = mysql_query("SELECT auth.session, auth.`timestamp`, MAX(sessions.starttime) AS MAXTIME, MIN(sessions.starttime) AS MINTIME,
       +                              sessions.ip, sessions.sensor
       +                              FROM auth INNER JOIN sessions ON auth.session = sessions.id
       +                              WHERE timestamp >= '$previous_date'
       +                              GROUP BY sessions.ip
       +                              ORDER BY auth.id ");
       +
       +while ($ROW_ATTACKER = mysql_fetch_array($QUERY_ATTACKS))
       +  {
       +    $IPADDRESS = $ROW_ATTACKER["ip"];
       +    $START     = $ROW_ATTACKER["MAXTIME"];
       +    $END       = $ROW_ATTACKER["MINTIME"];
       +    $SENSOR    = $ROW_ATTACKER["sensor"];
       +    $SESSION   = $ROW_ATTACKER["session"];
       +    $TIMESTAMP = $ROW_ATTACKER["timestamp"];
       +
       +    /* Already in the DB? dont report again */
       +    $IP_EXISTS = mysql_query("SELECT contacted FROM report WHERE ip='$IPADDRESS'");
       +
       +    if ($ROW_EXISTS = mysql_fetch_array($IP_EXISTS)) {
       +      continue;
       +    }
       +
       +    echo "IP = $IPADDRESS\n";
       +
       +    $attack_success = 0;
       +    $total_attacks = attackAttempts($IPADDRESS, $db);
       +    $attack_success = attackSuccessful($IPADDRESS, $db);
       +
       +    if ($total_attacks > 10 )
       +      echo "More than 10 attempts ($total_attacks) ($attack_success)\n";
       +    else if ($attack_success > 0)
       +        echo "Attack Success ($total_attacks) ($attack_success)\n";
       +    else {
       +      echo "Less than 10 attempts ($total_attacks) ($attack_success)\n";
       +      continue;
       +    }
       +
       +    $email = array();
       +
       +    unset($f);
       +    /* Shouldn't need to sanitise the IP address */
       +    exec("whois $IPADDRESS ", $f);
       +    unset($tmpname);
       +    unset($output);
       +
       +    foreach ($f as $output) {
       +      if (stripos($output, "netname:") === 0)
       +        $tmpname = explode(':',$output);
       +      else if (stripos($output, "owner:") === 0)
       +        $tmpname = explode(':',$output);
       +
       +      preg_match('/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i', $output, $matches);
       +
       +      $email[] = strtolower($matches[0]);
       +      $email = array_filter($email);
       +    }
       +
       +    $email = array_filter($email);
       +    $email = array_unique($email);
       +
       +    $EMAILS = implode(" ",$email);
       +    $NAME   = trim($tmpname[1]);
       +    $email_parts = explode(" ", $EMAILS);
       +
       +    foreach ($email_parts as $b_email) {
       +
       +      $EMAIL_ABUSE = 0;
       +      $tmp_username = substr($b_email, 0, strpos($b_email, '@'));
       +      $tmp_username = strtolower($tmp_username);
       +      if ( $tmp_username == "abuse" || $tmp_username == "support") {
       +        $EMAIL_ABUSE = 1;
       +        $EMAILS = $b_email;
       +      }
       +    }
       +
       +    if (empty($email)) {
       +      $INSERT_REPORT = mysql_query("INSERT INTO report (name, ip, contact, contacted, date) VALUES ('$NAME', '$IPADDRESS','', 0, '$TIMESTAMP')");
       +      continue;
       +    } else {
       +        $INSERT_REPORT = mysql_query("INSERT INTO report (name, ip, contact, date) VALUES ('$NAME', '$IPADDRESS','$EMAILS', '$TIMESTAMP')");
       +    }
       +
       +    unset($to);
       +    $parts = explode(" ", $EMAILS);
       +    if (sizeof($parts) == 1)
       +      $to = rtrim($parts[0],'.');
       +    else {
       +      foreach ($parts as $send_cc) {
       +        $send_cc = rtrim($send_cc,'.');
       +        $to .= "$send_cc,";
       +      }
       +
       +      $to = substr($to, 0, -1);
       +    }
       +    echo "TO = $to";
       +
       +    /* Kippo stored the IP of the sensor as a name in the 'sensors' table, get
       +     * the sensor ID and then identify IP.
       +     */
       +    switch ($SENSOR)
       +    {
       +      case 1:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 2:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 3:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 4:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 5:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 6:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 7:
       +        $TARGET = "ip-removed";
       +        break;
       +      case 8:
       +        $TARGET = "ip-removed";
       +        break;
       +    }
       +
       +    /* My SMTP information, change to yours or remove and add the default
       +    PHP mail() command */
       +    $host = "ssl://smtp.gmail.com";
       +    $port = "465";
       +    $username = "";
       +    $password = '';
       +
       +    $subject = "SSH attack from $IPADDRESS";
       +    $from    = 'jay@jayscott.co.uk';
       +    $headers = "From: $from \r\n" . "Reply-To: $from \r\n";
       +
       +    $message = "To abuse/support,";
       +
       +    if ($EMAIL_ABUSE = 0) {
       +        $message .= "
       +
       +  Please note I could not find a abuse or support email address in an
       +  WHOIS lookup.";
       +    }
       +
       +  $message .= "
       +
       +  I run a honeypot network that reports any attacking IP address or
       +  successful logins from unauthorised IP address.
       +
       +  The IP $IPADDRESS first gained access or attempted to access the
       +  honeypot on $START GMT against the IP address $TARGET.";
       +
       +  $message .= "
       +
       +  It maybe that $IPADDRESS has been compromised, is an active
       +  participant in a botnet or is being used as a SSH tunnel.
       +
       +  You may wish to monitor the IP Address. You can view more details about
       +  the attack such as any more attacks carried out, amount of attacks and
       +  even watch the attack if they successfully logged in here:
       +
       +  http://honeypot.jayscott.co.uk/ip/$IPADDRESS
       +
       +  If you would like any advice or require further information please
       +  feel free to contact me, jay@jayscott.co.uk.
       +
       +  Regards,
       +  Jay Scott";
       +
       +    $headers = array ('From' => $from,
       +        'To' => $to,
       +        'Subject' => $subject);
       +    $smtp = Mail::factory('smtp',
       +        array ('host' => $host,
       +            'port' => $port,
       +            'auth' => true,
       +            'username' => $username,
       +            'password' => $password));
       +
       +   $mail = $smtp->send($to, $headers, $message);
       +
       +    if (PEAR::isError($mail)) {
       +        echo(" - " . $mail->getMessage() . "\n");
       +    } else {
       +        echo(" - Message sent\n\n");
       +    }
       +  }
       +?>
 (DIR) diff --git a/snippets.php b/snippets.php
       @@ -0,0 +1,76 @@
       +<?
       +
       +/*
       + * Various code snippets I used in pages through-out the project, didn't think
       + * there was much point in displaying all of the HTML etc.
       + */
       +
       +
       +/* === Get unique Malware links === */
       +
       +$QUERY_DOWNLOAD = mysql_query("SELECT input.input, input.timestamp, sessions.ip
       +                               FROM input INNER JOIN sessions
       +                               ON input.session = sessions.id
       +                               WHERE input.input LIKE '%wget%'
       +                               GROUP BY input.input
       +                               ORDER BY input.timestamp DESC ");
       +
       +while ($DOWNLOAD_ROW = mysql_fetch_array($QUERY_DOWNLOAD)) {
       +  if (strlen($DOWNLOAD_ROW['input']) > 8) {
       +
       +    $Date = strtotime($DOWNLOAD_ROW["timestamp"]);
       +    $myDate = date('D jS M, G:i:s', $Date);
       +
       +    $URL = htmlspecialchars($DOWNLOAD_ROW['input']);
       +
       +    echo "<tr><td>$myDate</td>
       +          <td>" . substr($URL, 5) . "</td></tr>";
       +  }
       +}
       +
       +
       +
       +/* === Get unique passwords === */
       +
       +$sql_date = mysql_real_escape_string($_GET['date']);
       +
       +if ($sql_date == 'all') {
       +  $previous_date = "2011-02-01"; /* date I started logging via sql */
       +} else if ($sql_date == 'week') {
       +  $previous_date = date("Y-m-d", strtotime("-7 day"));
       +} else if ($sql_date == 'month') {
       +  $previous_date = date("Y-m-d", strtotime("-30 day"));
       +} else {
       +  $previous_date = date("Y-m-d", strtotime("-1 day"));
       +}
       +
       +/* simply change password to username for username stats */
       +$query_passwords = mysql_query("SELECT COUNT(password) AS PCOUNT, password
       +                                FROM auth WHERE password <> ''
       +                                AND timestamp >= '$previous_date'
       +                                GROUP BY password
       +                                ORDER BY PCOUNT DESC LIMIT 20");
       +
       +
       +/* === Showing information on the attack === */
       +
       +$QUERY_CLIENT = mysql_query("SELECT version FROM clients
       +                             WHERE id = '$CLIENT'
       +                             LIMIT 1");
       +
       +$CLIENT_SEARCH = strtolower($ROWS_CLIENT['version']);
       +
       +  if (strpos($CLIENT_SEARCH, "putty"))
       +    echo "<b>Connected Manually</b> ";
       +  else if (strpos($CLIENT_SEARCH, "libssh"))
       +    echo "<b>Used a C scanner</b> ";
       +  else if (strpos($CLIENT_SEARCH, "winscp"))
       +    echo "<b>Used WinSCP</b> ";
       +  else if (strpos($CLIENT_SEARCH, "openssh"))
       +    echo "<b>Connected Manually</b> ";
       +  else if (strpos($CLIENT_SEARCH, "nmap"))
       +    echo "<b>NMap Scan</b> ";
       +
       +
       +
       +?>