The Internet of Broken Protocols: Showcase #5

(complete list of protocols:

Administrative note: I've posted solutions to the first 4 challenges. Some readers again found attacks that I wasn't aware of, but I'm not surprised anymore :=).

I'm interested in making my puppy protocols less broken, so please share with me your "patches". I'm also open to challenge submissions, please drop me a line if you have something cool to share.


In the past few years I've found many use cases in which doing crypto in Javascript makes a lot of sense. This challenge is one of those cases. Although the crypto is trivial the whole protocol is complex, involves many players and requires a basic knowledge of web security. Your task is to identify any weaknesses and propose a fix. You can leave your findings in a comment or email me at I'll update the post with my solution in a few days.

This protocol makes web ads load faster by reducing round trips needed to fetch the ads. It has 4 participants:

* The advertiser (e.g., Coca Cola, Nike, etc.) creates ads and uploads them to the ad serving system. An ad is a piece of HTML and Javascript and could be malicious.

* The ad serving system (e.g., DoubleClick, Facebook, etc.) verifies ads, rejects malicious, and serves supposedly good ads from

* The publisher (e.g., New York Times, etc.) gets ads from either the advertiser or the ad serving system and displays them on their website at Since ads could be malicious, they will be served via an iframe sourced to (so that they can't interfere with anything running on, thanks to the same-origin policy).

* The end user visits with their browser and sees ads.

As the name implies is an important origin because it serves all the ads and it also runs some other sensitive services. How the ad serving system validates ads is outside the scope of this challenge, but let's assume that it catches all malicious ads. Having said that, there's some weakness in the protocol that you can exploit to serve an arbitrary ad off

The protocol consists of two steps: provisioning and rendering.

# Provisioning

1. The advertiser uploads an ad to the ad serving system.

2. The ad serving system verifies the ad. If it is good, the ad serving system encrypts the ad with a random key, and wraps the random key with a long-term key, returns this piece of HTML

<iframe name="{ENCRTYPED_AD}" src="{WRAPPED_KEY}">

Both encryptions are authenticated (e.g., AES-GCM or some traditional encrypt-then-MAC scheme). When loaded on a browser, unwraps the key, and returns a small, cachable piece of Javascript that uses the key to decrypt the "name" attribute and displays the decrypted ad. Storing the ad in the iframe's name attribute is a neat hack (see the first comment of this bug to understand why it works), and it really makes ads load faster because the browser usually doesn't need to send any other request to fetch the ad.

# Rendering

1. User visits

2. The publisher contacts the advertiser who gives them the piece of HTML received at the end of the provisioning step (note: usually the publisher doesn't contact the advertiser directly, there's another player that I've omitted to simplify the protocol).

3. The publisher inserts the iframe to their website.

4. The user's browser loads the iframe and renders the ad.