Nmap Development mailing list archives

Re: [NSE] ventrilo-info Ventrilo server version detection and info


From: Marin Maržić <marzic () gmail com>
Date: Fri, 07 Jun 2013 23:59:38 +0200

Hey, these replies (2 emails at the bottom of this) slipped past me.
Just came across them now half a year later when I was looking to post
some updates to those probes. Never too late?

The updated scripts keep the kind of portrules you seemed to like to use
(less likely to run). Also added some version probes that can be
controlled by rarity and act as a sort of "softmatch" for activating the
scripts. Should help some when the services run on arbitrary ports and
the scripts have such restrictive portrules set.

- murmur-version.nse
Now only sends and receives 1 packet when scanning the same port number
on the same host in both TCP and UDP (used to repeat for each protocol).

The "softmatch" probe:

Probe UDP Murmur q|\0\0\0\0abcdefgh|
rarity 9
ports 64738

match murmur m|^\0.{3}abcdefgh.{12}$|s p/Murmur/ v/1.2.X/

- ventrilo-info.nse
Now only sends and receives 1 packet when scanning the same port number
on the same host in both TCP and UDP (used to repeat for each protocol).
Various code improvements, bug fixes.

The "softmatch" probe follows. This one is encrypted and the
match can't really be matched on anything except that it should be at
least 111 bytes (conservative guess, should catch all).

Probe UDP Ventrilo
q|\x01\xe7\xe5\x75\x31\xa3\x17\x0b\x21\xcf\xbf\x2b\x99\x4e\xdd\x19\xac\xde\x08\x5f\x8b\x24\x0a\x11\x19\xb6\x73\x6f\xad\x28\x13\xd2\x0a\xb9\x12\x75|
rarity 9
ports 3784

match ventrilo m|^.{111}|s p/Ventrilo/ v/2.1.2+/

The UDP payload follows. It is a general status request with a 1 packet
reply:

# Ventrilo 2.1.2+
# UDP general status request (encrypted).
# See http://aluigi.altervista.org/papers.htm#ventrilo
udp 3784
"\x01\xe7\xe5\x75\x31\xa3\x17\x0b\x21\xcf\xbf\x2b\x99\x4e\xdd\x19\xac\xde\x08\x5f\x8b\x24\x0a\x11\x19\xb6\x73\x6f\xad\x28\x13\xd2\x0a\xb9\x12\x75"

- teamspeak2-version.nse
You mentioned that this could have been done with a version probe and a
couple match lines (and you were right!), but I have since found where
the precise version numbers are hidden in the binary blob response.
There is some information on the protocol at
http://wiki.wireshark.org/TeamSpeak2 but they haven't found the version
offsets. A normal login request is used.

The "softmatch" probe:
Probe UDP TeamSpeak2
q|\xf4\xbe\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x32\x78\xba\x85\x09\x54\x65\x61\x6d\x53\x70\x65\x61\x6b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x57\x69\x6e\x64\x6f\x77\x73\x20\x58\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x20\x00\x3c\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x6e\x69\x63\x6b\x6e\x61\x6d\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|
rarity 9
ports 8767

match ts2
m|^\xf4\xbe\x04\x00\x00\x00\x00\x00.............([^\0]+)[^\w\s]+([^\0]+)\0+[^\0].{355}$|s
p/TeamSpeak 2/ o/$2/ i/name: $1; no password/
match ts2 m|^\xf4\xbe\x04\x00\x00\x00\x00\x00............\0{60}.{356}$|s
p/TeamSpeak 2/ i|name: n/a; has password or version < 2.0.19.16 (very
unlikely)|

Examples of output:

PORT     STATE SERVICE VERSION
8767/udp open  ts2     TeamSpeak 2 (name: COWCLANS; no password)
Service Info: OS: Win32

PORT     STATE SERVICE VERSION
8767/udp open  ts2     TeamSpeak 2 (name: TeamSpeak Server; no password)
Service Info: OS: Linux

- TeamSpeak 2 nmap-payloads
The payload sent is the one used in the above script. It is a normal
login request and is not encrypted. Some information fields sent are in
ASCII, but it's in hex here because it was convenient to copy it like
that off the wire. I guess the description could be something like:

# TeamSpeak 2
# UDP login request
# See http://wiki.wireshark.org/TeamSpeak2

