It doesn't relate specifically to any programming language or technique, but still:
You know how you can use programs like Wireshark to read packets going through your computer (or router, more accurately)? These packets can contain secret information that must be encrypted somehow, like username and password for some systems. But even without this information, one can recreate these packets and obtain the same information, no? For example, I can send these packets from my computer, pretend that I've requested the service and obtain access that way to the given system. How is that prevented?
Also, a kind-of-related question: when a router receives a packet, how does it know to which computer to direct it to if multiple computers are connected to it in an LAN?
What you describe is called a replay-attack - to prevent this sort of attack the respective protocol needs to have some built-in features (like some unique ID per request and becomes invalid after being received the very first time and/or becomes invalid after a certain amount of time and/or some timestamp etc.).
Related
I have an imaginary program that I've distributed to dozens of clients which involve their home thermostats. The script performs two tasks:
When a request from my server is received, the script will modify the temperature of the user's thermostat to the designated temperature.
When a request from my server is received, the script will reply back the current set temperature of the thermostat.
The program being ran on the clients computer is programmed in a scripting language and is not compiled. The source code can be modified at any time and the new modified script can be re-ran at will.
I have three problems:
What changes can I make to the script running on the client's computer and/or the program running on my server such that I feel more confident that the user did not tamper with the source code of the script?
How can I be relatively sure that the user is running the most up-to-date version of my program?
Without using IP addresses, how can the client know a request came from the server and not another client?
I understand that code running on a client's PC is impossible to police. However I want to make it less trivial for someone to modify the source code of my script.
As you correctly point out, it's impossible to guarantee nobody modifies your source - or replaces your client with an entirely different one they write from scratch. It simply cannot be done and it's not even because your client is implemented as a script; binaries can be replaced/spoofed as well.
What changes can I make to the script running on the client's computer and/or the program running on my server such that I feel more confident that the user did not tamper with the source code of the script?
Make your script compute a cryptographically secure hash of its own source code and send that hash to the server. You'll know what the hash of your client's source code is and can make sure this is the same. This does not guarantee the client is not pretending to be running your source (they could compute the hash of your client and send it while running entirely other code) but this will prevent casual and/or accidental modifications to the script from working (i.e. it guarantees any spoofing is intentional).
How can I be relatively sure that the user is running the most up-to-date version of my program?
Include a version number in the client source code you distribute so you can guarantee each new version has a unique hash with almost 100% probability. Then, you can have a history of versions with corresponding client hashes.
Without using IP addresses, how can the client know a request came from the server and not another client?
This one you can actually do correctly. Have your server use its private key to sign the messages it sends, and have your client verify the signature using your server's public key (which the client source code can contain). Since only your server could possibly have signed the messages with the correct private key, the client can be confident that success with the corresponding public key means your server sent the message.
If it is a home thermostat, the whole architecture is likely wrong. Your server will not be able to connect to devices on your customers' home networks (or at least they will have to perform configuration that you should not expect to be done).
So in a better architecture, you have your service on the internet, to which your devices connect. Note that these connections can be long ones as well, not necessarily just the typical short-lived http connections.
The client software running on a device can be modified by your users arbitrarily, or they can make other clients, you cannot do much about this. In reality, unless this is very valuable for some reason, nobody will bother, especially in a commercial way, because any change to your api will break 3rd party clients. One option to still make client code harder to modify is obfuscation, but be aware that it is not really a security feature, but it does increase the necessary effort.
Checking the version of the client is straightforward, it can just be sent with requests. However, the usual way to achieve what I think you wanted is to version your API. You probably don't care about the exact version of the client, but you do care about which version of the service (the API) it supports. If that is your goal, look into API versioning.
Authenticating the server in this architecture is straightforward if communication uses TLS. With TLS (eg. https), server authentication is implicit. You still want to authenticate the client though, which can be done via the standard means, a username-password, tokens or a client certificate. When talking about devices, you might want to consider a device with a TPM chip so that it can securely hold secrets, but whether you need that depends on the exact scenario and your threat model (who will have physical access, what happens if they can impersonate other devices and so on).
I am working on a project where an Arduino will send measurements and receive commands through an Ethernet interface and a REST API to open and lock a door. For all means, we can consider that the devices are protected, but that the Ethernet network may be accessed. Therefore, a Man-in-the-middle attack is plausible.
The commands to open/lock the door will be part of the reply of an HTTP GET request. In order to prevent a MITM attack where the response is faked to open the lock, I want to use some kind of encrypted response. Now, Arduinos lack the power to use HTTPS, and I want it to be Arduinos because of costs and ease of development.
I have come up with the following scheme:
Both the Arduino and the server have an identical set of index-value registers. The value will be used as a code to encrypt using AES-128.
When the Arduino sends its GET request, it also sends a randomly selected index, indicating to the server which value to use to encrypt the open/lock command.
The server sends a clear text response (JSON) where the command field is an encrypted text.
The Arduino will decode it and apply the required action.
The Arduino will also send some sensor data from time to time. In this case, it will send the index of the code it used to encrypt the data and the encrypted data.
The set of index-value keys is large, so repetitions are rare (but may occur from time to time).
My question is, is this scheme secure? Am I missing something? Is there any other more tested alternative for securing these interactions that doesn't involve using a more advanced platform?
Thanks in advance!
Use an ESP2866 based Arduino. It does not cost significantly more, it uses the same tools but you can use SSL instead of rolling your own solution. I have used the Wemos D1 boards and they work as a drop in Arduino replacement.
I'm a security/crypto newbie looking for some advice on whether my system is secure, and if not, whether crypto is the right answer for me. Here's my situation:
I am sending TCP messages via zeroMQ req/rep between remote servers
The system has a fixed number N senders, and 1 receiver
I am not TOO worried about others reading my message (although preferably not), but I absolutely do not want others to be able to masquerade as one of my senders, as the messages contain instructions for the receiver to execute
Latency/performance is a large factor. I expect 100k+ messages/second to be sent
Ideally, is there a way for me, since I know who are the authorized senders, to specify on my receiver to only accept messages from so-and-so and be safe knowing that? Either in zeromq itself or other method?
Thanks all for your help!
If you share an AES key between all your senders (preferable via SSH or reliable other public key infrastructure) you would be quite safe. The receiver doesn't have to know exactly which system that sent the request, it's the same key all over.
BUT: since you are sending a lot of packets that all are small you HAVE TO make sure you pad your data in a clever way (likely with transaction id that you have a counting check for on the receiver's end, sender id + some random data). If you don't, you will be open for replaying attacks, whether the malicious person has the key or not.
Another fun interesting approach is to send challenge-responses from the receiver somehow, i. e. a random number that is hashed together with some common key (which one of them should be considered the "salt"?). And please, do not the symmetric encryption key for this, please - if someone manages to attack the challenge/response somehow you will also give them your holy shared key.
A response with the made hashing, the "answer" to the challenge, proves that the senders have the same secret key as the receiver / challenger have, and can be quite quick (SHA-1 or similar are fast).
Have fun. Don't you never, ever dare to use your solution for real.
I am developing a mobile application which sends some encrypted data to a Bluetooth device and this Bluetooth device sends the data to server. My question is that in this case how can I prevent replay attacks. Someone might use a fake Bluetooth device to get the signals and send them to the server.
The mobile application works in offline mode and has no connection to server. So using a synchronized nonce or counter doesn't help.
I can not also use time-stamp to narrow the attack window because mobile phone's time might not be correct (synchronized with a time server).
Communication between my mobile application and Bluetooth device is one-way and my mobile application can only send data to the device.
One way to do this would be to use a counter, but allow it to skip a large number of steps. For example if the last counter value you've seen from phone A is 123 and you get something with a counter value of 156 then you accept it, but anything outside the range of [124, 1000123] you discard (1000000 being completely arbitrary and dependent on your use case).
This would prevent a replay attack, but you do have to take care that the transmissions aren't malleable or it would be trivial to forge counter numbers. This could be accomplished by having a secret per device MAC key (which would only be possible if the server and phone communicate beforehand).
It's worth stating that it would be good for the transactions to be authenticated (only phone A has the capability to generate a message saying it's from phone A) or an attacker could move up the counter very quickly and do a denial of service on phone A. However, from the way you phrased the question it sounds like it's something you've already dealt with.
I am pretty new in this kind of things.
I have a local area network, accessed by some users via cable some and via wifi others.
I have developed a local application in php which receives only some of the LAN clients as authentic users; they can be identified by the system with an algorithm of key exchange similar to Diffie–Hellman's, to estabilish a secret key. The client then asks to be identified throug such a channel.
The problem is, MITM attack is possible in this kind of situation. I read wikipedia about how such an attack is executed: somebody listens the messages of the two, and puts himself between them creating two different secret keys for the client and server.
This attack is reality, so it must be possible; but I do not understand how it happens in a LAN:
the attacker can listen to the messages, and inject message of his own, impersoning the two subjects of the communications by forging https' IP fields if necessary...
But he can't prevent the original unforged message to reach, concurrently (but also later, because of forging process taking the attacker computer some time) with his malevolent forged one, the recipient! Especially in a wifi connection, which cannot be cut off for a single user, for example cutting his cable.
So, client and server receive two different http requests from each other, a true and a forged one; isn't this a way for them to recognize that such an attack is in progress?
Maybe this question is newby-ous; as I said, I am pretty new at this.
I think that is a scenario where you would use a digital signature (which also uses the idea that asymmetric encryption/Diffie-Hellman uses, that is "public and private key") to sign your messages.
The MITM attacker can not forge a message with a bad "from" and then sign it with the private signature of the original sender. The recipient uses the public part of the signature/certificate to validate the message. So that way he will not only know he is being attacked but also which message is genuine.