In this first activity, you will experiment with the countdown timer app from the Send and Receive Packets activity [1]. Its original form is vulnerable to malformed packet attacks you will learn how to harden it against them. The malformed packet attack will cause the receiver to throw an exception. At that point, it will become unresponsive until its script is restarted or reloaded with the Flash button.
This activity requires two micro:bit modules running different scripts, a Sender script and a Receiver script.
Running 2 micro:bit modules: You can either connect each micro:bit to a separate computer or connect both to separate USB ports on the same computer.
# countdown_sender_w_malformed_packet_option from microbit import * import radio radio.on() radio.config(channel=7,length=128) sleep(1000) print("Countdown App") print("micro:bit sender") while True: text = input("Enter countdown start: ") value = int(text) message = input("Enter message after countdown: ") dictionary = { } dictionary['start'] = value dictionary['after'] = message # Sends malformed packet if value is -1 if value is -1: dictionary['start'] = "Not a number!" packet = str(dictionary) print("Send: ", packet) radio.send(packet) print()
# countdown_receiver.py from microbit import * import radio radio.on() radio.config(channel=7,length=128) sleep(1000) print("Countdown App") print("micro:bit receiver\n") while True: packet = radio.receive() if packet is not None: print("Receive: ", packet) print() print("Parse: ") dictionary = eval(packet) value = dictionary['start'] message = dictionary['after'] print("value = ", value) print("message = ", message, "\n") while value >= 0: print(value) sleep(1000) value = value - 1 print(message) print()
Let’s first make sure the sender and receiver micro:bit modules work as expected with normal packets. If the terminal doesn’t display what you type or display messages, try closing and reopening the terminal by clicking Close Serial and then clicking Open Serial again.
See Texting with Terminals [3] if you need a reminder on how to set up the serial connection to the micro:bit modules.
Now, it’s time to examine the effect a malformed packet can have on a script. At this point, the Sender serial terminal should be prompting you to enter another number of seconds to count down.
For background info on how the scripts work without the malformed packets, see How Radio Data Packets Work [4] from the Cybersecurity: Radio Data tutorial.
Here is an example of a properly formed packet, sent by the sender micro:bit:
{'after': 'All done!', 'start': 3}
Even when you type -1 for the countdown start, the dictionary that’s created is this:
{'after': 'All done!', 'start': -1}
…but then, the script reaches these statements:
# Sends malformed packet if value is -1 if value is -1: dictionary['start'] = "Not a number!"
After that, the packet is changed to this:
{'after': 'Add done!', 'start': 'Not a number!'}
In the receiver script, the value corresponding to the dictionary’s 'start' key is stored in a variable named value. When the receiver script gets to this line:
value = value - 1
…it tries to subtract 1 from the 'Not a number!' string, and throws this runtime exception: TypeError: can't convert 'int' object to str implicitly. After the exception, the receiver micro:bit will not respond until it is restarted.
The receiver’s runtime exception from the malformed packet is easily preventable with exception handling. For the basics of how exception handling works, try or review the Exception Handling Primer [5].
After placing the susceptible portion of the script into a try: block and handling the exception with except:, the receiver will no longer stop running its script when it receives that kind of malformed packet.
This modified receiver script puts the while value >= 0: countdown loop into a try-except statement.
Applications don’t normally have just one vulnerability, so it’s best to test for more than one scenario. For example, what if the dictionary packet is changed to some other object, like maybe a string? This is just one example of the kinds of questions that application security validation specialists help with as part of software development.
Your receive script is hardened against one kind of malformed packet attack, but what if there are more? In the first example, the dictionary contained an unexpected term. What if the dictionary is instead not a dictionary? That would cause another kind of exception that the receiver script is not yet hardened against.
Links
[1] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-radio-data/send-and-receive-packets
[2] https://python.microbit.org/v/2
[3] https://learn.parallax.com/tutorials/language/python/cybersecurity-radio-basics/texting-terminals
[4] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-radio-data/how-radio-data-packets-work
[5] https://learn.parallax.com/tutorials/robot/cyberbot/exception-handling-primer