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> ";
+
+
+
+?>