If we do not wish to fight, we can prevent the enemy from engaging us even though the lines of our
encampment be merely traced out on the ground. All we need do is to throw something odd and
unaccountable in his way. --Sun Tzu, The Art of War
OS fingerprinting is a process for determining the operating system a remote host computer is
running, based on characteristics of the data returned from the remote host. This can be as simple
as connecting up to the host and reading a service banner or as complex as statistical analysis of
TCP initial sequence numbers and flags. An outsider has the capability to discover general
information, such as which operating system a host is running, by searching for OS-specific
differences in implementation of the TCP stack. In some cases, these differences can reveal
information as detailed as the OS version number and processor architecture.
By pinpointing the exact OS of a host, an attacker can launch an educated and precise attack
against a target machine. In a world of buffer overflows, knowing the exact flavor of an OS and
architecture could be all the opportunity an attacker needs. By using software such as Netfilter
for Linux, an administrator can evade accurate OS-fingerprinting methods and in some cases even
manipulate the results gathered by the external force. While these practices should never be
considered a sound security solution, sometimes they can deter and even confuse a would-be
attacker if the host poses as an obscure network entity.
While fingerprint evasion does offer a nice layer of obscurity as to the actual OS a host is
running, it does not in any way secure the host from various vulnerabilities. Security practices
and policies attempt to raise the level of skill required to compromise the system, obscurity
only attempts to mask the actual target. Even if your system appears to be running Microsoft IIS5
to the world, this won't protect you if you are running a vulnerable version of let's say sendmail,
and some script kiddy's automated scanner attempts to exploit you. Fingerprint evasion is meant to
deter attacks, not prevent them.
Techniques for Discovery
Before attempting to dissuade a potential attacker through OS deception, one must familiarize
themselves with the tools and methods used in fingerprinting an OS. The term ``attacker'' here is
used loosely and encompasses those who would attempt to fingerprint a host or those who might have
the intentions of doing the system harm. Security has been, and in the writer's mind always will
be, a sequence of measure and counter-measure scenarios. By becoming accustomed to the tools and
methodologies available for this type of attack you cannot only prepare and plan for current
engagements, but also gain insight into what the future may have in store.
Several publicly available tools exist for attempting to fingerprint an OS. Of these tools, one
seems to be the popular choice: nmap (http://www.insecure.org/nmap/index.html) by Fyodor of
Insecure.org. nmap uses several techniques for attempting to determine the host operating system
from a network level, some of them primitive in their approach and others more complex, requiring
a good understanding of the TCP/IP protocol and protocol standards. Of the methods nmap
incorporates, some of the most notable are:
FIN Probing--by sending a packet to an open port on a host with nothing more than the FIN flag set
in the packet, an attacker can glean information from certain hosts that respond to the requests.
This behavior is non-RFC-compliant so it is a good indicator of OS.
TCP ISN Sampling--TCP packet ISN (initial sequence number) sampling can be a valuable way to
determine and categorize the remote host. By watching the ISNs for patterns an attacker can make
an educated guess as to the host OS.
ICMP Error Messaging--through the use of ICMP (internet control message protocol) error messages,
an attacker can find useful information based on the host responses. Particular areas of interest
are the checksums, error message echo integrity and TOS (type of service) fields in the reply
packets.
TCP Options--perhaps the most revealing aspect of any TCP stack is how it handles optional TCP
flags and data. By making specific requests to a host and varying window scales and segment sizes,
one can determine which operating system a host is running based on its willingness to accept or
respond with these optional parameters.
While all of these methods of OS fingerprinting are at the packet level, great care should be
taken to understand your system at a service level. An attacker could sort and compare packet
structures but will often simply query a web server for the ``Server'' field in the HTTP response
header. Knowing which services readily identify themselves, and more importantly the operating
system architecture, will show us other avenues that can be used for remote information retrieval.
Client modesty (or lack thereof) can be an excellent way to glean information from a host as well.
Unlike the other options, this process can be completely passive. By watching how a client
application presents itself to a service, you can make a reasonable guess at the operating system
and possibly the architecture. Of these clients, web browsers, e-mail clients and IRC (internet
relay chat) clients are most often the biggest offenders. If we were on IRC and requested a CTCP
version from a user, and received the reply of ``mIRC32 v5.81 K.Mardam-Bey'', we could make an
educated guess at this point that the host is running some form of the Windows operating system.
Finally, there is exploit testing. While less tactful, it can nevertheless be useful in discovering
the operating system of a host. By initiating a series of OS-specific denial-of-service attacks an
outsider can test to see if a host is vulnerable. This can determine which rating system a host is
running, usually down to the patch level. The Windows community should be grateful that Fyodor and
the other fingerprinting-tool authors didn't decide to incorporate this method into their usual
slew of scanning techniques.
Why Fingerprint Evasion?
If you have read up to this point, you are at least no doubt a little curious as to why one would
go to the trouble of OS fingerprint evasion. Good question! I think the logic here varies from
person to person. Everyone has his or her own reasons for wanting, or not wanting for that matter,
operating system obscurity.
For some, the extra layer of obscurity helps them feel fuzzy and warm inside. Like the people who
feel the need to remove the issue banner from their Telnet login screens, but resort to Telnet
rather than SSH for remote access security (obscure, but technically less secure). For others, the
notion of operating system obscurity at the network level allows them to fine-tune and tweak their
IDS (intrusion detection system) since they have a fairly good idea not only of what should be
coming into their network, but also of what data should be leaving it (obscure, cautious and
hopefully secure). Some might even have a need for security, where every network they plug in to
is a potential hostile network; and the more obscure their operating system is, the bigger the
window of opportunity they have to complete whatever the task is at hand without being noticed
(obscure, cautious, secure and probably reading your e-mail). Finally, there are those of us who
do it for fun, because we can and because we get some small kick out of being able to fool the
unknown individuals around us who persist on launching scans in our direction (yes, guilty as
charged).
Evasion
Now it's time to try our luck at fingerprint evasion. Familiar with some of the common techniques
used in determining a host's operating system, we can reverse engineer these concepts to aid us in
hiding our operating identities.
First, we need to make sure that all patches are in place and the system is secured. As I stated
before, obscurity should only be entertained after security has been implemented. I'm sure some
would disagree here, relying solely upon obscurity for their means to a secured system, but what
good is obscurity if that script kid33's automated script gains root on your machine tonight? I'm
willing to bet once he has root access, what flavor of Linux you are running isn't on his or her
list of things to figure out.
Second, we need to observe our services. Do they match up with the operating system we are hoping
to pass ourselves off as using? In most cases this isn't as much of a concern since most UNIX
environments share similar if not the same services. But if you are hoping to present yourself as
a Windows machine, or even a Cisco router for that matter, it may not be to your advantage to show
up having IRCd running. Make an effort in matching up your services with a suitable decoy host.
While we're on the subject of services, it is also a good idea to begin greping through the source
code of these services looking for banners or common identifiers of the services. Some subtle
identifiers could be the supporting of ASP pages or web content that is served compressed in gzip
format. For most people this will be a lot of work. Again, it's up to you to gauge what level of
obscurity and conformity with your new decoy host you are trying to achieve.
Next, we need to look at how our host appears on a network vs. how our decoy host should look on a
network. To make this a little bit easier I suggest studying already documented materials, namely
the current fingerprint files used by the tools themselves. Time should be taken to note not just
how your decoy host responds to usual queries, but also what special flags it supports in TCP. TCP
flags are useful information for outsiders to determine what OS you are running. The fingerprint
files don't include all possible responses a host might give, just simple techniques that work
reproducibly. Depending on what level of obscurity you hope to achieve, it may be worth looking
into fingerprint information not used by nmap (OSPF, OOB, IPv6, etc.). Or the joy of thoroughness
could be outweighed by the sleepless nights you would spend gathering this information.
Finally, a decision needs to be made. Are you crafty, or are you paranoid? If you answer to the
latter, then you most likely want to continue by obfuscating your client software. As mentioned
above, a host's client software tends to give out all kinds of information regarding the system,
either directly or indirectly. In our previous example an IRC client lists itself as being for
Win32, but there are also more subtle ways of determining a host, such as reading the e-mail
headers of outgoing mail. Once again, it all comes down to how many sleepless nights you are
willing to spend before your system meets your criteria.
Potential Problems
OS fingerprint evasion is like any other aspect of security; it takes planning, proper execution
and most importantly, understanding. If security policies are not properly implemented, the system
could be more vulnerable than if these policies were not implemented at all.
Popularity gives way to recognition. In most realms of software, popularity is a great thing; it
brings attention to all your hard work and determination. In the case of OS fingerprint evasion,
recognition works against you. If you are using a popular tool or package, eventually
vulnerabilities and particulars will be discovered; this is inevitable. These same
software-specific identifiers will allow others to fingerprint your counter-measure accurately
rather than the operating system itself.
Most every OS attempts to make its TCP ISN sequencing random, in attempt to thwart TCP hijacking
and more complex attacks on the system. If your chosen implementation of evasion attempts to alter
TCP initial sequence numbers, great care should be taken to ensure you do not downgrade this
functionality and put your host at risk to these types of attacks.
As with any software package that makes it onto your system, application security should be a
primary concern. Part of the evasion process is masking existing services; the other comes in the
form of code, which is meant to filter your traffic and mask what you put on the wire. Great care
should be taken to ensure that the application produced for this task is secure through good
programming practices and rigorous testing. All it takes is one poorly thought-out strcpy() to
turn this asset quickly into a liability.
One of the evasion tactics previously listed is to alter the service banners of software that
identifies itself. Be careful because some add-on software packages actually use these same
banners to determine compatibility with the current system software.
Risk vs. Reward
Having established that evasion does not mean security, we need to look at another aspect of this
process, namely performance. Since a good evasion setup filters your traffic en masse, it is
feasible that system performance will suffer. Obviously if you have a site that hosts web pages
for 10,000 clients, performance is a bigger issue than if you simply have a Linux box set up
somewhere for you and your friends to check e-mail and IRC. As an administrator, you need to
decide which is the bigger reward for you (and your users), performance or privacy.
Proof of Concept
To illustrate the feasibility and relative ease of fingerprint evasion I have included a small
sample user-space application (OSFPE) for Linux, which makes use of the Netfilter kernel modules
[see Listing 1 at ftp://ftp.ssc.com/pub/lj/listings/issue89/4750.tgz]. Through the use of such
software as Netfilter in Linux, OS fingerprint evasion is becoming increasingly more efficient.
Similar modifications and applications are sprouting up all over the place; in BSD it is possible
to accomplish this task via ipfilter and a moderate amount of code (during the time of this writing
ipfilter has been removed from the BSD CVS tree, sorry guys). Windows users (who are by far at
the biggest disadvantage in this arena) are discovering ways to shim their TCP/IP communications,
and with the inception of Libpcap for Win32, capture and forge their own packet responses.
Netfilter at a Glance
Netfilter, as stated by its author, is ``a framework for packet mangling''. Sounds fun, eh?
Netfilter interfaces with the Linux kernel (kernels 2.4.x and above to be exact) and registers
hooks for each protocol. If the proper rules are in place, these hooks capture incoming or
outgoing network traffic that match specified rules. These packets are then processed and marked
for either NF_DROP to have the packet dropped, NF_ACCEPT to accept the packet for normal processing
on the stack or NF_QUEUE to have the packet queued for manipulation in user space. If the packet
gets queued for manipulation in user space, the ip_queue driver places it in a queue; it is then
handled asynchronously by any applications running in user space that have registered themselves
for these types of packets. When these applications pull the packets from the queue they have the
ability to manipulate, accept and reject the packets. If the packets are accepted, they are handed
off to the next application running that has registered for such a packet. If the packet is
flagged for NF_DROP, the packet is dropped and processing of that particular packet ceases.
Through the use of Netfilter, applications in user space essentially have kernel-level control of
network traffic.
Iptables
Iptables is an application used to interface with Netfilter to set, view and remove a system's
current network filtering rules. I make mention of iptables here because in developing the
proof-of-concept code we felt it was a better idea to introduce users to the iptables program for
rule administration rather than having the application handle them. This will allow people to
better understand what is going on with the packet queuing.
What We Did
By taking advantage of the Netfilter modules and iptables rule administration program we were able
to set up rules to capture incoming UDP, TCP and ICMP packets. Based on the incoming packets and
the source host we either allow them to access the system normally or craft responses to appear as
a Windows host, as defined in one of nmap's OS fingerprint entries. Here is the fingerprint we
were attempting to match, and a brief walk-through on how we accomplished this goal:
TSeq(Class=TD|RI%gcd=1|2|3|4|5|8|A|14|1E|28|5A%SI=<1F4)
T1(DF=Y%W=2017|16D0|860|869F%ACK=S++%Flags =AS%Ops=M|MNWNNT)
T2(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
T3(Resp=Y%DF=Y%W=0%ACK=O%Flags=AR%Ops=)
T4(DF=N%W=0%ACK=S++|O%Flags=R%Ops=)
T5(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(DF=N%W=0%ACK=S++|O%Flags=R%Ops=)
T7(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
PU(DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK =E%ULEN=134%DAT=E)
The first line states that we need to build a time dependent (TD) TCP sequencing or one that has
random increments (RI) equal to, but not greater than, 0x1F4 (500). This was actually pretty easy
to accomplish, or match up I should say. First we grabbed the incoming packet, took the TCP
sequence number, generated a psuedo-random number between 1 and 500 and added the values together.
This met both the random increment and greatest common denominator (gcd) requirements for the
fingerprint.
Next we broke down all the various packet tests (T1-T7) and created cases for them in our TCP
handler. All of these are pretty straightforward and simply dictate how the host should respond to
different types of packets to open and closed ports, the exact tests and their parameters are
covered more in-depth in Fyodor's paper on remote OS detection.
Next we matched up our response for a UDP port-unreachable query. What nmap does here is send a
UDP packet to a closed port on the host and wait for a response in the form of an ICMP
port-unreachable packet. ICMP port-unreachable packets simply tell the querying host that the port
to which they attempt to deliver a UDP message failed because there is no listening UDP service on
that port. On some networks these messages never get sent back and are dropped at the router. In
order to conform to the fingerprint we made an effort to send back what they were expecting.
Finally, as an extra little bonus we sent back Syn-Ack packets to the host for specific ports on
our host if they happen to scan for these TCP ports as being open. Similarly, we sent back no
response for particular UDP ports that we want to appear to be open on our host (as stated above,
only closed UDP ports send back a port-unreachable message). When the scan of our host is complete,
it should appear as though TCP ports 135 and 139 and UDP ports 135, 137 and 138 are open. If we
attempt to fingerprint our host we should match up with the above-listed fingerprint and get the
listing as ``Windows NT4 / Windows 95 / Windows 98''.
As a final note, proof-of-concept code is just that, a little piece of programming used to prove a
point. Do yourself a favor and don't run this on a critical device. Open it up, learn from it,
modify it, exploit it, but don't depend on it. I've made an attempt to keep the code safe and
somewhat readable (arguable), but I can't promise anything.
Acknowledgements
Thanks to Rex Warren for all his hard work aiding me with this paper and the sample code, Fyodor
for allowing me to reference all his hard work and for such a great security tool, Dan Kurc for
reading over my code and calling that baby ugly (Hey! It's my first C program), Sir Dystic for
C-isms and Courtnee.
Resources
Rob Beck is currently a security architect for @stake Security Consulting Services, specializing
in Windows OS/application penetration assessment and secure build design.
|
|