- TeamSpeak 2 TCP port service detection (the "TCPQuery" interface):
Here are 2 examples you asked for of what output looks like for the
suggested "ver" command:

2.0.23.19 Win32 Freeware
OK

2.0.24.1 Linux Freeware
OK

- TeamSpeak 2 TCP port service detection (the http web admin interface):
When I comment it out, the specific line matches. When I leave it
functional below or above the specific lines, it overrides. Weird?

- TeamSpeak 3 UDP probe and nmap-payloads
This is an encrypted login request packet copied off the wire. Think
there is no documentation on it. There seem to be some fields that echo
back what is sent, and some that are static when sent this exact
payload, so I match on them. Length varies. I guess the description
could be something like:

# TeamSpeak 3
# UDP login request (encrypted)

- TeamSpeak 3 TCP port service detection (the "ServerQuery" interface):
2 examples of what output looks like for the suggested "version" command:

version=3.0.6.1 build=1340956745 platform=Windows
error id=0 msg=ok

version=3.0.7.2 build=1368605352 platform=Linux
error id=0 msg=ok

- On another note, when I tried to make version scripts run for any as
of yet unidentified port (like normal probes would with --version-all),
it wasn't that straightforward. I came across this bit in
http://nmap.org/book/nse-api.html#nse-api-arguments:
"port.service
    Contains a string representation of the service running on
port.number as detected by the Nmap service detection. If the
port.version field is nil, Nmap has guessed the service based on the
port number. Otherwise version detection was able to determine the
listening service and this field is equal to port.version.name."

Thought that maybe the mentioned fields could help determine if it was a
guess or not, but this came up when testing (debug output at the start
of a portrule) the 4 possible combinations:

- port without an nmap-services entry, and no regex rule match:
NSE: port.service=nil
NSE: port.version=not nil
NSE: port.version.name=nil
NSE: port.version.name_confidence=3

PORT      STATE         SERVICE REASON      VERSION
62314/udp open|filtered unknown no-response

- port without an nmap-services entry, and there is a regex rule match:
NSE: port.service=murmur
NSE: port.version=not nil
NSE: port.version.name=murmur
NSE: port.version.name_confidence=10

PORT      STATE SERVICE REASON       VERSION
62314/udp open  murmur  udp-response Murmur 1.2.X

- port (80) with a nmap-services entry (http), and no regex rule match:
NSE: port.service=http
NSE: port.version=not nil
NSE: port.version.name=http
NSE: port.version.name_confidence=3

PORT   STATE         SERVICE REASON      VERSION
80/udp open|filtered http    no-response

- port (80) with a nmap-service entry (http), and there is a regex rule
match:
NSE: port.service=murmur
NSE: port.version=not nil
NSE: port.version.name=murmur
NSE: port.version.name_confidence=10

PORT   STATE SERVICE REASON       VERSION
80/udp open  murmur  udp-response Murmur 1.2.X

