Cutting the Lights: Vulnerabilities in a Billboard Lighting System

On my way home one night, I noticed a highway billboard sign whose lights had switched on as I drove past. It caught my attention and I wondered how those lighting systems were controlled (I mostly assumed either timers or daylight sensors). I researched it a bit and wasn’t surprised to find SmartLink which, as their website says, is “a cellular M2M controller system designed to remotely control and monitor billboard lighting applications. Over 50,000 systems have been installed to date.” I noticed the SmartLink Client Billboard Login link on their site didn’t reveal much, but things got interesting when I found their Android app.

Opening the app doesn’t allow the user to get far without authenticating:

Next, I decompiled the APK and began analyzing the source. After searching around for hints of API communication, I found a single class that seemed to handle all requests. Below are a few of those methods:

Note the sendData  method which seems to be a helper method for actually performing the HTTP requests:

A lot of interesting things happening here. Analyzing the above method, I didn’t find evidence of a session state mechanism that would authenticate the user during requests. In order to confirm this, I decided to debug the app with jdb and attempt to invoke one of the requests manually. After I patched the APK for debugging and installed it, I attached to the process and set a breakpoint in the doLogin  method.

On my device, I attempted to login in order to trigger the breakpoint. Once execution was paused, I manually invoked the getCustList  method with a dummy UserID  parameter to check whether the request would be formed and completed. To my surprise, it returned a full dump of the entire customer list:

Here is a look at the HTTP request:

This confirmed that none of the API endpoints employed a session state mechanism, meaning an attacker could completely manage/control any billboard in the system. Below is a look at another view of the app that displays a customer’s assigned structures:

The API was also using HTTP, meaning it was sending user credentials (and all other traffic) in plaintext. If this wasn’t bad enough, more research revealed some other fundamental flaws.

Visiting the web directory at /mobile/  showed a directory listing. Included among the files was a renamed/downloadable PHP file containing the API’s source code, as well as a log file containing every user login entry, with plaintext usernames and passwords, for the past 6 months.

It seemed OutdoorLink had broken every basic rule in the book and left all of their customers carelessly vulnerable to attack — it would be simple for an attacker to make his own “highway adblock” by killing all of the billboard lights in the system.

I reached out to the Director of Engineering at OutdoorLink and quickly heard back. I immediately forwarded him all of the information describing the vulnerabilities (and design flaws) above. He responded promptly by disabling directory listing on the server and removing the files that I mentioned above (though they are still on archive.org). The API issue was treated with a little less urgency than I expected (OutdoorLink attributed this to a lack of resources),  but it was eventually addressed.

Disclosure Timeline

2015-07-29: Initial report sent to OutdoorLink
2015-07-29: Response received, directory listing and file issues addressed
2015-08-07: Follow up with OutdoorLink, API still vulnerable
2015-08-07: Response received that they’re developing new web services and apps
2015-08-10: Follow up to request timeline of new web service and app
2015-08-13: Response received, fix not expected for weeks due to resources. App is now forcing SSL.
2015-08-19: I make several suggestions for handling session state and we discuss. OutdoorLink moves forward with implementation.
2015-08-28: Android App version released with new auth scheme, waiting on Apple App to be updated before disabling old API
2015-10-04: Follow up again, iOS app completed, submitting to App Store for approval
2015-10-09: Issues with iOS app, needs more work
2015-10-20: iOS app resubmitted to App Store
2015-11-03: iOS app approved/released, old API decommissioned — confirmed resolved

OutdoorLink was very receptive to my reports and thanked me for reaching out.

Share this: Facebooktwittergoogle_pluslinkedin
  • Did you receive any compensation for this find?

    • Matson, Gregory P.

      That’s a dumb question. You really think he’d answer that? Come on.

      • everett

        Why would that be dumb? We’re in the age of bug bounties. It’s relevant.

      • gyozafiend

        Matson, There are no such thing as dumb questions. Just Dumb Answers. Come on.

  • Erez Yalon

    Nice work Randy.
    I would like to post a summary of this text with your images to LinkedIn.
    Is that OK?