Skip to content

Commit f4800f8

Browse files
authored
Merge pull request #1937 from drwetter/fix_1935_3.0
Fix problem when nmap file has .txt extension (3.0)
2 parents ca558a9 + 29bd759 commit f4800f8

2 files changed

Lines changed: 154 additions & 31 deletions

File tree

testssl.sh

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19003,17 +19003,12 @@ nmap_to_plain_file() {
1900319003
else
1900419004
fatal "Nmap file $FNAME is not in grep(p)able format (-oG filename.g(n)map)" $ERR_FNAMEPARSE
1900519005
fi
19006-
# strip extension and create output file *.txt in same folder
19006+
# create ${FNAME%.*}.txt in $TEMPDIR
1900719007
target_fname="${FNAME%.*}.txt"
19008-
> "${target_fname}"
19009-
if [[ $? -ne 0 ]]; then
19010-
# try to just create ${FNAME%.*}.txt in the same dir as the gnmap file failed.
19011-
# backup is using one in $TEMPDIR
19012-
target_fname="${target_fname##*\/}" # strip path (Unix)
19013-
target_fname="${target_fname##*\\}" # strip path (Dos)
19014-
target_fname="$TEMPDIR/$target_fname"
19015-
> "${target_fname}" || fatal "Cannot create \"${target_fname}\"" $ERR_FCREATE
19016-
fi
19008+
target_fname="${target_fname##*\/}" # strip path (Unix)
19009+
target_fname="${target_fname##*\\}" # strip path (Dos)
19010+
target_fname="$TEMPDIR/$target_fname"
19011+
> "${target_fname}" || fatal "Cannot create \"${target_fname}\"" $ERR_FCREATE
1901719012

1901819013
# Line x: "Host: AAA.BBB.CCC.DDD (<FQDN>) Status: Up"
1901919014
# Line x+1: "Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 443/open/tcp//https///"

utils/gmap2testssl.sh

Lines changed: 149 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,170 @@
1-
#/bin/sh -e
1+
#!/usr/bin/env bash
22

3-
# utility which converts grepable nmap outout to testssl's file input
3+
#set -e
4+
5+
# Utility which converts grepable nmap outout to testssl's file input
6+
# It is just borrowed from testssl.sh
7+
# License see testssl.sh
8+
9+
10+
echo A | sed -E 's/A//' >/dev/null 2>&1 && \
11+
declare -r HAS_SED_E=true || \
12+
declare -r HAS_SED_E=false
413

514
usage() {
615
cat << EOF
716
817
usage:
918
10-
"$0 filename<.gmap>": looks for filename/filename.gmap and converts into basename \$(filename)-testssl.txt"
11-
"$0 filename<.gmap>" "scan option": same as before, only adds testssl.sh scan option in front of IPs"
19+
"$0 <filename>": looks for <filename> (nmap gmap format) and converts into basename \$(filename)-testssl.txt"
1220
1321
EOF
1422
exit 0
1523
}
1624

17-
[ -z "$1" ] && usage
18-
FNAME="$1"
19-
OPT2ADD="${2:-}"
25+
fatal () {
26+
echo "$1" >&2
27+
exit $2
28+
}
29+
30+
is_ipv4addr() {
31+
local octet="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"
32+
local ipv4address="$octet\\.$octet\\.$octet\\.$octet"
33+
34+
[[ -z "$1" ]] && return 1
35+
36+
# Check that $1 contains an IPv4 address and nothing else
37+
[[ "$1" =~ $ipv4address ]] && [[ "$1" == $BASH_REMATCH ]] && \
38+
return 0 || \
39+
return 1
40+
}
41+
42+
filter_ip4_address() {
43+
local a
44+
45+
for a in "$@"; do
46+
if ! is_ipv4addr "$a"; then
47+
continue
48+
fi
49+
if "$HAS_SED_E"; then
50+
sed -E 's/[^[:digit:].]//g' <<< "$a" | sed -e '/^$/d'
51+
else
52+
sed -r 's/[^[:digit:].]//g' <<< "$a" | sed -e '/^$/d'
53+
fi
54+
done
55+
}
56+
57+
# arg1: a host name. Returned will be 0-n IPv4 addresses
58+
# watch out: $1 can also be a cname! --> all checked
59+
get_a_record() {
60+
local ip4=""
61+
local noidnout=""
2062

21-
if ! grep -q gmap <<< "$FNAME"; then
22-
FNAME="$FNAME.gmap"
23-
fi
24-
[ ! -e $FNAME ] && echo "$FNAME not readable" && exit 2
63+
ip4=$(filter_ip4_address $(dig -r +short +timeout=2 +tries=2 -t a "$1" 2>/dev/null | awk '/^[0-9]/ { print $1 }'))
64+
if [[ -z "$ip4" ]]; then
65+
ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | awk '/address/ { print $NF }'))
66+
fi
67+
if [[ -z "$ip4" ]]; then
68+
ip4=$(filter_ip4_address $(drill a "$1" | awk '/ANSWER SECTION/,/AUTHORITY SECTION/ { print $NF }' | awk '/^[0-9]/'))
69+
fi
70+
echo "$ip4"
71+
}
2572

