Saturday 12 September 2020

Providing source code when submitting papers: how to give anonymous but protected access

Update 30 November '21: if you simply want to anonymize your GitHub repository and are OK with it being public, then consider using


When submitting an academic paper for review, it is often a good idea to provide access to the research code as well. Even if reviewers only rudimentary scroll through the code, it shows you are committed to releasing the code once the paper is published.

The problem is that often you want to provide reviewers anonymous access to your code, but don't want the code to be accessible publicly. In this blog post, I'll explain how to provide read-only (anonymous) access to a GitLab repository. The end result is that you can instruct reviewers to execute the following command:

git clone

where they use the token "anonymous" as the username and a generated password. This token provides read-only access and can easily be revoked if needed (this login info isn't a GitLab account). You can easily include these instructions in a paper, giving reviewers access to the code without revealing your GitLab username in the URL, and while protecting access to the code using a password.

How to configure this in practice?

First, to assure the git URL won't contain your username, you have to create a new group on GitLab with an anonymous name. The name of this group will replace "anongroup" in the above example URL.

Second, in this group create a new project (i.e. repository) with an anonymous name. The name of this project will replace "anonproject" in the above example URL. You will now have a git URL containing only anonymous identifiers.

Finally, to provide read-only access to this repository, open the repository, go to Settings, and then to Repository. Then create a Deploy Token and select that the token provides read-only access. For the username we'll pick "anonymous". Then configure when the token expires: make sure it stays valid during the complete review process! Finally, click on "Create deploy token", and GitLab will automatically generate a password for this token.

Viola! The resulting token can only be used to clone the repository. Note that this token cannot be used to log into GitLab and view the repository in a browser. This token can only be used to directly clone the git repository using, for example, the command above.

Remember to create commits under an anonymous identity as well! That can easily be done using:

    git config "Paper 1"
    git config ""

The configured name and email will only be used in the git repository you are currently in. A final tip is to include a README file in the repository, which can for example be written in Markdown and then converted to HTML.

Friday 24 July 2020

Protecting Wi-Fi Beacons from Outsider Forgeries

We recently presented the paper Protecting Wi-Fi Beacons from Outsider Forgeries at the WiSec 2020 conference. You can view the recorded presentation on YouTube:

After the presentation we received a lot of interesting question, and it's useful to discuss these in more detail. So let's dig into some of the details of our work!

How does beacon protection handle hidden networks?

A hidden network still sends out beacon frames just like a normal network. The only difference with a hidden network is that its beacons do not contain the SSID of the network. As a result, all our attacks apply to hidden networks as well. Additionally, our defense works exactly the same for hidden networks.

Did you observe any clients recover from attacks after they received a beacon from the real AP?

In our attacks we spoof beacons to influence the behavior of clients. We found that with some attacks, such as those manipulating the throughput of clients, the effects of the attack are reset when the victim receives a real beacon (after we injected a spoofed one). In this specific case however, we found a way to make the effect permanent, and I refer to the second paragraph of section 3.3 in our paper on how we accomplished that.

Additionally, our transmission power attack did not work against all operating systems, and this might be because these devices reset their behavior back to normal when receiving a real beacon.

What makes certain devices more vulnerable than others?

Certain devices or operating systems may not support all features that are advertised in a beacon, and therefore they may not be affected.

Another reason why some devices are not affected to certain attacks is because they do not constantly track all information in a beacon. Put differently, some devices initialize parameters when they connect to the network, and will not update these parameters while being connected. As a result, if we spoof a beacon with different parameters, these updated values will simply be ignored.

What are the differences between beacon protection and Management Frame Protection of 802.11w?

We purposely designed beacon protection to be similar to Management Frame Protection. In particular, they both use the same underlying cryptographic primitives. This will hopefully simplify implementations and encourage vendors to adopt our defense.

Unfortunately, Management Frame Protection did not authenticate beacons and left them unprotected. In order to also protect beacons we cannot simply protect them in exactly the same way though: several edge cases have to be handled differently. This is discussed in more detail in section 4 of the paper. For example, care is needed when handling "Multiple BSSID" beacons, we need backwards compatibility, we added a capability to report rogue APs, and we are using a new beacon protection key.

Why do we need a new key? Why not use the same key used by Management Frame Protection?

Using the same key will only be secure if the same nonce (i.e. replay counter) will never be reused. This would imply using the same replay counter for beacons and other broadcast management frames. Unfortunately, this is surprisingly hard to implement: in practice the Wi-Fi chip may reorder beacons and broadcast management frames right before their transmission (after they were authenticated!). Preventing this is non-trivial. Unfortunately, we also cannot use two different replay counters under the same key, because they would again result in nonce reuse. All combined, the easier solution in practice is to generate a second key.

Have you thought about clients maliciously reporting fake beacons even if there aren't any?

We only prevent outsider attacks, so an insider can indeed maliciously report fake beacons. The impact of this is likely low though. The idea behind reporting fake beacons is that the network administrated is aware that something fishy is going on in the network (e.g. someone setting up rogue APs). So maliciously reporting fake beacons will annoy the network administrator, but other than that will likely have no impact.

In practice we can also consider fake beacon reports valid if multiple clients send a report. Additionally, in an enterprise network such as Eduroam, the network administrator can determine the username of the device that reported a fake beacon. This means such misbehaving insiders can be issued a warning or even banned from the network.

Sunday 21 June 2020

Riving a router stuck in an infinite reboot loop

When doing wireless security research, you need enough devices to test and confirm your findings. Results have to be practical, after all. Due to COVID-19, this became more tedious: access to the lab is being limited, making it harder to test many devices.

Because I wanted some extra devices to hack play around with, I realized that I still had a router from my ISP. The problem is that I bricked that router more than a year ago: stuck in an infinite reboot loop, after accidentally including a backtick ` into the wrong field. This menacing backtick likely caused some start-up process to fail, trigger a reboot of the router. I didn't want to bother with calling the ISP and explaining that yes, I already rebooted it — in fact it rebooted a thousand times already — before getting it replaced. So I simply used my own router instead.

But now it became interesting to get that router working. So how can we revive it? Pressing the reset button in various ways, and for more than 30 seconds, had no effect. That's not good... On the bright side, the router did seem to briefly be operating before it reboots. Maybe that gives enough time to quickly navigate to the management interface and reset the field? Unfortunately not, the management interface is operational for just one second.

My solution was to make a script to detect when the router is operational, and within the available section automatically navigate the management interface, reset some options, and hope that will fix it. To immediately detect when the router is being (briefly) operational, I wrote the following scapy script:

The above script rapidly sends ARP requests for the IP of the router. Once an ARP reply is received the scrip exits. This needs to be run as root because we're using raw packet injection.

One the router is accessible, we need to rapidly navigate to its management page, log in, and try to reset it from there. Luckily, with selenium we can do exactly that:

The above code only worked after tweaking the sleep calls. If the were even a tiny bit longer, the router would already be rebooting. If they were shorter, the page wouldn't have loaded yet. After a few attempts, this managed to reset the router!

The router did behave unusual after this reset. Wi-Fi was working in the 5 GHz band, but not in the 2.4 GHz band, and some other strange behaviour. This was fixed by manually resetting the router a second time. Probably when we reset the router for the first time it rebooted in the middle of resetting its configuration, which resulted in an inconsistent configuration. Anyway, now everything worked, without having to make annoying calls to the ISP.