These programs are extremely useful, but as we discuss later in this section, they are safe to use only in an environment in which all of the machines are more or less trusted to play by the rules. While it may be appropriate to use these services within a local area network, it's almost never appropriate to use them across the Internet. It's just too easy for someone to convince these services that they're OK and that the service should perform what's requested.
The difficulty with these commands is that they use address-based authentication. The server looks at the source address of the request and decides whether or not it trusts the remote host to tell it who the user is (this is controlled by the /etc/hosts.equiv and .rhosts files on Unix systems).
An attacker who convinces one of these servers that a connection is coming from a "trusted" machine can essentially get complete and unrestricted access to your system. This can be done by impersonating a trusted machine and using its IP address, by confusing DNS so that DNS thinks that the attacker's IP address maps to a trusted machine's name, or by any of a number of other methods.
If the trusted host check described previously fails (that is, if the user is not coming from a trusted host), most of these services simply deny the client's request and disconnect. The rlogind server, however, will prompt the client for a password if the trusted host check fails. The password entered is sent in the clear over the net, just as with Telnet, so you have to worry about attackers capturing passwords from rlogin sessions, as they can from Telnet sessions. See Chapter 21, "Authentication and Auditing Services", for a discussion of ways to address password sniffing attacks.
On some systems, it is possible to disable the trusted host checks with a command-line argument to the servers; even if your server doesn't provide a convenient switch to disable the checks, if you have (or can get) source code for the servers, it's usually a relatively simple fix. However, without the trusted host mechanism, the rshd server is completely pointless because it provides no way to prompt for a password or other authenticator if the trusted host check fails. The rlogind server is still somewhat useful without the trusted host check because it can ask for a password, but it's not much more useful than Telnet.
The security implications for the server are somewhat worse in Windows NT than they are in Unix. The basic problem is the same; the server is relying on the client's information about the user. Most clients are not in the least trustworthy (there are a number of ways for somebody with control over a client to take on any identity they please). In addition, since the client is identified only by checking the source IP address, the server is vulnerable to IP address spoofing even if it only trusts carefully chosen clients.
Worse yet, there is a mismatch between rsh and Windows NT's security model. Under NT, a program cannot just assume a user's identity without a password. rsh, however, is incapable of providing a password. The rsh server has to find some way to bridge this gap. Some servers take the straightforward and completely insecure approach of not even trying to assume the user's identity, and running everything with the server's permissions. Others store a mapping between rsh users and Windows NT users, including the Windows NT password. This provides better security when the server is in use, but an attacker who gets access to the mapping data has user and password information.
Because of these problems, running these servers is not advisable.
Using ports below 1024 for the client end is an attempt at a security scheme that allows password-less access to these services as long as the requests come from a trusted host and user, as discussed earlier. The idea is that, if the request comes from a port below 1024 on the client end, then the request must be OK with root on the client machine; if it were not, the client never could have gotten the port below 1024 to use for the request. This notion is completely incorrect on Windows operating systems, where any user can use any port that is not already in use.
Further, some of the clients of the server on port 514 (rsh, for example) use a second TCP connection for error reporting. This second TCP connection is opened from a random port below 1024 on the server to a random port below 1024 on the client; that is, an outgoing rsh command involves an incoming TCP connection for the error channel.
Direction | SourceAddr. | Dest.Addr. | Protocol | SourcePort | Dest.Port | ACKSet | Notes |
---|---|---|---|---|---|---|---|
In | Ext | Int | TCP | <1024 | 513 |
[82]
|
rlogin, external client to internal server |
Out | Int | Ext | TCP | 513 | <1024 | Yes | rlogin, internal server to external client |
In | Ext | Int | TCP | <1024 | 514 | [82] | rsh/rcp/rdump/rrestore/rdist, external client to internal server |
Out | Int | Ext | TCP | 514 | <1024 | Yes | rsh/rcp/rdump/rrestore/rdist, internal server to external client |
Out | Int | Ext | TCP | <1024 | <1024 | [82] | rsh error channel, internal server to external client |
In | Ext | Int | TCP | <1024 | <1024 | Yes | rsh error channel, external client to internal server |
Out | Int | Ext | TCP | <1024 | 513 | [82] | rlogin, internal client to external server |
In | Ext | Int | TCP | 513 | <1024 | Yes | rlogin, external server to internal client |
Out | Int | Ext | TCP | <1024 | 514 | [82] | rsh/rcp/rdump/rrestore/rdist, internal client to external server |
In | Ext | Int | TCP | 514 | <1024 | Yes | rsh/rcp/rdump/rrestore/rdist, external server to internal client |
In | Ext | Int | TCP | <1024 | <1024 | [82] | rsh error channel, external server to internal client |
Out | Int | Ext | TCP | <1024 | <1024 | Yes | rsh error channel, internal client to external server |
[82]ACK is not set on the first packet of this type (establishing connection) but will be set on the rest.
The other commands rely completely on address-based authentication, and don't allow the user to specify a password at all. They're used so seldom across the Internet that proxies for them are not widely available. All of them allow the user to specify enough data that's passed to the server that it would be possible to write modified-procedures proxies for them. Modifying the rcmd( ) and related functions in the standard Unix library allow you to create clients that use a generic proxy server.
rexec is usually lumped in with the BSD "r" commands, but actually it has a slightly more secure design than the others. Rather than providing source-address authentication, it always requires the user to provide a username and password. This advantage is outweighed by the fact that it passes these across the network in the clear, so it has no security advantage over Telnet, for example. Worse yet, most rexec daemons provide no logging whatsoever. This makes rexec a favorite point of attack, since you are unlikely to notice the attackers at any point -- while they're trying to break in, or even after they've gotten in.
Direction | SourceAddr. | Dest.Addr. | Protocol | SourcePort | Dest.Port | ACKSet | Notes |
---|---|---|---|---|---|---|---|
In | Ext | Int | TCP | >1023 | 512 |
[83]
|
Incoming rexec, client to server |
Out | Int | Ext | TCP | 512 | >1023 | Yes | Incoming rexec, server to client |
Out | Int | Ext | TCP | >1023 | 512 | [83] | Outgoing rexec, client to server |
In | Ext | Int | TCP | 512 | >1023 | Yes | Outgoing rexec, server to client |
[83]ACK is not set on the first packet of this type (establishing connection) but will be set on the rest.
rex is a TCP Sun RPC service; for more information on the packet filtering, proxying, and network address translation characteristics of RPC services, see Chapter 14, "Intermediary Protocols".
Remote Console or RCONSOLE
Despite their very similar names, these services do quite different things. RCMD is a fairly standard remote execution service; you start up the server, and clients that connect to it can then execute any command. REMOTE is more limited; you start the command to be run at the same time you start the server, and the client can control only the command you started. Commands that use graphics or complicated input and output methods will not work with either service (this includes a number of standard programs you might want to use from a command line, including most notably edit). Neither service encrypts information.
Remote Console provides more capabilities than either RCMD or REMOTE. It gives you a console on the remote machine exactly as if you were physically logged into the machine and had asked for a command prompt. It takes over video and all input and output, so that any program that normally works in a console window will work correctly. Remote Console does support encryption. By default, it encrypts authentication information. In addition, clients can request that an entire connection be encrypted (the server cannot require encryption). Authentication information is encrypted with DES. The details of the other encryption systems are not documented.
The services also use different security models. RCMD uses normal Windows NT authentication. The user who is running the client must have permission to log in to the server machine interactively, and the commands will run with that user's permissions. (Some early versions of RCMD do not actually correctly run the commands with the user's permissions; you should be sure to run the most recent version.) REMOTE does not by default do any authentication whatsoever, and the command is run with the permissions of the user who started the server. When you start a REMOTE server, it is possible to limit access to a particular group or user.
Remote Console uses its own authentication. By default, only members of the Administrators group can use Remote Console. It is possible to give this ability to other users by making them members of the group "RConsoleUsers"; if you do this, the users will automatically have the privilege "Log on as a batch file". When these users use Remote Console, they will get a console running with their normal permissions, as if they were physically logged in at the console (except that Remote Console does not check to see if they have the "Log on locally" permission that would let them do that).
REMOTE is of limited usefulness and is highly insecure. RCMD is more useful but still not very secure. If you need occasional command-line access to remote machines on a relatively secure network, Remote Console is a reasonable way to provide it. If you need full administration remotely, you will need a more powerful remote access solution; if you need to cross an insecure network, you will need a better protected one. In any case, if you are working remotely between NT machines, Remote Console is preferable to rsh, since Remote Console uses Windows NT user authentication, which is more secure than rsh's source address authentication.
All of these services are based on SMB transactions; the packet filtering, proxying, and network address characteristics of SMB transactions are discussed in Chapter 14, "Intermediary Protocols".
SSH servers are widely available for Unix and Windows NT and may be available for other platforms that provide command-line interfaces. SSH clients are available for almost all platforms.
There is a good bit of confusion about the name "SSH". Originally there was a single program called ssh, but over time, several other entities have grown up. There is a package, including the ssh program and others, which is usually called SSH; there is a network communications protocol that the ssh program (and others) are based on, which is also usually called SSH; and there is a company called SSH Communications Security that has other products that use the SSH name.
Currently, two versions of the SSH protocol exist, SSH version 1 and SSH version 2. SSH version 1 is the original. Version 2 has a number of new features, including support for the TLS protocol, which is discussed further in Chapter 14, "Intermediary Protocols". This protocol (at the time of writing) is not yet an IETF standard, and hence, SSH version 2 is still a work in progress. SSH version 2 is also in the process of becoming an IETF standard.
The original implementation, which is distributed primarily in source code form, has a generous license that makes it available free of charge for most noncommercial purposes. The reference implementation of SSH version 2 by SSH Communications Security is being supported and sold commercially (although it is available free of charge for very limited uses). Multiple programs based on the SSH protocols, some of them commercial and some of them freely available, are also developed by other people.
Because of the multiple implementations and the different licensing and legal restrictions, both versions are in widespread use, and this is expected to continue to be the case for some time. Unless otherwise noted, this discussion applies to both versions of the SSH Communications Security package.
Used correctly, SSH provides protection against a number of risks. Because it uses an encrypted connection for the entire conversation, including user authentication, it protects against eavesdroppers, whether they are looking for passwords or for data. The integrity mechanism that's used prevents session hijacking; an attacker cannot take over an existing connection because the attacker will not be able to correctly generate the integrity checksums.
SSH is a very popular tool for people who break into sites, as well as for administrators, and for many of the same reasons. Because SSH provides encrypted connections, administrators can't tell what information is moving across an SSH connection. Furthermore, SSH provides port-forwarding features (discussed later), which allow you to run all sorts of other protocols across an SSH connection, without any administrative control.
Since SSH is often used for remote administration, it's also a very useful command for attackers to booby-trap. Attackers will often install versions of SSH that function normally but send the attacker all authentication information, as well as the information needed to decrypt a connection (allowing them to snoop on it or hijack it). You should keep careful control over what machines can run SSH, and they should be protected bastion hosts where you will detect changes.
Both version 1 and 2 of SSH meet the characteristics of a secure private communication session because:
In both versions of SSH, public key cryptography is used to prove the identity of a server. The first part of checking the identity is to verify that you have a valid public key for the server that you wish to connect to. At the time SSH version 1 was developed, this was a very difficult problem because there was no standard interoperable global infrastructure for the purpose of distributing and verifying public keys. This situation is slowly improving, and SSH version 2 can use a certificate authority to verify a public key (this is one of the features provided by using TLS, which is discussed in Chapter 14, "Intermediary Protocols"). SSH version 2 also supports the mechanism developed for SSH version 1.
The solution SSH version 1 uses is novel; the client retrieves the public key from the server itself, checks to see if it already knows a key for a server having this name, and compares the keys. A mismatch in keys causes a warning to be printed. When the client doesn't already have a key, it also prints a warning and optionally stores the public key for the next time you connect to the server. This system makes the client vulnerable to a hostile server on the first connection, but it does provide significantly more security than having the client vulnerable to a hostile server on every connection.
It is also possible to provide a local system database of keys for servers that users might want to connect to. This protects clients against a hostile server but at the expense of maintaining the local database. Having a local database is effective only if it is possible to know in advance which servers clients are going to connect to.
After checking the validity of a key, SSH then checks the identity of the server by sending a message encrypted using the public key.[84] When the server proves that it successfully decrypted the message, and therefore knows the private part of the public key, the client believes it is talking to the correct server.
[84]SSH version 2 does not always use public key algorithms for this. See the description of TLS in Chapter 14, "Intermediary Protocols", for how server identity is determined.
Port forwarding is both a useful feature and a very dangerous one. It is useful, for example, if you want to create a simple virtual private network between two servers that you control. Allowing SSH with port forwarding can be an effective way to protect protocols like POP and IMAP that normally exchange unencrypted data.
Port forwarding is dangerous because it can be set up to forward external connections to an internal service, effectively bypassing your firewall. If this occurs, it will be difficult to detect by examining network traffic because the connections will be encrypted. For this reason, you should only allow incoming SSH connections to servers that you control, and you should consider turning off the general port forwarding features for incoming connections. Similarly, you should limit outgoing SSH connections to using SSH clients that you control, preferably with port forwarding turned off. Remote port forwarding will allow apparently outbound connections to carry inbound traffic.
Port forwarding does require some knowledge of how the protocols work and the port numbers that are used. It is therefore not useful to most users. If you receive requests to use port forwarding features, you may wish to consider implementing a real virtual private network. See Chapter 5, "Firewall Technologies", for information on virtual private networking.
Both the client and the server provide ways to permanently turn off port forwarding; you can compile them without the port forwarding feature, or use a system configuration file to disable it. However, this will not prevent users from using their own clients (which may ignore the system configuration file).
Inbound port forwarding is configured at the start of an SSH session. SSH can set up forwarding for several different ports at the same time. However, an attacker can only exploit the ports that were set up at the start of a session; additional ports can only be attacked when new SSH sessions are started. For instance, if you set up port forwarding to an IMAP server, that may expose the IMAP server to attackers, but it doesn't allow access to any other services. It is possible to place default forwarding information into the per-user configuration file. This will cause ports to be forwarded automatically whenever an SSH session is started. You may want to disable inbound port forwarding on your SSH server to keep users from opening internal ports to attackers with this feature.
However, if an attacker can do port forwarding to a proxy server, and the proxy server can talk to the internal network, a single port forward can turn into extremely general access. For instance, if a port is forwarded from the outside to a web proxy, the attacker then has access to anything that the web proxy can reach. For various reasons, ranging from laziness to a desire to accommodate bad browser configurations, administrators often set up their external proxy systems so that they can reach internal servers. In this configuration, one single port forward can provide an attacker straightforward access to the entire internal web, and all the information and vulnerable servers that are on it. A SOCKS proxy server can give even more direct and widespread access.
If you allow incoming SSH connections and port forwarding, you should make sure that any firewall proxy services refuse and log connection attempts from those systems. In general, if you are using firewall proxy services, you should configure them to not allow connections to internal systems. This protects you from users using port forwarding on an incoming SSH server and using your proxy servers to access internal or external resources.
Direction | SourceAddr. | Dest.Addr. | Protocol | SourcePort | Dest.Port | ACKSet | Notes |
---|---|---|---|---|---|---|---|
In | Ext | Int | TCP |
Any[85]
|
22 |
[86]
|
Incoming SSH connection, client to server |
Out | Int | Ext | TCP | 22 | Any[85] | Yes | Incoming SSH connection, server to client |
Out | Int | Ext | TCP | Any[85] | 22 | [86] | Outgoing SSH connection, client to server |
In | Ext | Int | TCP | 22 | Any[85] | Yes | Outgoing SSH connection, server to client |
[85]SSH clients use a port below 1024 when using .rhost-based authentication methods, and a port above 1023 otherwise.
[86]ACK is not set on the first packet of this type (establishing connection) but will be set on the rest.
Only enable remote X11 support when you need it.
Consider disallowing outbound SSH connections, because they can be used to tunnel inbound connections, and it is difficult to enforce port forwarding restrictions on them.