Some conclusions from this:
- port.version is never nil (guess or not)
- port.service and port.version.name are always equal (guess or not)
- port.version.name_confidence is never nil; it is 3 when a guess was
made and it is 3 even when no guess can be made, it is 10 on a match
- if a port number has an entry in nmap-services, port.service and
port.version.name will be set to it. This is why, for example, the Skype
version script can never work against port 80 (it's set to "http"), or
against any other port with an entry in nmap-services that isn't
"unknown" or "".

Then it seems that the following type of port rule would best emulate a
normal probe that runs on any open or open|filtered, and as of yet
unidentified port (udp in this case):
portrule = function(host, port)
    return port.version.name_confidence ~= 10
        and not shortport.port_is_excluded(port.number, "udp")
end

Guess I would have to add such a rule to all scripts if I wanted "true"
--version-all functionality (full Nmap version detecting power).

Marin


On 16.1.2013. 1:30, David Fifield wrote:> On Tue, Dec 18, 2012 at
03:30:19AM +0100, Marin Maržić wrote:
here's a service detection and info script for the Ventrilo voice
communication server service. If used as a normal script it prints out a
lot of the server status details. More info in the .nse.

Thank you, this is now committed in r30505 and following. I made some
changes to the documentation, and changed the port rule to make it less
likely to run. We don't yet have a good way to control the running of
version scripts like this, which target services that can be run against
arbitrary ports, but which we don't want to run for every open|filtered
port by default. In version probes we use the rarity, but there is no
equivalent notion for NSE scripts.

David Fifield


On 23.12.2012. 2:14, David Fifield wrote:> On Wed, Dec 19, 2012 at
07:59:51PM +0100, Marin Maržić wrote:
been working on improving TeamSpeak 2 and 3 server service detection and
here's what I came up with.

TeamSpeak 2 (2 TCP and 1 UDP port):

TCP port service detection (the "TCPQuery" interface):

- replaced match line (for the NULL probe):
match telnet m|^\[TS\]\r\n$| p/Teamspeak VoIP Information telnetd/
- with:
softmatch ts2-TCPQuery m|^\[TS\]\r\n$|

- and added probe:
Probe TCP verLine q|ver\r\n|
rarity 9
ports 51234

match ts2-TCPQuery m|^\[TS\]\r\n(\S+) (\S+) (\S+)\r\nOK\r\n$|
p/TeamSpeak 2 server TCPQuery interface (telnetd)/ v/$1/ i/$3/ o/$2/

- This improves the detection of the specific TS2 telnetd (they call it
the TCPQuery function) with additional information (more precise name,
specific version, some extra info and OS). Rarity 9 works great because
of the softmatch in the NULL probe so it doesn't slow down searches.

I applied the part to make a more specific match for the TCPQuery port.

Can you send some examples of verbatim responses sent in response to the
"ver" command? I want to see what kind of things are going in the info
field, and how the OS names are formatted. If there are multiple OS
strings, we usually like to break them into multiple match lines in
order to have different CPE.

TCP port service detection (the "ServerQuery" interface):

- replaced match lines (for the NULL probe):
match teamspeak m|^TS3\n\r$| p/TeamSpeak voice communication/ v/3/
match teamspeak m|^TS3\n\rWelcome to the TeamSpeak 3 ServerQuery
interface, type \"help\" for a list of commands and \"help <command>\"
for information on a specific command\.\n\r$| p/TeamSpeak voice
communication/ v/3/

- with:
softmatch ts3-ServerQuery m|^TS3\n\r$|
softmatch ts3-ServerQuery m|^TS3\n\rWelcome to the TeamSpeak 3
ServerQuery interface, type \"help\" for a list of commands and \"help
<command>\" for information on a specific command\.\n\r$|

- and added probe:
Probe TCP versionLine q|version\r\n|
rarity 9
ports 10011

match ts3-ServerQuery m|^TS3\n\r.*?version=(\S+) build=(\S+)
platform=(\S+)\n\rerror id=0 msg=ok\n\r$|s p/TeamSpeak 3 server
ServerQuery interface (telnetd)/ v/$1/ i/build: $2/ o/$3/

Same here, I applied the more specific matches, but please show some
example ooutput of the "version" command.

TCP port service detection (the http web admin interface):

- This one seemed to exist already in nmap-service-probes in the form of
2 match lines (for the NULL probe):
match http m|^HTTP/1\.1 \d\d\d .*\r\nConnection:
keep-alive\r\nContent-Type: text/HTML\r\nContent-Length: \d+\r\nServer:
Indy/([\d.]+)\r\nSet-Cookie: .*\r\n\r\n<!-- header\.html
-->.*TeamSpeak|s p/TeamSpeak admin httpd/ v/1.X/ i/Indy httpd $1/
match http m|^HTTP/1\.1 \d\d\d .*\r\nConnection:
keep-alive\r\nContent-Type: text/HTML\r\nContent-Length: \d+\r\nServer:
Indy/([\d.]+)\r\nSet-Cookie: .*<title>TeamSpeak 2 -
Server-Administration</title>|s p/TeamSpeak admin httpd/ v/2.X/ i/Indy
httpd $1/

- Unfortunately they never match because they are overriden by this line:
match http m|^HTTP/1\.1 200 OK\r\n.*Server: Indy/([\w._-]+)\r\n|s
p/Indy/ v/$1/

- not sure how this kind of stuff is usually fixed

This doesn't seem to be the case anymore in the current version of the
file. The Indy/TeamSpeak lines appear (in the GetRequest probe) above
any more generic Indy lines. Is it possible that the server output is
slightly different and now doesn't match the regular expressions?

- payload (nmap-payloads):
# TeamSpeak 2
udp 8767

"\xf4\xbe\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x32\x78\xba\x85\x09\x54\x65\x61\x6d\x53\x70\x65\x61\x6b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x57\x69\x6e\x64\x6f\x77\x73\x20\x58\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x20\x00\x3c\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x6e\x69\x63\x6b\x6e\x61\x6d\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

UDP port service detection (the voice/login/session port):

Probe UDP TeamSpeak3

q|\x05\xca\x7f\x16\x9c\x11\xf9\x89\x00\x00\x00\x00\x02\x9d\x74\x8b\x45\xaa\x7b\xef\xb9\x9e\xfe\xad\x08\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x3e\x00\x97\x2b\x1c\x71\xb2\x4e\xc0\x61\xf1\xd7\x6f\xc5\x7e\xf6\x48\x52\xbf\x82\x6a\xa2\x3b\x65\xaa\x18\x7a\x17\x38\xc3\x81\x27\xc3\x47\xfc\xa7\x35\xba\xfc\x0f\x9d\x9d\x72\x24\x9d\xfc\x02\x17\x6d\x6b\xb1\x2d\x72\xc6\xe3\x17\x1c\x95\xd9\x69\x99\x57\xce\xdd\xdf\x05\xdc\x03\x94\x56\x04\x3a\x14\xe5\xad\x9a\x2b\x14\x30\x3a\x23\xa3\x25\xad\xe8\xe6\x39\x8a\x85\x2a\xc6\xdf\xe5\x5d\x2d\xa0\x2f\x5d\x9c\xd7\x2b\x24\xfb\xb0\x9c\xc2\xba\x89\xb4\x1b\x17\xa2\xb6|
rarity 9
ports 9987

match ts3

m|^.{8}\x00\x00\x02\x97\x76\x8b\x54\xad\x79\xe3\xaf\x87\xeb\xaa\x1a\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x33\x08\x86\x2d\x40|s
p/TeamSpeak 3 server/

- not sure about the rarity here, won't get picked up on a default scan
with 9

- payload (nmap-payloads):
# TeamSpeak 3
udp 9987

"\x05\xca\x7f\x16\x9c\x11\xf9\x89\x00\x00\x00\x00\x02\x9d\x74\x8b\x45\xaa\x7b\xef\xb9\x9e\xfe\xad\x08\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x3e\x00\x97\x2b\x1c\x71\xb2\x4e\xc0\x61\xf1\xd7\x6f\xc5\x7e\xf6\x48\x52\xbf\x82\x6a\xa2\x3b\x65\xaa\x18\x7a\x17\x38\xc3\x81\x27\xc3\x47\xfc\xa7\x35\xba\xfc\x0f\x9d\x9d\x72\x24\x9d\xfc\x02\x17\x6d\x6b\xb1\x2d\x72\xc6\xe3\x17\x1c\x95\xd9\x69\x99\x57\xce\xdd\xdf\x05\xdc\x03\x94\x56\x04\x3a\x14\xe5\xad\x9a\x2b\x14\x30\x3a\x23\xa3\x25\xad\xe8\xe6\x39\x8a\x85\x2a\xc6\xdf\xe5\x5d\x2d\xa0\x2f\x5d\x9c\xd7\x2b\x24\xfb\xb0\x9c\xc2\xba\x89\xb4\x1b\x17\xa2\xb6"

For all these, we need some more information. We don't like having
undocumented binary blobs in the database. Do you have a link to
protocol documentation? What do these probes do? Where do they come
from? Check the comments above each payload in nmap-payloads; that's the
kind of information we need.

UDP port service detection (the voice/login/session port):

- Attached an NSE script for this one. More info in the .nse.

It looks like what this script does can be done with a version probe. It
just sends a static payload and then does a pattern match on the
returned value. A blank name, for example, would be handled with two
match lines. My above comments on documentation apply equally here;
please show some example output if possible.

David Fifield

Attachment: murmur-version.nse
Description:

Attachment: teamspeak2-version.nse
Description:

Attachment: ventrilo-info.nse
Description:

_______________________________________________
Sent through the dev mailing list
http://nmap.org/mailman/listinfo/dev
Archived at http://seclists.org/nmap-dev/

Current thread: