Curious Caroline writes:
I have a friend who was talking to a security tester the other day, and apparently the tester said that having a "malicious server" is different than having a "spoofed" server. How is that so? My friend would really like to know, so I told her I'd ask you.
Your friend has a good question.
The two terms are actually orthogonal -- you could have a spoofed-but-non-malicious server, a non-spoofed-but-malicious-server, and either of the other two combinations as well. When going through the threat modelling process, we're always on the lookout for both malicious entities and spoofed entities, and the difference between the two is really the kind of threat they possess (and thus the kind of mitigation we use to prevent it).
Spoofing threats occur when the server (or other entity) you are talking to is not the one you think you are talking to, and you have no way of verifying that this has occurred. For example, you think you have made a connection to www.amazon.com and are about to send over all your credit card details, but in reality you have connected to www.evil.com and it is about to steal all your information. Note that a spoof could be non-malicious and / or non-intentional. For example, imagine your Proxy server gets confused and when you try to visit www.microsoft.com in your web browser you actually get the content from www.google.com instead. The spoof here was unintentional and the "wrong" server (Google in this case) is not malicious at all. It's just a bit annoying.
Note also that there are spoofs against the software and spoofs against the user. If the DNS records for a particular server are wrong (for example), the software will be confused -- it asked for the IP address of www.microsoft.com, it received a IP address back from the DNS server, and it went to exactly that IP address. The software "believes" it is at the right place, even though it may be the real IP address of www.google.com.
Spoofs against the user are something we see a lot of these days with phishing attacks and the like. In this case, the browser asks for the IP address of www.evil.com, it gets the IP address, it goes there, and as far as the software is concerned you really are at www.evil.com. Trouble is that the content on www.evil.com is made to look just like www.citibank.com so the user is fooled into typing in their credentials. Sometimes browser bugs are used in this situation too -- address bar spoofs can be used to make the user think they are really at www.citibank.com even if they check the address bar, even though the browser still "knows" you are on www.evil.com
Of course, the best known way to mitigate all of these spoofing threats is to use a secure (SSL) connection. As long as you request a secure connection (and, in the case of the human spoofs, the user confirms that the certificate is issued to the intended company) then you will only be able to connect to the real server. A spoofed server (whether intentional or accidental) will not have the correct certificates needed to establish the secure connection. Of course SSL is more expensive than unsecured HTTP (in terms of network connection setup time, etc) so typically people only use it for high-value traffic, but realistically all traffic is high-value to someone. For example, imagine if someone spoofed blogs.msdn.com and posted an entry by "Peter Torr" that said "You should turn your Internet Explorer security settings down to 'Low' for all zones!" Now anyone who read that sentence by "Peter Torr" would either (i) think I was a complete moron, or (ii) start using the internet in an insecure fashion based on some really bad "expert advice".
Enough about spoofing. A malicious server is just a server that wants to compromise your software in some fashion. It could be a spoofed server but it could be the "real" server that you intend to talk to; doesn't matter. For example, imagine that instead of spoofing your internal database server, a bad actually takes over the machine and installs his own hacked code on it. Or, if your application supports some kind of file-type or shortcut that can be e-mailed around, imagine someone evil convinces you to open a shortcut that points directly to her malicious server. Now SSL won't help you at all, because all your clients really are connecting to the "right" database server, it's just that the server is no longer trustworthy and could be spewing out all sorts of junk.
You can't get away from malicious servers just by using SSL. No, to protect against malicious servers you actually have to write secure software :-). And although malicious servers can represent all the typical STRIDE threats against your software, I would focus most on the remote servers trying to DoS or EoP the client machines (eg, go from owning a single database server to owning all the client machines in the network). I say this because you are unlikely to be able to protect against information disclosure or tampering threats when faced with an un-spoofed-but-malicious server. (You really are connecting to the database server, and it really does go over SSL, but once you've sent your sensitive data to the server you have no control over what it does with it next. Similarly, if you query it for some data and it returns a result that is within reasonable limits of what you expect back, you have no way of knowing whether the data is correct or if it has been spoofed / tampered with by the malicious server).
So to mitigate against malicious server scenarios, you need to ensure that your client code is rock-solid against malformed inputs sent from the server. Never assume the packets coming in are the right size, or that the internal structures are filled out correctly, or that the buffer lengths in the header match the real size of the payload, etc. In fact, never assume the data will arrive at all -- always have a reasonable timeout to detect misbehaving servers (or just bad network connectivity) so your client doesn't hang indefinitely.
Once you've validated that the packets are well-formed and syntactically correct, it's still not necessarily a good idea to blindly take action based on the information inside them. Is the data in the packet within a reasonable set of limits? Given the current state of the client, is the request a reasonable one to service? Does the data you got back make any sense at all? etc. And remember as you do this that "lists of known-good behaviour" (allow-lists) are much better than "lists of known-bad behaviour" (block-lists) because, well, you don't really know what all the bad behaviours are, so you are likely to miss some of them.
Although there's little else you can do to protect against "0wned" servers, you can do some other small things to help mitigate the attacker-fooled-you-into-connecting-to-the-wrong-server threat. For example, you could publish a list of "known good" servers in Active Directory and before connecting to any machines the client could ensure the server was on that list. Now if a bad guy tries top set up his desktop machine as a malicious server, he isn't going to get very far unless he can also get it listed in AD (which should be really hard to do!). You could also ask the user to confirm each server the first time they connect to it, in an attempt to catch unexpected server names.
And a bonus point: Remember that you always have the man-in-the-middle (MITM) threat unless your connections are suitably encrypted and digitally signed. Even then, sometimes the mere fact that Client A is talking to Server B is "interesting" to an attacker, but that's usually only for highly sensitive things like military operations. For most situations, you don't need to worry about that :-)