Greping strings from different lines of nmap output - awk

I have the following nmap output:
Nmap scan report for 192.168.1.14
Host is up (0.13s latency).
PORT STATE SERVICE VERSION
110/tcp closed pop3
--
Nmap scan report for 192.168.1.15
Host is up (0.13s latency).
PORT STATE SERVICE VERSION
110/tcp open pop3 Popper
--
Nmap scan report for 192.168.1.20
Host is up (0.13s latency).
PORT STATE SERVICE VERSION
110/tcp open pop3 Dove
which I get using the command: nmap -p 110 -sV 192.168.1.10-20
Note: I have not used the -oG output format with nmap because I understand that it is deprecated.
The output I require:
192.168.1.15 open Popper
192.168.1.20 open Dove
As you can see it should print the IP address, the State and Version of only the OPEN ports
What I have tried:
Using all sorts of variations (of the command below) using grep and awk to get my required output but cannot get it too work how I want it to:
nmap -p 110 -sV 192.168.1.10-20 | grep -B3 'open' | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}"
The difficulty I am having is how to extract specific parts from different lines of the output and put them together
Update
I have found that sometimes in the VERSION column there are more than just single words e.g sometimes it may say Popper 1.2.7-Beta rather than just Popper. In which case it then just prints 1.2.7-Beta instead of Popper 1.2.7-Beta (because the space between the words confuses it). How would you deal with this occurring?

Try this:
awk '/Nmap scan report/ { host=$NF } NF==4 && $2=="open" { print host, $2, $NF }' nmap-output.txt
Explanation:
1) For any line that matches the string "Nmap scan report", remember the last field of the line in the variable name "host"
2) For any line that has 4 fields and where the second field matches the string "open", print the remembered "host" variable, the second field of this line ("open"), and the last field of the line (what is in the Version column).

How about this awk:
awk '/^Nmap/{a=$5}
/^110\/tcp open/{print a,$2,$3}' Your_file

Related

How to present multiple greps as if they were in different columns?

Let's say.
I have one file with the name of the computer and some other information.
E.g.
Computer1
There's another file with the ip address and some other information.
192.168.100.2
I have 2 greps for example:
grep -i computer /etc/hosts
grep -i ips /etc/hosts
They give me answers like
Computer1
19.168.100.2
Well, I would like to get a file with headers and the information organized as this:
Name
Ip
oser1313
19.168.100.1
I'm quite lost I have no idea how could I format this I usually copy-paste it on Excel but I don't want to do it anymore and since I have to do this on several computers from a server It would be great if I can format it.
Just do something like this:
awk '
{ lc = tolower($0) }
lc ~ /computer/ { name = $0 }
lc ~ /ips/ { ip = $0 }
END {
print "Name", "Ip"
print name, ip
}
' /etc/hosts
The above is untested since you didn't provide a sample input file to test with and it's just mimicing what your grep commands do but there may be a better way to do it if we knew what your input looked like.
I suppose that your two files have the same number of lines and that line numbers match between one file and the other: if oser1313 is line n in the output of grep from /etc/hosts then same for 19.168.100.1 in /etc/hosts.
So it turns pretty simple as bash script:
grep -i computer /etc/hosts > part1.dat
grep -i ips /etc/hosts > part2.dat
echo "Name,IP" > out.dat
paste -d"," part1.dat part2.dat >> out.dat
rm part1.dat part2.dat
Or a oneliner, as suggested in comments:
printf "Name,IP\n$(grep -i computer /etc/hosts),$(grep -i ips /etc/hosts)\n" > out.dat

Get Top 50 IPs from access.log including IPV6

I often use this to check website access logs by IP address. The problem is that it only includes IPV4 and not IPV6.
Any idea what regex I can use so that it includes (or runs a separate) command for IPV6?
cat access.log | sed -e 's/^\([[:digit:]\.]*\).*"\(.*\)"$/\1 \2/' | sort -n | uniq -c | sort -nr | head -50
Matching IP addresses via regular expressions can be tricky - yours matches lots of things that aren't valid IPv4 addresses, like 100000.55, for example.
There's a perl module, Regexp::Common that provides well tested regular expressions for matching all sorts of things, including both IPv4 and IPv6 addresses. If you install it (The Ubuntu package is libregexp-common-perl), you can replace the sed part of that pipeline with
perl -MRegexp::Common=net -lne '/^($RE{net}{IPv4}|$RE{net}{IPv6}).*"(.*)"$/ && print "$1 $2"'
to match both address families.

