What is the best way to secure UDP server with HMAC? - python

I hope this is not too opinionated because I'm looking for a finite answer.
I'm developing a UDP server in Python 3.x that is utilizing asyncio. The server is going to work with a game engine to process pretty much every interaction a player makes in the game. Therefore, I have to authenticate the game client with the game server in some way as well ensure replay attacks do not happen on top of everything else that could harm or spoof the game server.
When it comes to authenticating with UDP, I'm at a loss. My plan is to have both the game client and game server authenticate per user and game session. That means having something like a public key on the client end and a private key on the server end where the server can authenticate the client is approved.
During that authentication, I am going to generate a symmetric key that the game server makes and passes it down to the game client so every packet sent can be verified with that symmetric key using HMAC. If not, all packets are dropped.
My Question
Is this the best approach? Creating some type of public key where something like a token is generated per session to ensure packets coming to the UDP server are from authenticated clients? My worry here is the keys are still stored in a Windows EXE file and still likely can be cracked and extracted or am I just too paranoid?

Going to answer my own question!
No It's Not The Best Approach
The reason this is not the best approach is because even with this process, my use of public/private key was incorrect. I was not referring to encrypting data between the client and server, I was referring to creating a nonce with having some type of password on the client that matches the password on the server.
This means the moment I send credentials from the client to the server, it's being sent without encryption on the line or in the buffer to the server. Once this authentication is accepted by the server, it will hash the password, store it and then send the nonce back to the client, which will also be without encryption.
The username, the password, and the nonce will be vulnerable to Man in the Middle attacks from both a third-party and the client itself. Which means they can sniff the packets, snag the transmission and crack the user or attempt replays being they have the nonce.
Solution
My game client does not have SSL/TSL/DTSL options. This is why I actually posted the question, but did not clarify this. My server, as it's custom within Python, does have that ability though. But, I found a plugin for the game engine last night that allows for AES encryption of the data being written to the buffer before said buffer is sent as a packet to the UDP server, which means I can encrypt the passing of data in those packets in a secure way that hopefully the server can decrypt with a legit private key.
Doing this will be a good option because it likely will be my only option. Now when a malicious user sniffs the traffic, they wont be able to see credentials or the nonce. The only issue after that is cracking the EXE, which I'm fine with for now.

Related

Python SMTP connection is too slow in API call

I have a small issue with the smtplib in Python. I am currently building an API with Flask and I am going through the authentication stage. The theory is very simple: I have created a route accepting POST requests via json with username, password and an email address.
Every time a new user is created the inner logic sends a basic response to the given email with a secret code to activate the account. Everything works wonderfully, however the request takes on average 7.5s and the bulk of that is the actual email delivery.
I am using the smtp library in this way inside a function that gets triggered every time a new user is created:
def func(*args, **kwargs): # the arguments are email address from/to and the actual message
with smtplib.SMTP_SLL('****.mail.com') as smtp:
smtp.login(ADDRESS, PASSWORD)
smtp.sendemail(msg)
My question is: Would it be possible and maybe faster to assign the SMTP_SSL connection to an object, like below, outside the function so that the connection were always open:
server = smtplib.SMTP_SSL('****.mail.com')
server.login(ADDRESS, PASSWORD)
def func(*args, **kwargs): # the function doesn't connect everytime
server.sendemail(msg)
In my estimation the actual connection, verification and login take up the longest.
Also, which security problems might emerge keeping the SMTP connection always open when the web server for the website is running?
Thank you very much
A similar question has been adressed in
How to send bulk emails through SMTP without establising a connection for every email?
In general, I think it's ill advised. If you're connecting to your ISP's SMTP-server, they will not appreciate permanently hogging a socket. If it takes that long to do the handshake, it would be a fair guess that they already have some load to sure.
Besides, you will likely be disconnected after a while of inactivity. Exception handling will also get tricky if you do it like you suggested.
Depending on your environment, and as suggested in the above discussion, you can set up Postfix as a null client, with connection caching enabled. This punts handling the hairy bits to a piece of software that is engineered to deal with it.
Your webserver would then use smtplib to connect to this null client and send your email. This transaction will be practically instant, and Postfix would do its thing.

Most secure server to server connection

