UDP message and security

linkgoron

Platinum Member
Mar 9, 2005
2,598
1,238
136
Hi guys,

where I work we're I've developed some kind of extremely basic client/server application.

Sometimes a message needs to be sent to all the computers on the network at once using. the server sends a broadcast UDP packet with some kind of message to all the computers. Making this instantaneous is extremely important.

The client recieves a UDP packet and then pops up a message according to the string that was sent from the server. (basically there are two options. the server sends the ID number of the message, the clients all have a local db file with all the messages, and the clients display the message or the server sends the code for a manual code and the message is written in the packet)



I was wondering what kind of security issues can this cause?
I'm using C# 2.0.
there's only one server, so on the client side I've set the computers to only allow a message from the server's IP.

the only thing I've thought about was IP Spoofing, but even that can't affect many computers, because I'd think that the routers would recognize an ip spoof and stop it from moving deeper into the network.
I also don't think this is such a big issue, because the worst that can happen is a message poping up on people's computers...

yet...I've been told that this can open a window for viruses and hackers. I can't see how, as the clients don't send any response to the server. but I'm no security/network expert.

I was hoping you guys can help me out...
Should I fear some kind of code injection, or anything else? Is there any code I can write to help me?
I'm also going to do some more research on the net, but maybe some people here have some experience with this.

Thanks!
 

Cogman

Lifer
Sep 19, 2000
10,286
145
106
Yes, you should fear some sort of code injection. Buffer overflows are all too common. As well, both IP address and mac address can be spoofed, there is no way for the routers to know who sends the genuine message and who sends the spoofed one (thus the message propagates through the entire network.)

The way the buffer overflow works is like this. Guy figures out how long messages are supposed to be, he then sends a message that is longer then the messages are supposed to be. In the extra message space is included malicious code which can be made to run right after the message terminates. It is really quite nasty.

