Many robots and other manufacturing machines have their work orchestrated by computers on a factory network. If there is any kind of connection to the outside world, a malformed packet might provide a cyberattack entry and then cause malfunctions.
Similarly, in a remote-controlled navigation contest, your cyber:bot robot might also be vulnerable to malformed packets in addition to sniffing attacks. So, we'll now enhance the application from Cybersecurity: Navigation Control from a Keyboard [1].
In Your Turn: Handle Transmitter Exceptions [2], you already hardened the sender against accidentally entering malformed packet data, but the receiver is not yet hardened against intentional attacks. So, in this activity, you will harden the Terminal Control — Go Wireless! [3] app against both kinds of attacks.
# terminal_bot_controller_wireless_malfomred_packet_attack from microbit import * import radio radio.on() radio.config(channel=7,length=64) sleep(1000) print("\nSpeeds are -100 to 100\n") while True: try: vL = int(input("Enter left speed: ")) vR = int(input("Enter right speed: ")) ms = int(input("Enter ms to run: ")) dictionary = { } dictionary['vL'] = vL dictionary['vR'] = vR dictionary['ms'] = ms # Sends malformed packet attack if ms to run is negative. if ms < 0: dictionary = { 'vL': -20, 'vR': 20, 'ms': "Not a number!" } packet = str(dictionary) print("Send: ", packet) radio.send(packet) print() except: print("Error in value entered.") print("Please try again. \n")
# terminal_controlled_bot_wireless from cyberbot import * import radio radio.on() radio.config(channel=7,length=64) sleep(1000) print("Ready...\n") while True: packet = radio.receive() if packet is not None: print("Receive: ", packet) dictionary = eval(packet) vL = dictionary['vL'] vR = dictionary['vR'] ms = dictionary['ms'] bot(18).servo_speed(vL) bot(19).servo_speed(-vR) sleep(ms) bot(18).servo_speed(None) bot(19).servo_speed(None)
Let’s first make sure the sender micro:bit and receiver micro:bit in the cyber:bot work as expected with normal packets. Since we are going to leave the cyber:bot tethered with USB, we’ll use some short distance maneuvers with low speeds and short run times.
Now it is time to see the effect that a malformed packet can have.
If your micro:bit was not tethered, it would be stuck until a human came and restarted it by pressing and releasing the micro:bit module’s reset button! That is not always possible in a competition, but you can do it now.
The original Sender script terminal_bot_controller_wireless.py is explained here: How the Wireless Controller Script Works [5].
The exception handling added to the Sender script is explained here: Your Turn: Handle Transmitter Exceptions [2].
The cyber:bot Receiver script terminal_controlled_bot_wireless is explained here: How the Wireless Controlled Bot Script Works [6].
With that aside, let’s look at how the Receiver script terminal_controlled_bot_wireless was modified to send a malformed packet in response to a negative value.
At this point in the Sender script, the maneuver values have all been collected, and before the statements below, the dictionary looks like this: { 'vL': 25, 'vR': 25, 'ms': -1 }. If the ms variable receives -1 from ms = int(input("Enter ms to run: ")) earlier in the script, the if ms < 0: statement detects it, and changes the dictionary to dictionary = { 'vL': -20, 'vR': 20, 'ms': "Not a number!" }.
# Sends malformed packet attack if ms to run is negative. if ms < 0: dictionary = { 'vL': -20, 'vR': 20, 'ms': "Not a number!" }
If you guessed that the receiver script also needs protection with a try-except statement, you were right!
As mentioned earlier, devices on a network need both encryption AND protection from malformed packets. This does not normally take many lines of code. Like the earlier example, both Sender and Receiver scripts need the encrypt/decrypt function (ascii_shift in our example).
def ascii_shift(key, text): result = '' for letter in text: ascii = ( ord(letter) + key - 32 ) % 94 + 32 result = result + chr(ascii) return result
The Sender script also needs to encrypt the packet before sending:
packet = ascii_shift(17, packet)
…and the Receiver needs to decrypt the packet after receiving:
packet = ascii_shift(-17, packet)
In Python for computers (as opposed to MicroPython for the micro:bit), an encryption/decryption module would be imported. Instead of adding a comparatively weak encryption function, you’d import a module like PyCryptodome, Cryptography, or PyNaCl and use its stronger cryptography methods to encrypt and decrypt.
The last task in hardening the keyboard-controlled cyber:bot is to implement both encryption and exception handling.
Links
[1] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard
[2] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless-6
[3] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless-1
[4] https://python.microbit.org/v/2
[5] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless-3
[6] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-navigation-control-keyboard/terminal-control-%E2%80%94-go-wireless-4