I need to build a Python application that receives highly secure data, decrypts it, and processes & stores in a database. My server may be anywhere in the world so direct connection is not feasible. What is the safest/smartest way to securely transmit data from one server to another (think government/bank-level security). I know this is quite vague but part of the reason for that is to not limit the scope of answers received.
Basically, if you were building an app between two banks (this has nothing to do with banks but just for reference), how would you securely transmit the data?
Sorry, I should also add SFTP probably will not cut it since this python app must fire when it is pinged from the other server with a secure data transmission.
What is the safest/smartest way to securely transmit data from one server to another (think government/bank-level security)
It depends on your threat model, but intrasite VPN is sometimes used to tunnel traffic like this.
If you want to move up in the protocol stack, then mutual authentication with the client pinning the server's public key would be a good option.
In contrast, I used to perform security architecture work for a US investment bank. They did not use anything - they felt the leased line between data centers provided enough security.
Transmission and encryption need not happen together. You can get away with just about any delivery method, if you encrypt PROPERLY!
Encrypting properly means using a large, randomly generated keys, using HMACs (INSIDE! the encryption) and checking for replay attacks. There may also be a denial of service attack, timing attacks and so forth; though these may also apply to any encrypted connection. Check for data coming in out of order, late, more than once. There is also the possibility (again, depending on the situation) that your "packets" will leak data (e.g. transaction volumes, etc).
DO NOT, UNDER ANY CIRCUMSTANCES, MAKE YOUR OWN ENCRYPTION SCHEME.
I think that public key encryption would be worthwhile; that way if someone collects copies of the encrypted data, then attacks the sending server, they will not have the keys needed to decrypt the data.
There may be standards for your industry (e.g. banking industry), to which you need to conform.
There are VERY SERIOUS PITFALLS if you do not implement this sort of thing correctly. If you are running a bank, get a security professional.
There are several details to be considered, and I guess the question is not detailed enough to provide a single straight answer. But yes, I agree, the VPN option is definitely a safe way to do it, provided you can set up a VPN.If not, the SFTP protocol (not FTPS) would be the next best choice, as it is PCI-DSS compliant (secure enough for banking) and HIPAA compliant (secure enough to transfer hospital records) and - unlike FTPS - the SFTP protocol is a subsystem of SSH and it only requires a single open TCP port on the server side (22).

Encrypting data in Python -

I'm writing a client - server model ( client is a script on a server that gathers data and sends it via REST to the server ) and want to encrypt the data that is sent.
At the moment I have a function that generates the a random key, which adds time from a specific timezone - IP-HOSTNAME-YEAR-MONTH-DAY-HOUR-(MINUTE/2)
Each part of the key is ran from 3,000 - 10,000 times trough a SHA256 and finally the 128 bit key is generated. Script all in all takes ~0.8 - 1 second to complete.
Data is encrypted via AES , using parts of the 128 bit key for the key and iv.
The server script, listens for any connections, verifies if the IP address is listed and then proceeds to decrypt the data (using the same method to generate the key and iv )
My question is:
- Am I reinventing the wheel ?
- Is there a better practice to generate a dynamic, time limited key for data encryption ?
My goal was to have a key that is limited to 60-120 seconds and then discard it, use multiple cycles to generate the keys (thanks to reading the python way for Truecrypt ), so if any data is caught it wouldn't be decrypted "easily" .
Also, the server model will have a SSL cert that it will use to encrypt the encrypted.
I was thinking of giving a static key for each client script (RSA generated), that would be used to for AES encryption.
Thank you on your honest answers and any new ideas to improve this.
Using the simplest SSL/TLS (without PKI) as transport protection for REST is probably the most effective way to get the wheel right the first time.
Beside that, you should clarify a few topics. For instance:
Is it important that the client does not get deceived by an attacker which may be impersonating the server? If it is, then you have to properly setup PKI so that the client can authenticate the server with a certificate. Alternatively you can use TLS-SRP.
Is it important that the server does not get deceived by an attacker which may be impersonating a real user? If it is, then you have to setup an authentication scheme: for instance HTTP Digest, SSL client certificates, TLS-SRP, etc.
Is it important that a compromise at the client or server does not jeopardize data exchanged in previous sessions? If it is, then you have to restrict the cipher suite to cipher that offer perfect forward secrecy (DHE).
Only if you have troubles in setting up SSL you should consider rolling up your own protocol.
Yes, and don't! Cryptographic technologies take years to develop and test for a reason, they're extremely hard to get right. It sounds like you might want to look at using RSA or some other PKI infrastructure. If I were you I would look into PyCrypto https://www.dlitz.net/software/pycrypto/. Either way, don't implement your own cartographic system it will be broken and insecure!

UDP security and identifying incoming data

