Reading Aranet4 sensor data from Python

I got myself an Aranet4 device to monitor CO2 levels in my office. The monitor gives pretty accurate readings and has very low energy demands (due to the e-ink display) (here’s the datasheet). While the intended way to read the measurements is to use the mobile app, it’s always good to be able to access the raw data yourself; you get to store as many readings as you like (otherwise limited to past 7 days) and can analyse them in any way you want. ...

February 5, 2023

Handling and confirming (interrupt) signals in Python

Let’s say you have a long-running Python script that should run uninterrupted or perform a graceful shutdown should a user decide to terminate it ahead of completion. By default, sending an interrupt (usually by pressing <Control-C>) to a running Python program will raise a KeyboardInterrupt exception. One way of (gracefully or not) handling interrupts is to catch this specific exception. For example like this: while True: try: do_your_thing() except KeyboardInterrupt: clean_up() sys.exit(0) This generally works fine. However, you can still trigger another KeyboardInterrupt while the clean_up is running and thus interrupt the clean-up process. Also, as interrupts might be sent accidentally (ever cancelled the wrong script because you thought you were in a different pane?), it would be nice to let the user confirm that the script should indeed be interrupted. ...

September 29, 2022

Python tarfile directory traversal

Currently, there’s a lot of hype around the behavior of Python’s tarfile module for extracting archives. In short: tarfile will not sanitize filenames in archives to prevent directory traversal attacks. For example, creating an archive and adding a file with a leading ../ will make the extract* methods create that file in a directory above the current one. This way (or by using an absolute path starting with /), a file can be written to an arbitrary location (given that the user executing the code has the according write privileges). ...

September 23, 2022

Bypassing regular expression checks with a line feed

Regular expressions are often used to check if a user input should be allowed for a specific action or lead to an error as it might be malicious. Let’s say we have the following regular expression that should guard the application from allowing any characters that could be used to execute code as part of a template injection: /^[0-9a-z]+$/ At first sight this looks OK: if we have a string containing only numbers and/or characters a-z we will match them and can continue. If we have other characters and are thus not matching this pattern, we can error out. Injecting something like abc<%=7*7%> or any other template injection pattern won’t work. Or will it? It depends… ...

May 14, 2022

Exploiting Python pickles

In a recent challenge I needed to get access to a system by exploiting the way Python deserializes data using the pickle module. In this article I want to give a quick introduction of how to pickle/unpickle data, highlight the issues that can arise when your program deals with data from untrusted sources and “dump” my own notes. For running the example code I’m using Python 3.8.2 on macOS 10.15; the demonstration of the reverse shell is just a connect-back to a loopback address. ...

April 5, 2020