There are ways to defend against it, however.
1st. make sure that any sort of message display code has a fixed length of characters to display ect, that ensures that you aren't executing any extra code (never trust a message to be sane, always check it at the client level and treat it like it is unclean).
2. Use encryption. A simple encrypted client serve handshake will do, and can be performed pretty quickly. (look up RSA, SSL, or GPG techs for ideas on how to go about this).
3. If you can, don't let the communication portion of the application run with any sort of privileges, Don't give it registry access or even application launching access if at all possible (probably not, but here's hoping).

Paranoia is the key to good security, when communicating, always make the assumption that the message coming in was sent with malicious intent and needs to be cleared before being processed.
 

DaveSimmons

Elite Member
Aug 12, 2001
40,730
670
126
Besides protecting against buffer overruns, an MD5 hash using a shared secret for authentication is an easy way to add reasonable assurance that it's a valid message. It's not as strong as RSA, but should be strong enough for this use.
 

Cogman

Lifer
Sep 19, 2000
10,286
145
106
Besides protecting against buffer overruns, an MD5 hash using a shared secret for authentication is an easy way to add reasonable assurance that it's a valid message. It's not as strong as RSA, but should be strong enough for this use.

While it may work, you would still be sending out plaintext messages. That opens the possibility of the hash being broken just by monitoring the packet stream. If you did do the hash, I would do it along with the message being sent, and encrypt the whole thing.

IE, a message might look like encrypt(message + hash)
 

linkgoron

Platinum Member
Mar 9, 2005
2,598
1,238
136
Yes, you should fear some sort of code injection. Buffer overflows are all too common. As well, both IP address and mac address can be spoofed, there is no way for the routers to know who sends the genuine message and who sends the spoofed one (thus the message propagates through the entire network.)

The way the buffer overflow works is like this. Guy figures out how long messages are supposed to be, he then sends a message that is longer then the messages are supposed to be. In the extra message space is included malicious code which can be made to run right after the message terminates. It is really quite nasty.

There are ways to defend against it, however.
1st. make sure that any sort of message display code has a fixed length of characters to display ect, that ensures that you aren't executing any extra code (never trust a message to be sane, always check it at the client level and treat it like it is unclean).
2. Use encryption. A simple encrypted client serve handshake will do, and can be performed pretty quickly. (look up RSA, SSL, or GPG techs for ideas on how to go about this).
3. If you can, don't let the communication portion of the application run with any sort of privileges, Don't give it registry access or even application launching access if at all possible (probably not, but here's hoping).

Paranoia is the key to good security, when communicating, always make the assumption that the message coming in was sent with malicious intent and needs to be cleared before being processed.

I'd expect that the router(s) should know "where" the ip (i/e the server) "should" be, and as such should know that if it recieves a packet from a "wrong" place in the network, the router wouldn't forward it.

Also the messages aren't in any speficied length, as the text can change. Sometimes it can be 30 letters, and sometimes 3 letters (it depends if the message is in the local DB file). So Basically should I strive to make all my message say 30 letters? Maybe make some sort of break in the string (lets say either 60 letters or the '-' char,whichever comes first or something alike?)?

The problem with a handshake is the fact that I have one server on 1000 computers, and I need the message to get to them as quickly as possible (lets say under 5 seconds,preferably less). Can I complete this fast enough?
 
Last edited:

Cogman

Lifer
Sep 19, 2000
10,286
145
106
I'd expect that the router(s) should know "where" the ip (i/e the server) "should" be, and as such should know that if it recieves a packet from a "wrong" place in the network, the router wouldn't forward it.

Also the messages aren't in any speficied length, as the text can change. Sometimes it can be 30 letters, and sometimes 3 letters (it depends if the message is in the local DB file). So Basically should I strive to make all my message say 30 letters? Maybe make some sort of break in the string (lets say either 60 letters or the '-' char,whichever comes first or something alike?)?

The problem with a handshake is the fact that I have one server on 1000 computers, and I need the message to get to them as quickly as possible (lets say under 5 seconds,preferably less). Can I complete this fast enough?

The router doesn't know anything other then "This computer has the mac address of this, and claims to be this IP." Don't expect them to realize that port 3 was supposed to have mac address x (unless they are specifically setup that way).

The bigger issue with buffer overflows comes when you say something like
Code:
char message[30]
getMessage(message)
You shouldn't have a specific message size for incoming communication. but you should be able to say "message too long, flush extra bits out."

As for the handshaking, it goes extremely fast, you could send the handshake out simultaneously to each client and handle them as they come in.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
1. A lot of assumptions are semi-explicitly stated about your network. Are you in control of all your routers? Is this an internal network?

2. You can code against buffer overflows and other flubbups. Do so.

3. There's a difference between authentication and secrecy. I.e., with verifiable hashing you can have authentic messages without making the content secret. Decide which, if either, is important to you.

4. If you do sign with a hash (e.g., for authenticity), make sure the salt for the hash varies over time. Otherwise you are susceptible to replay attacks. This is trickier than it sounds. If your salts get out of sync, you become vulnerable to DoS attacks.

5. All systems weigh security measures versus risk. Many systems decide risk is very low and opt for no security at all. Make sure you properly analyze your risk, though -- anything running as an administrator is pretty risky to expose to a network.

6. Remember -- handshakes are meant to be part of authentication. You tell me challenge A, I respond with answer B and challenge C, you respond with answer D, etc. Unless handshakes are used as a mechanism to establish authentication for the eventual message, despite any number of handshake interchanges, an attacker can just spoof the final message.

7. Handshake performance is often bound by the slowest machine involved. That can be quite slow over 1k nodes.

I think you should consider what kind of attacks you want to attempt to handle correctly. Define your fault model. Then we can help you to figure out what kind of security you would need.
- Can users inject arbitrary level 2 packets?
- Level 3 packets?
- Could an attacker compromise any host?
- Could an attacker compromise any N hosts?
- Can an attacker add a host to a network that is already compromised (e.g., for masquerading)?
- Can an attacker take down links? Will the topology survive?
- Can an attacker take down or compromise routers? Will the topology survive? If a router is compromised, does that change the possible attacks?
- Can the attacker observe any link on the network? If not, which links?

Overall, since you're using UDP, I strongly recommend some measure of authentication -- if only because it is legal to deliver UDP messages more than once.

What kind of faults do you want to avoid:
- Attacker can execute arbitrary code on an arbitrary host
- Attacker can successfully dupe a client into thinking a legitimate message was sent by the server
- Attacker can convince server a particular client is down/misbehaving
- Attacker can convince server a particular malfunctioning client is functioning normally
- Etc., the list goes on for as many arbitrarily bad things as you want to imagine.
 
Last edited:

DaveSimmons

Elite Member
Aug 12, 2001
40,730
670
126
^ well said. My own assumptions were that:

1. blocking buffer overruns was critical. This is always true since this is the exploit that lets an attacker run arbitrary code.

2. blocking false messages would be nice, but has nowhere near the importance of 1.

3. It's unlikely that anyone would make much of an effort to spoof messages.

For that case a MD5 hash of (cleartext message) + (time as string) + (shared secret NOT sent with the message) offers "reasonable" protection against false messages and replay attacks.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
^ well said. My own assumptions were [assumptions]

For that case a MD5 hash of (cleartext message) + (time as string) + (shared secret NOT sent with the message) offers "reasonable" protection against false messages and replay attacks.

Yes. ... assuming (time as string) is reasonably synchronized between hosts (by some other service?)
 

linkgoron

Platinum Member
Mar 9, 2005
2,598
1,238
136
I have no control over my network at all.

From what I've seen here a basic byte[]= getmessage() should help me avoid buffer overflows. Unless I'm misunderstading something. Which it seems I am.

Obviously my main issue is running code on the computers in my network and compromising systems.

my second issue is getting false messages.

My server doesn't really care if a computer is working properly (as in, my message is recieved without any reply).

I don't care if someone knows what I'm sending, but I want to authenticate that my message is getting from the server, and not some random guy who knows how create UDP packets. (unlikely as it sounds...)
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
I have no control over my network at all.

From what I've seen here a basic byte[]= getmessage() should help me avoid buffer overflows. Unless I'm misunderstading something. Which it seems I am.

I'm not sure what language you're using. However, if your language will guarantee that bytes are allocated for the whole message, you should be in the clear. Especially considering UDP message sizes.

Obviously my main issue is running code on the computers in my network and compromising systems.
Well, code insertion starts with decent coding. You have to ensure that nothing from packet is ever executed. Thats harder than it sounds, but the short version is to check all buffer sizes and never read more bytes than you can hold. Best to put messages on the heap, as well, to prevent stack-smashing altogether.

my second issue is getting false messages.

I don't care if someone knows what I'm sending, but I want to authenticate that my message is getting from the server, and not some random guy who knows how create UDP packets. (unlikely as it sounds...)

Then you need to make sure your messages are authentic, e.g., with DaveSimmons's approach. In particular, you cannot rely on contents of UDP, IP, or ethernet headers to be accurate or genuine (assuming your layer 3 is IP and your layer 2 is ethernet).
 

linkgoron

Platinum Member
Mar 9, 2005
2,598
1,238
136
Hmm... I believe I've missed something.
What my packet should hold is : cleartext + time string (why?) + md5hash(secret)?

If I md5 hash everything I won't be able to read the message, because you can't decrypt it, only encrypt something and see if it's the same.

this is another thought I've had (it could be what you guys said and I just misunderstood?):
I've thought about sharing a random symmetric encryption key every day/week/whatever using RSA (or similar), and then encrypt the message using the key, and the systems would be able to read the message and use it.

I'd have to change the Key after every sent message ,because someone watching the network would be able to flood the network with what I sent, unless maybe I can add the time of day and use some kind of time-frame that a message won't be displayed after... like you guys offered.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Hmm... I believe I've missed something.
What my packet should hold is : cleartext + time string (why?) + md5hash(secret)?

Your packet should hold:
cleartext
md5hash( cleartext + secretSalt + time )

Only clients and servers know secretSalt. Ergo, by re-creating the hash at the client, it can know that the message came from the server.

Here is why you must include the time:

Server A: Text: Shutdown Hash: 7
Client B: Observes: Shutdown/7 -- hash matches (client shuts down)
Attacker C: Observes: Shutdown/7 -- remembers for later use

... a few hours later ...

Attacker C: Text: Shutdown Hash: 7
Client D : Observes: Shutdown/7 -- hash matches (client shuts down)

Thats a "replay attack". Without a timestamp to futz with the hash, an attacker can just replay on old message that it recorded at a previous time to achieve the same effect.

Timestamps fix that because the hash on Shutdown is a function not only of content and secret key, but also time -- hence unpredictable. The trick is making sure that the timestamp changes frequently enough, and is sufficiently well synchronized between server and client, to keep the vulnerability window low.

With reliable datagrams (i.e., not UDP) the timestamp can be virtual, e.g., tick whenever a message is sent or received.

I'd have to change the Key after every sent message ,because someone watching the network would be able to flood the network with what I sent, unless maybe I can add the time of day and use some kind of time-frame that a message won't be displayed after... like you guys offered.

Yup, you know what a replay attack is. Hence the timestamp.
 
Last edited:

linkgoron

Platinum Member
Mar 9, 2005
2,598
1,238
136
Ok I've re-thought the process.
What I need is an encryption key on the server, and decryption keys on the clients.

Basically I'll reverse the public/private keys- instead of a known encryption key, and an unknown decryption key, I'll have a public decryption key and a private encryption key.

something like:
send (encrypt_with_key(<cleartext>+<timestamp>))

The way I see it, this way I don't have any problems with sharing the key with all the clients, and I also don't have any problem with replay attacks.

I also don't care if an attacker knows what I sent because the message is not a secret. The encryption is.

The obvious question here is: how easy is it to crack a key, once you know the message, and if I missed some serious security issue with this?


Ahh.. An attacker will be able send his own key to my clients and flood me with messages...
 
Last edited:

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Basically I'll reverse the public/private keys- instead of a known encryption key, and an unknown decryption key, I'll have a public decryption key and a private encryption key.

something like:
send (encrypt_with_key(<cleartext>+<timestamp>))

Theoretically, what you propose is less secure than the hashed-based signature. It is vulnerable to a different attack -- computational decomposition of cleartext and ciphertext, since the attacker will be able to accumulate many cleartext/ciphertext pairs (assuming decryption key really is 'public').

In practice, it would be pretty daunting to circumvent, but bear in mind you still need a mechanism to keep timestamps in sync. Thats not trivial, unless you have big timestamps and can tolerate some windows where timestamps aren't quite right.

Ahh.. An attacker will be able send his own key to my clients and flood me with messages...

Its pretty hard to deal with flood-based (D)DoS attacks. The only way I know to deal with them is with a honeypot.
 

DaveSimmons

Elite Member
Aug 12, 2001
40,730
670
126
One easy defense against replay attacks would be to cache the last N valid messages on each client.

When a new message arrives, validate the hash then also check the cache to see if it is a duplicate message. Since you only store valid messages in the cache the invalid messages won't push valid ones out of the cache.

This lets you set the tolerance between the local clock and server clock much higher. If you are caching 24 hours worth of messages then a clock difference of 12+ hours can be ignored because a replay attempt using a message from 6 hours ago would be foiled by the cache.