I have been creating an application using UDP for transmitting and receiving information. The problem I am running into is security. Right now I am using the IP/socketid in determining what data belongs to whom.
However, I have been reading about how people could simply spoof their IP, then just send data as a specific IP. So this seems to be the wrong way to do it (insecure). So how else am I suppose to identify what data belongs to what users? For instance you have 10 users connected, all have specific data. The server would need to match the user data to this data we received.
The only way I can see to do this is to use some sort of client/server key system and encrypt the data. I am curious as to how other applications (or games, since that's what this application is) make sure their data is genuine. Also there is the fact that encryption takes much longer to process than unencrypted. Although I am not sure by how much it will affect performance.
Any information would be appreciated. Thanks.
One solution is to use TCP because it is immune to spoofing the source address over the open internet because of the three-way-handshake (More information on why TCP source address spoofing is impossible.). If you still want to use UDP, you could have a simulated three way handshake to begin the connection. A session id could then be added to each UDP packet. This will increase the connection overhead by 2 packets and a few bits per packet, however you will still gain from UDP's speed for the rest of the session when compared to tcp.
However, using TCP or UDP as a transport layer still leaves you open to other attacks such as Sniffing and Man in The Middle attacks using arp spoofing or dns cache poising. Another problem is if both the attacker and the gamers are on the same local lan, such as a wireless network or another broadcast network then you are able to receive traffic regardless of the source/dest address and ONLY THEN does spoofing a three way handshake become possible (and an hmac can't help!). The best soltuion is to use SSL/TLS as your transport layer which solves all of these problems.
You should not reinvent the wheal, but if you need to encrypt UDP for some reason you should use a Stream Cipher like RC4-drop1024 or even better a Block Cipher like AES 256 in OFB Mode. This will save bandwidth over other modes of encryption because they round up to the largest block size.
EDIT:
Based on Marts comment for (Datagram Transport Layer Security)DTLS I did some digging and I found there is an official RFC and its supported by OpenSSL and should be exposed using the pyOpenSSL library. I recommend using the RC4-SHA cipher suite to reduce overhead, this suite is supported by SSL 3.0 (newest). However DTLS will probably have more overhead (LAG!) then TCP.
You can look at HMAC
Wikipedia:
In cryptography, HMAC (Hash-based
Message Authentication Code), is a
specific construction for calculating
a message authentication code (MAC)
involving a cryptographic hash
function in combination with a secret
key. As with any MAC, it may be used
to simultaneously verify both the data
integrity and the authenticity of a
message.
Each client would need to get a unique token which only they know. Every message they send, they'll make a hash based on the token and the message and send it along with the message itself. Then you can verify that the message came from a specific client.
If you absolutely need to verify that a particular user is a particular user then you need to use some form of encryption where the user signs their messages. This can be done pretty quickly because the user only needs to generate a hash of their message and then sign (encrypt) the hash.
For your game application you probably don't need to worry about this. Most ISPs wont allow their users to spoof IP addresses thus you need to only worry about users behind NAT in which you may have multiple users running from the same IP address. In this case, and the general one, you can fairly safely identify unique users based on a tuple containing ip address and UDP port.
DTLS is likely the best solution, however, it appears to be very poorly documented. I've been looking for a similar solution for a while now and all of the references I've seen to OpenSSL's DTLS implementation suggests that you'll be needing to dig through the OpenSSL examples & source code to figure out how to use it... which, to me, means I'm going to make 10 serious security mistakes when I try to set it up. Also, I don't believe the pyOpenSSL liberary exports this functionality.
An alternative I've been considering is the Secure Remote Password Protocol. The advantage of this solution is that it gives you strong mutual authentication (on par with the security of Kerberos according to the docs) and, just as importantly in your case, it provides both ends with a shared session key that can be used for encryption.
Given the shared key, each packet could contain AES256_CBC( <random starter block for CBC><user-id><sequence_number><application data> ) If the decryption succeeds in providing the anticipated user-id, the packet is authenticated as coming from your user and the sequence number can be used for avoiding replay attacks.
One downside to SRP is that, in Python, the number crunching is pretty slow. I modified the demo Python code into something a bit more usable and found that it took about 300ms to perform a single client-server SRP exchange (2Ghz CPU). However, a straight-forward implementation in C++ of the SRP algorithim using the BigNumber support in the OpenSSL took only 2ms. So, if you intend to go this route, I'd highly recommend using a C/C++ implementation of the algorihim for production code. Otherwise, you'll likely only be able to handle a few logins per second.
I'm breaking this down into four levels of security.
Extremely Insecure - Anyone on the network can spoof a valid request/response with generally available prior knowledge. (ie syslog)
Very Insecure - Anyone on the network can spoof a valid request/response only if they have at least read access to the wire. (Passive MITM) (ie http accessable forum with browser cookies)
Somewhat Insecure - Anyone in the network can spoof a valid request/response if they can read AND make changes to the wire (Active MITM) (ie https site with self-signed cert)
Secure - Requests/Responses cannot be spoofed even with full access to the
wire. (ie https accessable ecommerce site)
For Internet games the very insecure solution might actually be acceptable (It would be my choice) It requires no crypto. Just a field in your apps UDP packet format with some kind of random practically unguessable session identifier ferried around for the duration of the game.
Somewhat insecure requires a little bit of crypto but none of the trust/PKI/PSK needed to prevent Active-MITM of the secure solution. With somewhat insecure if the data payloads were not sensitive you could use an integrity only cipher with (TCP) TLS/ (UDP) DTLS to reduce processing overhead and latency at the client and server.
For games UDP is a huge benefit because if there is packet loss you don't want the IP stack to waste time retransmitting stale state - you want to send new state. With UDP there are a number of clever schemes such as non-acknowledged frames (world details which don't matter so much if their lost) and statistical methods of duplicating important state data to counter predictable levels of observed packet loss.
At the end of the day I would recommend go very insecure or somewhat insecure /w DTLS integrity only.
I would look into the Garage Games networking library. It is written in C++ and uses UDP. It is designed for low latency and is considered one of the best for games.
If I remember correctly they would actually calculate the likely position of the player both on the client side and the server side. It would do this for many aspects to ensure integrity of the data. It also would do a crc check on the client software and compare against the server software to make sure they matched.
I am not sure you can license it separately anymore so you may have to license the game engine (100 bucks). It would at least give you some insight on a proven approach to UDP for games. Another possibility is looking into the PyGame networking code. It may have already addressed the issues you are facing.

Basics of string based protocol security

I wasn't sure how to phrase this question, so apologies in advance if it's a duplicate of something else.
I wanted to sanity check how I've secured my twisted based application and think I've done a good job at it, but it's been over a decade since I've written anything that uses raw or managed sockets.
Authentication transaction:
Client connects and immediately a challenge response is sent back with a 16 character hex string.
Client side takes user name & password, password is converted sha1( salt + sha1(password)) and credentials are sent back to the server as { username, password }. On the server side, authentication does standard lookup pattern ( if user exists and has password equal to input then grant ).
If the connection between user & client is lost, the protocol class marks itself as dirty and disconnects itself from the user object. Any time after this point, to get access to the user object again, the client would have to repeat the authentication process with a new salt.
Am I missing something? Is there a better/more secure approach for a character stream based protocol?
The protocol you described addresses one attack, that is the a replay attack. However, you are very vulnerable to MITM attacks. The TCP connection won't drop when the attacker moves in on the protocol. Further more anything transferred over this system can be sniffed. If you are on the wireless at a cafe everyone in the area will be able to sniff everything that is transmitted and then MITM the authenticated session. Another point is that sha1() is proven to be insecure you should use sha256 for anything security related.
NEVER REINVENT THE WHEEL, especially when it comes to security.
Use SSL! Everyone uses SSL and it has a LONG history of proven secuirty, and that is something you can't build. SSL Not only solved Man in the Middle Attacks but you can also use Certificates instead of passwords to authenticate both client and server which makes you immune to brute force. The sun will burn out before an attacker can brute force a 2048bit RSA certificate. Father more you don't have to worry about an eve dropper sniffing the transmission.
Keep in mind that OpenSSL is FREE, generating certificates is FREE, and the singing of certificates is FREE. Although the only reason why you would want to sign a certificate is if you want to implement a PKI, which is probably not necessary. The client can have the server's public key hard coded to verify the connection. The server could have a database of client public keys. This system would be self contained and not require OCSP or CRL or any other part of a Public Key Infrastructure.
Your authentication seems solid but prone to man in the middle attacks as it does not ensure the integrity of the connection to the server.
I'd suggest to implement the SRP 6 protocol instead. It is proven to be secure, ensures the integrity of the connection and even creates a common secret that can be used to establish some form symmetric encryption. The protocol looks a bit difficult at first sight but is actually quite easy to implement. There is also a JavaScript Demo available on the project website and links to several implementations in different languages.

Categories