projectvoip

VOIP honeypot using Asterisk as the backend.
git clone git://git.beardyjay.co.uk/projectvoip
Log | Files | Refs | README

commit 9b1362c537aa9444dc0cde478859b65250f2ede1
Author: Jay Scott <jay@beardyjay.co.uk>
Date:   Mon, 18 Aug 2014 19:58:21 +0100

Uploaded again.

Diffstat:
AREADME | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrontab | 3+++
Aextensions.conf | 24++++++++++++++++++++++++
Aproject-voip.rb | 242+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asip.conf | 21+++++++++++++++++++++
Avoip.sql | 49+++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 392 insertions(+), 0 deletions(-)

diff --git a/README b/README @@ -0,0 +1,53 @@ + + +http://projectvoip.jayscott.co.uk + + +Project VOIP +============= + + +Project VOIP was meant to be a VOIP honeypot but I havent had much time to +develop it so I am uploading everything I have so far here :-) + +Project VOIP is based on phorensix v.1 by J. Oquendo / sil @ infiltrated dot net. + +Phorensix was scripted in bash and logged all information to a series of files. +Project VOIP is coded in Ruby has been updated to work with the latest version of +asterisk and also logs all information to a MySQL database. + +Jay Scott <jay@jayscott.co.uk> + + +What it does +------------ + +-> Logs the following information to a mysql database: + -> IP Address information + -> Peer(s) AS Number + -> Netblock AS Number + -> Netblock Prefix + -> AS Name + -> AS Country + -> AS Domain name + -> ISP Name + -> Number called + -> SIP Agent + -> SIP Channel used. + -> Traceroute of the IP Address + -> Packet capture of the session (.cap file) + -> Recording of the call (.wav) + +Installing +---------- + +Install Tshark and ruby gems if not installed already + + - apt-get install tshark rubygems mysql-client libmysqlclient-dev + +Install the ruby gem files for mysql + + gem install mysql + +Use the configs below as a template, changing the values as appropriate + diff --git a/crontab b/crontab @@ -0,0 +1,3 @@ +# Dump the .cap and .wav every 18 mins - dirty hack + +*/18 * * * * /usr/bin/ruby -w /home/jay/project-voip.rb -d 1 2>&1 diff --git a/extensions.conf b/extensions.conf @@ -0,0 +1,24 @@ +[general] + +static=yes +writeprotect=no +clearglobalvars=yes +autofallthrough=yes + +[project-voip] + +exten => _X.,1,Set(CTIME=${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}) +exten => _X.,n,system(/usr/bin/ruby /home/jay/project-voip.rb -i ${SIPCHANINFO(peerip)} -w /opt/project-voip/wav/${CTIME}.wav -c ${CHANNEL} -e ${EXTEN} -u '${SIPCHANINFO(useragent)}' &) +exten => _X.,n,Answer +exten => _X.,n,Wait(1) +exten => _X.,n,Playtones(ring) +exten => _X.,n,Wait(5) +exten => _X.,n,StopPlaytones +exten => _X.,n,Playback(press-pound-to-login-star-to-hangup) +exten => _X.,n,Record(/opt/project-voip/wav/${CTIME}:wav,,,qk) +exten => _X.,n,Wait(1) +exten => _X.,n,Hangup + +[default] + +include => project-voip diff --git a/project-voip.rb b/project-voip.rb @@ -0,0 +1,242 @@ +#!/usr/bin/ruby + +=begin + +Project VOIP +============= + + +Project VOIP was meant to be a VOIP honeypot but I havent had much time to +develop it so I am uploading everything I have so far here :-) + +Project VOIP is based on phorensix v.1 by J. Oquendo / sil @ infiltrated dot net. + +Phorensix was scripted in bash and logged all information to a series of files. +Project VOIP is coded in Ruby has been updated to work with the latest version of +asterisk and also logs all information to a MySQL database. + +Jay Scott <jay@jayscott.co.uk> + + +What it does +------------ + +-> Logs the following information to a mysql database: + -> IP Address information + -> Peer(s) AS Number + -> Netblock AS Number + -> Netblock Prefix + -> AS Name + -> AS Country + -> AS Domain name + -> ISP Name + -> Number called + -> SIP Agent + -> SIP Channel used. + -> Traceroute of the IP Address + -> Packet capture of the session (.cap file) + -> Recording of the call (.wav) + +Installing +---------- + +Install Tshark and ruby gems if not installed already + + - apt-get install tshark rubygems mysql-client libmysqlclient-dev + +Install the ruby gem files for mysql + + gem install mysql + +Use the configs below as a template, changing the values as appropriate + + +Make sure and update the Mysql information!. + +=end + +require 'rubygems' +require 'optparse' +require 'mysql' + +BASE_DATA = "/opt/project-voip/data" +CRON_FILE = "/opt/project-voip/data/cron" +MYSQL_HOST = "" +MYSQL_USER = "" +MYSQL_PASS = "" +MYSQL_TABLE = "" +HONEYPOT_ID = "1" + +options = {} + +op = OptionParser.new do|opts| + + opts.banner = "Usage: ruby #{File.basename($0)} " + options[:ipaddress] = nil + options[:data] = nil + options[:useragent] = "Unknown" + options[:exten] = "Unknown" + options[:channel] = "Unknown" + + opts.on( '-i', '--ipaddress [IPADDRESS]', 'IP Address' ) do|i| + options[:ipaddress] = i + end + + opts.on( '-e', '--exten [EXTEN]', 'Phone number called ' ) do|e| + options[:exten] = e + end + + opts.on( '-c', '--channel [CHANNEL]', 'Channel passed by Asterisk' ) do|c| + options[:channel] = c + end + + opts.on( '-u', '--useragent [USERAGENT]', 'Callers user-agent' ) do|u| + options[:useragent] = u + end + + opts.on( '-w', '--wav [WAV FILE]', 'WAV file location' ) do|w| + options[:wav] = w + end + + opts.on( '-d', '--data', 'Upload Data Files to MySQL.' ) do + options[:data] = true + end + + opts.on( '-h', '--help', 'Display this screen' ) do + puts opts + exit + end + + opts.on("--version", "Show version") do + puts OptionParser::Version.join('.') + exit + end +end + +op.parse! + +# Get the options passed +ip_address = options[:ipaddress] +data_update = options[:data] +useragent = options[:useragent] +called_exten = options[:exten] +caller_channel = options[:channel] +wav_file = options[:wav] + +# No IP.. somethings wrong, exit :p +if !data_update.nil? + + File.open("#{CRON_FILE}").each_line{ |s| + arrayData = s.split(':') + file_id = arrayData[0] + file_cap = arrayData[1].strip + file_wav = arrayData[2].strip + + cf = File.new(file_cap, 'rb') + wf = File.new(file_wav, 'rb') + + cap_data = Mysql.escape_string(cf.sysread(cf.stat.size)) + wav_data = Mysql.escape_string(wf.sysread(wf.stat.size)) + + begin + con_info = Mysql.real_connect("#{MYSQL_HOST}", "#{MYSQL_USER}", "#{MYSQL_PASS}", "#{MYSQL_TABLE}") + rescue Mysql::Error => e + puts "Error code: #{e.errno}" + puts "Error message: #{e.error}" + puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate") + end + + con_info.query("UPDATE caller SET capture=\"#{cap_data}\", recording=\"#{wav_data}\" WHERE id='#{file_id}'") + + con_info.close + } + + puts "Updated" + File.delete("#{CRON_FILE}") + File.new("#{CRON_FILE}", "w") + exit(1) + +end + +# No IP.. somethings wrong, exit :p +if ip_address.nil? + exit(-1) +end + +# Set the dates we want +date = Time.new +current_date = date.strftime("%Y%m%d") +current_time = date.strftime("%H%M%S") +mysql_date = date.strftime("%H%M%S") + +cap_file = "#{BASE_DATA}/#{ip_address}-#{mysql_date}.cap" + +whois_info = Array.new +whois_data = `whois -h whois.pwhois.org #{ip_address}` +whois_info = whois_data.split("\n") + +# ip_address, origin_as, prefix, as_path, as_org_name, org_name, net_name, cache_date, lat, long, city, region, country +whois_info = whois_info.map do |x| + x.split(':')[1].strip +end + +traceroute_output = `traceroute -w 1 -m 25 -n #{ip_address} &` +packet_capture = `tshark -q -R \"ip.addr == #{ip_address}\" -w #{cap_file} -a duration:20 &` + +# Connect to MySQL DB. +begin + con_info = Mysql.real_connect("#{MYSQL_HOST}", "#{MYSQL_USER}", "#{MYSQL_PASS}", "#{MYSQL_TABLE}") +rescue Mysql::Error => e + puts "Error code: #{e.errno}" + puts "Error message: #{e.error}" + puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate") +end + +rs_check = con_info.query("SELECT * from information WHERE ip_address='#{ip_address}'") + +# If the IP is unique then create a new record for it. +if rs_check.num_rows == 0 + con_info.query("INSERT INTO information + (ip_address, asn, prefix, as_path, as_org_name, org_name, net_name, lat, lon, city, region, country, traceroute) + VALUES + ('#{ip_address}', '#{whois_info[1]}', '#{whois_info[2]}', '#{whois_info[3]}', '#{whois_info[4]}', '#{whois_info[5]}', '#{whois_info[6]}', '#{whois_info[8]}', '#{whois_info[9]}', '#{whois_info[10]}', '#{whois_info[11]}', '#{whois_info[12]}', '#{traceroute_output}')") +end + +d = DateTime.now + +# Insert the call information +con_info.query("INSERT INTO caller + (uid, number, agent, channel, timestamp, honeypot) + VALUES + ('#{ip_address}','#{called_exten}','#{useragent}','#{caller_channel}', '#{d.to_s}', '#{HONEYPOT_ID}')") + + +# This section dumps the wav and cap file information to a file to be read by +# cron. We cant upload the wav and cap file at the same time because you dont +# know if the call has finished so the wav and cap are still in progress. +# +# Asterisk cant reliably detect if a call has terminated, if it did we could +# call function to kill tshark and then update the DB with the file data then. +# +# PROBLEM: The cron could run just after this information has been saved or not +# finished processing and chop the data anyway +# +# meh.... need to ditch asterisk and just create my own sip server. + +# Get the ID of the record we just inserted. + +rs_id = con_info.query("SELECT MAX(id) AS MAXID FROM caller") + +while row = rs_id.fetch_row do + last_id = row[0] +end + +con_info.close + +if !File::file?(CRON_FILE) + cronFile = File.new("#{CRON_FILE }", "w") +end + +File.open("#{CRON_FILE}", "a") do |f| + f.puts "#{last_id}:#{cap_file}:#{wav_file}" +end diff --git a/sip.conf b/sip.conf @@ -0,0 +1,21 @@ +[general] +context=project-voip ; Default context for incoming calls +allowoverlap=no ; Disable overlap dialing support. (Default is yes) +udpbindaddr=0.0.0.0 ; IP address to bind UDP listen socket to (0.0.0.0 binds to all) +tcpenable=yes ; Enable server for incoming TCP connections (default is no) +tcpbindaddr=0.0.0.0 ; IP address for TCP server to bind to (0.0.0.0 binds to all interfaces) +srvlookup=yes ; Enable DNS SRV lookups on outbound calls +alwaysauthreject=no +allowguest=yes + + +[100] +username=100 +secret=100 +context=project-voip +type=friend +canreinvite=no +host=dynamic +qualify=1000 +mailbox=100 +allow=all diff --git a/voip.sql b/voip.sql @@ -0,0 +1,49 @@ + + +DROP TABLE IF EXISTS `caller`; +CREATE TABLE IF NOT EXISTS `caller` ( + `id` int(15) NOT NULL AUTO_INCREMENT, + `uid` varchar(15) NOT NULL, + `number` varchar(100) DEFAULT NULL, + `agent` varchar(100) DEFAULT NULL, + `channel` varchar(100) DEFAULT NULL, + `capture` longblob NOT NULL, + `recording` longblob NOT NULL, + `timestamp` datetime NOT NULL, + `dumped` int(1) NOT NULL DEFAULT '0', + `honeypot` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `uid` (`uid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +DROP TABLE IF EXISTS `information`; +CREATE TABLE IF NOT EXISTS `information` ( + `id` int(15) NOT NULL AUTO_INCREMENT, + `ip_address` varchar(15) NOT NULL, + `asn` varchar(100) DEFAULT NULL, + `as_path` varchar(100) DEFAULT NULL, + `prefix` varchar(100) DEFAULT NULL, + `as_org_name` varchar(100) DEFAULT NULL, + `org_name` varchar(100) DEFAULT NULL, + `country` varchar(100) DEFAULT NULL, + `net_name` varchar(100) DEFAULT NULL, + `lon` float(10,6) DEFAULT NULL, + `lat` float(10,6) DEFAULT NULL, + `city` varchar(100) DEFAULT NULL, + `region` varchar(100) DEFAULT NULL, + `traceroute` varchar(400) DEFAULT NULL, + `reported` int(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `ip_address` (`ip_address`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +DROP TABLE IF EXISTS `report`; +CREATE TABLE IF NOT EXISTS `report` ( + `id` int(15) NOT NULL AUTO_INCREMENT, + `uid` varchar(15) NOT NULL, + `email` varchar(200) DEFAULT NULL, + `last_contact` datetime DEFAULT NULL, + `total_contact` int(2) DEFAULT NULL, + `reply` text, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1;