View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0005467 | Kali Linux | New Tool Requests | public | 2019-05-29 14:11 | 2019-09-30 13:29 |
Reporter | altjx | Assigned To | |||
Priority | normal | Severity | major | Reproducibility | N/A |
Status | closed | Resolution | won't fix | ||
Product Version | 2019.2 | ||||
Summary | 0005467: [Tool Submission] Leprechaun - Post-exploitation tool to help identify valuable services and systems | ||||
Description | Leprechaun is a tool created by Alton Johnson (@altonjx) to help penetration testers identify valuable resources on an internal network penetration test. For example, when obtaining domain administrator with a tool such as Bloodhound, the user is able to run recursive netstat commands on multiple hosts and use Leprechaun to aggregate the results, spitting out a nice beautiful graph to display what connections are established within the environment. Essentially, they're able to map out the data flow. Reddit post: https://www.reddit.com/r/netsec/comments/bu2470/postexploitation_with_leprechaun_finding/ I also have a previous tool that was submitted in Kali, called iSMTP, in case that helps expedite the process for me. Thanks! Regards, | ||||
Steps To Reproduce | Simply run the command with the following arguments: ./leprechaun.rb -p 80 -f netstat_results.txt -t internal | ||||
Attached Files | leprechuan.rb (6,721 bytes)
just wanted to say i really appreciate being part of a good family here over the last 4 years. i'm officially moving to ATL in a little less than two weeks (planning on leaving out June 7th) to continue growing my business. i've been talking about it and wanting to for years, but now is the perfect time. with the additional of another full-time employee on my team, the pressure is on -- shit's about to get real, lol.#!/usr/bin/env ruby # # This tool was intended to be used during post-exploitation. # Essentially, once you have elevated privileges, you can run a recursive netstat # using tools such as winexe, smbexec, psexec, whatever., and parse it here. # # See the GitHub or blog page for more information. # # Author; Alton Johnson (@altonjx) # Company: Vonahi Security (@vonahi_security) # Created: 05/22/2019 # Version: 1.0 # ['securerandom','terminal-table','getopt/std'].each(&method(:require)) def help puts "\n " + "-" * 61 puts " \e[1;34mLeprechaun v1.0 - Alton Johnson (@altonjx)\e[0;00m" puts " " + "-" * 61 puts "\n Usage: #{$0} -f /path/to/netstat_results.txt -p <port>" puts "\n -f\tFile containing the output of netstat results." puts " -p\tPort you're interested in. e.g., 80. Specify \"all\", \"common\", or separate ports with commas" puts " -t\tThe type of destination IP addresses you want to see connections to (e.g. external/internal/all)." puts "\n Example: #{$0} -f netstat_output.txt -p 80" puts " Example: #{$0} -f netstat_output.txt -p all" puts " Example: #{$0} -f netstat_output.txt -p common" puts " Example: #{$0} -f netstat_output.txt -p 80,443 -t external" puts "\n" exit end PRIVATE_IPS = [ IPAddr.new('10.0.0.0/8'), IPAddr.new('172.16.0.0/12'), IPAddr.new('192.168.0.0/16'), ].freeze class Leprechaun def initialize(netstat_results, ports, ip_type) @servers = {} @clients = {} @dest_port_mappings = [] @source_port_mappings = [] @ip_type = ip_type @data = File.open(netstat_results).read.split("\n") if ports.include? "," @ports = ports.split(",") else @ports = ports end @digraph = "digraph {\n" @digraph += "\toverlap = false;\n\n" @digraph_headers = "\t# Servers and clients are defined here.\n" @digraph_data = "\t# Connections are defined here.\n" end def private_ip?(ip_address) if ip_address.is_a?(String) ip_address = IPAddr.new(ip_address) end PRIVATE_IPS.any? { |private_ip| private_ip.include?(ip_address) } end def parse_data @data.each do |line| routes = line.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}:\d+\b/) next if routes.empty? or routes.nil? begin source_ip = routes[0].split(":")[0] # source IP address source_port = routes[0].split(":")[1] # source port dest_ip = routes[1].split(":")[0] # destination IP address dest_port = routes[1].split(":")[1] # destination port rescue next end next if dest_ip == "0.0.0.0" # Skip depending on type of traffic the user wants. if @ip_type == "internal" next unless private_ip? dest_ip elsif @ip_type == "external" next if private_ip? dest_ip end protocol = (line.downcase.include?("tcp") ? "tcp" : "udp") well_known = [17,21,22,23,25,53,69,80,81,86,110,123,135,139,143,161,389,443,445,587,636,1311,1433,1434,1720,2301,2381,3306,3389,4443,47001,5060,5061,5432,5500,5900,5901,5985,5986,7080,8080,8081,8082,8089,8000,8180,8443] if @ports.include? "common" next unless well_known.include? dest_port.to_i end if [email protected]? "all" and [email protected]? "common" if [email protected]? dest_port next end end if @servers[dest_ip].nil? # avoid adding duplicate connections server_hex = SecureRandom.hex(2) @servers[dest_ip] = {:hex => "", :ports => {}, :client_count => 0} @servers[dest_ip][:hex] = "s#{server_hex}" @digraph_headers += "\t#{@servers[dest_ip][:hex]} [label = < <b>#{dest_ip}</b> >, fillcolor=gold3, fontcolor=white, style=filled, shape=egg];\n" end if @servers[dest_ip][:ports]["#{dest_port}/#{protocol}"].nil? @servers[dest_ip][:ports]["#{dest_port}/#{protocol}"] = {:clients => [], :client_count => 0} end unless @servers[dest_ip][:ports]["#{dest_port}/#{protocol}"][:clients].include? source_ip @servers[dest_ip][:ports]["#{dest_port}/#{protocol}"][:clients] << source_ip # add source IP @servers[dest_ip][:ports]["#{dest_port}/#{protocol}"][:client_count] += 1 @servers[dest_ip][:client_count] += 1 end if @clients[source_ip].nil? # avoid adding duplicate connections client_hex = SecureRandom.hex(2) @clients[source_ip] = "c#{client_hex}" @digraph_headers += "\t#{@clients[source_ip]} [label = \"#{source_ip}\", fillcolor=green3, style=filled];\n" end if @dest_port_mappings.include? [dest_ip, "#{dest_port}/#{protocol}"] unless @source_port_mappings.include? [source_ip, "#{dest_port}/#{protocol}"] @digraph_data += "\t\"#{@clients[source_ip]}\" -> \"#{dest_port}/#{protocol}\";\n" @source_port_mappings << [source_ip, "#{dest_port}/#{protocol}"] end else @dest_port_mappings << [dest_ip, "#{dest_port}/#{protocol}"] @source_port_mappings << [source_ip, "#{dest_port}/#{protocol}"] @digraph_data += "\t\"#{@clients[source_ip]}\" -> \"#{dest_port}/#{protocol}\" -> #{@servers[dest_ip][:hex]};\n" end end @digraph += "#{@digraph_headers}\n #{@digraph_data}" @digraph += "}" end def print_table # Most connected clients. headers = ['Server','Number of connected clients','Highest traffic destination port'] data = [] # server IP address, connected clients, connected ports @servers.each do |ip, server_values| connected_clients = server_values[:client_count] ports = [] # port, # of connected clients server_values[:ports].each do |port, port_values| ports << [port, port_values[:client_count]] end ports.sort {|a,b| a[1] <=> b[1]} data << [ip, connected_clients, ports[0]] end data = data.sort {|a,b| a[1] <=> b[1]}.reverse table = Terminal::Table.new do |t| t.add_row headers t.add_separator data.each do |line| t.add_row [line[0], line[1], "#{line[2][0]} (#{line[2][1]} connections)"] end end puts table end def write_to_file puts "\n [*] Completed! Graph output file located at: ./network_diagram.png\n\n" File.open("data.dot", "w") {|f| f.write(@digraph)} `sfdp -Tpng data.dot -o network_diagram.png -Grankdir=LR` end end if $0 == __FILE__ if ARGV.length == 0 help end opt = Getopt::Std.getopts("f:p:t:") fail "Please specify a netstat output file (-f) as well as a port (-p)." unless opt['f'] and opt['p'] opt['t'] = "all" if opt['t'].nil? lep = Leprechaun.new(opt['f'], opt['p'], opt['t']) lep.parse_data lep.write_to_file lep.print_table end | ||||
Some additional information (based on what I saw in another issue): To help speed up the process of evaluating the tool, please make sure to include the following information (the more information you include, the more beneficial it will for us): Name: Leprechaun
|
|
Thank you for the submission, however we haven't got the cycles to add this in |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2019-05-29 14:11 | altjx | New Issue | |
2019-05-29 14:11 | altjx | File Added: leprechuan.rb | |
2019-05-29 14:15 | altjx | Note Added: 0010638 | |
2019-09-30 13:29 | g0tmi1k | Status | new => closed |
2019-09-30 13:29 | g0tmi1k | Resolution | open => won't fix |
2019-09-30 13:29 | g0tmi1k | Note Added: 0011150 |