How can I remove a Host entry from an ssh config file?

The standard format of the file is:
Host example
HostName example.com
Port 2222
Host example2
Hostname two.example.com
Host three.example.com
Port 4444
Knowing the host's short name, I want to remove an entire entry in order to re-add it with new details.
The closest I have got is this, except I need to keep the following Host declaration and the second search term will capture two many terms (like HostName):
sed '/Host example/,/\nHost/d'
With GNU sed:
host="example"
sed 's/^Host/\n&/' file | sed '/^Host '"$host"'$/,/^$/d;/^$/d'
Output:
Host example2
Hostname two.example.com
Host three.example.com
Port 4444
s/^Host/\n&/: Insert a newline before every line that begins with "Host"
/^Host '"$host"'$/,/^$/d: delete all lines matching "Host $host" to next empty line
/^$/d: clean up: delete every empty line
My final solution (which is somewhat OSX orientated) was this. It's largely based on Cyrus' earlier answer.
sed < $SOURCE "/^$/d;s/Host /$NL&/" | sed '/^Host '"$HOST"'$/,/^$/d;' > $SOURCE
This is more resilient to HostName directives which aren't indented.

how can I filter nmap results for multiple strings and output to file?

2I wanted to get a host list of linux servers on my network using nmap, but I'm not sure how to filter the results based on multiple strings. So I'm using something like:
nmap -sT -R --dns-servers 192.168.1.1,192.168.1.2 -p 22 192.168.1.0/24
which gives me the results but of course it's also showing every IP with the closed ports. How can I use logic with awk so that if it finds an IP with a hostname AND finds that the lines below have 'tcp open' it will spit those two lines to an output file?
The typical input to use from nmap would look like:
Interesting ports on server.domain.com (192.168.1.1):
PORT STATE SERVICE
22/tcp open ssh
Interesting ports on server2.domain.com (192.168.1.2):
PORT STATE SERVICE
22/tcp closed ssh
but this would be for every single IP that is scanned, so I'm trying to find a way to have a file with only the hostname and IP "if" it shows as 'tcp open' from the nmap command above. Basically giving you a file with:
server.domain.com (192.168.1.1)
So that I only get the server name and IP if SSH is actually listening on port 22
Based on the sample input and the sample output posted, something like this could work:
awk '/^Interesting/ {
domain = $(NF-1)
ip = substr($NF, 0, length($NF) - 1)
}
$2 == "open" {print domain, ip}' file
This works like this:
If a line starts with "Interesting", then the second to last field is stored as the domain, and the last field (minus the trailing colon) is stored as the ip.
If it finds a line where the second token is "open", then it prints the domain and ip found previously.

Nmap output format ip:port

I need load ip list from file, scan it, and create output format such as ip:port. I tried this:
nmap -iL mylistwithip.txt -p 80,21 -oG -PS 80,21 | awk '/open/{print $2}' >` output.txt
but it gives me only "open" and that's all.
While I need only opened ports from list of IP addresses, for example:
192.168.2.1
192.168.2.2
192.168.2.3
after scan ports, sample output.txt:
192.168.2.1:80
192.168.2.1:21
192.168.2.3:80
(only scanned ip addresses with opened ports)
Try this awk oneliner:
nmap -Pn -oG - 192.168.1.1 | awk '/open/{ s = $2; for (i = 5; i <= NF-4; i++) s = substr($i,1,length($i)-4) "\n"; split(s, a, "/"); print $2 ":" a[1]}'
try one more solution with single awk only.
nmap -vv -iL file | awk -F'[ /]' '/Discovered open port/{print $NF":"$4}'
Quick and ugly hack to achieve that:
nmap -vv -iL mylistwithip.txt | grep "Discovered open port" | awk {'print $6":"$4'} | awk -F/ {'print $1'} > output.txt
With -vv output includes lines like
Discovered open port 22/tcp on 192.168.2.1
Discovered open port 80/tcp on 192.168.2.1
Discovered open port 22/tcp on 192.168.2.107
Discovered open port 80/tcp on 192.168.2.107
First awk selects "ip address" and "port number/protocol" fields, and second cuts off "/protocol".
This will probably break in some future update of nmap. Using -sG (greppable output) would be a better idea.