73+
ports2starttls() {
74+
local tcp_port=$1
75+
local ret=0
2676

27-
TARGET_FNAME=${FNAME%.*}-testssl.txt
77+
# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
78+
case $tcp_port in
79+
21) echo "-t ftp " ;;
80+
23) echo "-t telnet " ;;
81+
119|433) echo "-t nntp " ;; # to come
82+
25|587) echo "-t smtp " ;;
83+
110) echo "-t pop3 " ;;
84+
143) echo "-t imap " ;;
85+
389) echo "-t ldap ";;
86+
3306) echo "-t mysql " ;;
87+
5222) echo "-t xmpp " ;; # domain of jabber server maybe needed
88+
5432) echo "-t postgres " ;;
89+
563) ;; # NNTPS
90+
636) ;; # LDAP
91+
1443|8443|443|981) ;; # HTTPS
92+
465) ;; # HTTPS | SMTP
93+
631) ;; # CUPS
94+
853) ;; # DNS over TLS
95+
995|993) ;; # POP3|IMAP
96+
3389) ;; # RDP
97+
*) ret=1 ;; # we don't know this ports so we rather do not scan it
98+
esac
99+
return $ret
100+
}
28101

29-
# test whether there's more than one "open" per line
30-
while read -r oneline; do
31-
if [ $(echo "${oneline}" | tr ',' '\n' | grep -wc 'open') -gt 1 ]; then
32-
# not supported currently
33-
echo "$FNAME contains at least on one line more than 1x\"open\""
34-
exit 3
102+
nmap_to_plain_file () {
103+
104+
local fname="$1"
105+
local target_fname=""
106+
local oneline=""
107+
local ip hostdontcare round_brackets ports_specs starttls
108+
local tmp port host_spec protocol dontcare dontcare1
109+
110+
# Ok, since we are here we are sure to have an nmap file. To avoid questions we make sure it's the right format too
111+
if [[ "$(head -1 "$fname")" =~ ( -oG )(.*) ]] || [[ "$(head -1 "$fname")" =~ ( -oA )(.*) ]] ; then
112+
# yes, greppable
113+
if [[ $(grep -c Status "$fname") -ge 1 ]]; then
114+
[[ $(grep -c '\/open\/' "$fname") -eq 0 ]] && \
115+
fatal "Nmap file $fname should contain at least one open port" 250
116+
else
117+
fatal "strange, nmap grepable misses \"Status\"" 251
118+
fi
119+
else
120+
fatal "Nmap file $fname is not in grep(p)able format (-oG filename.g(n)map)" 250
35121
fi
36-
done < "$FNAME"
122+
target_fname="${fname%.*}"-testssl.txt
123+
[[ -e $target_fname ]] && fatal "$target_fname already exists" 3
124+
> "${target_fname}" || fatal "Cannot create \"${target_fname}\"" 252
125+
126+
# Line x: "Host: AAA.BBB.CCC.DDD (<FQDN>) Status: Up"
127+
# Line x+1: "Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 443/open/tcp//https///"
128+
# (or): Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 22/open/tcp//ssh//<banner>/, 25/open/tcp//smtp//<banner>/, 443/open/tcp//ssl|http//<banner>
129+
while read -r hostdontcare ip round_brackets tmp ports_specs; do
130+
[[ "$ports_specs" =~ "Status: " ]] && continue # we don't need this
131+
[[ "$ports_specs" =~ '/open/tcp/' ]] || continue # no open tcp at all for this IP --> move
132+
host_spec="$ip"
133+
fqdn="${round_brackets/\(/}"
134+
fqdn="${fqdn/\)/}"
135+
if [[ -n "$fqdn" ]]; then
136+
tmp="$(get_a_record "$fqdn")"
137+
if [[ "$tmp" == "$ip" ]]; then
138+
host_spec="$fqdn"
139+
fi
140+
fi
141+
while read -r oneline; do
142+
# 25/open/tcp//smtp//<banner>/,
143+
[[ "$oneline" =~ '/open/tcp/' ]] || continue # no open tcp for this port on this IP --> move on
144+
IFS=/ read -r port dontcare protocol ssl_hint dontcare1 <<< "$oneline"
145+
if [[ "$ssl_hint" =~ ^(ssl|https) ]] || [[ "$dontcare1" =~ ^(ssl|https) ]]; then
146+
echo "${host_spec}:${port}" >>"$target_fname"
147+
else
148+
starttls="$(ports2starttls $port)"
149+
[[ $? -eq 1 ]] && continue # nmap got a port but we don't know how to speak to
150+
echo "${starttls}${host_spec}:${port}" >>"$target_fname"
151+
fi
152+
done < <(tr ',' '\n' <<< "$ports_specs")
153+
done < "$fname"
154+
155+
[[ -s "$target_fname" ]] || fatal "Couldn't find any open port in $fname" 253
156+
echo "$target_fname written successfully"
157+
return 0
158+
}
159+
160+
161+
[[ -z "$1" ]] && usage
162+
FNAME="$1"
163+
[[ ! -e $FNAME ]] && echo "$FNAME not readable" && exit 2
164+
165+
nmap_to_plain_file $FNAME
37166

38-
awk '/\<open\>/ { print "'"${OPT2ADD}"' " $2":"$5 }' "$FNAME" | sed 's/\/open.*$//g' >"$TARGET_FNAME"
39167
exit $?
40168

41-
# vim:ts=5:sw=5
169+
# vim:ts=5:sw=5:expandtab
42170

0 commit comments

Comments
 (0)