Jesse Sheehan

Encryption, Stacktraces, and Name Suppresion

2024-03-18

All images served up for Stuff’s articles are served up the endpoint https://www.stuff.co.nz/media/images/ID where ID is some long base64-encoded value. Here’s an example from an article on the front page as of the time of writing. This endpoint appears to also be doing some resizing of the image. This is all well and good and is in fact, common practice.

However, if we take the base64 id and change it manually - let’s say we change the first character to a 0 - then instead of a boring error page we are met with a very intesting stacktrace:

The stacktrace from changing one character in the image ID.
{
  "status": "INTERNAL_SERVER_ERROR",
  "message": "Unexpected character ('�' (code 65533 / 0xfffd)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n at [Source: (String)\"\\u0008��O��퉢�!�\\u0011\\u0013i\\u000B/platform-admin-media.stuff.co.nz/s3fs-public/2024-03/0WTdm6qIbf9bACLSvn1XSp8oqPc_0.jpg?VersionId=meSADsuNl6BRJyf0Oq61Lr7PSVRvAOwQ\",\"mode\":\"fill\"}\"; line: 1, column: 2]"
}

We can tell a few things from the information here:

So, what happens if we change a character later on in the ID?

Changing a character further on in the ID.
{
  "status": "INTERNAL_SERVER_ERROR",
  "message": "Illegal unquoted character ((CTRL-CHAR, code 30)): has to be escaped using backslash to be included in string value\n at [Source: (String)\"{\"image\":\"https://platform-adminc¾2�\\u001E�i\\u0009T�-��\\u001DKnz/s�fs-public/2024-03/0WTdm6qIbf9bACLSvn1XSp8oqPc_0.jpg?VersionId=meSADsuNl6BRJyf0Oq61Lr7PSVRvAOwQ\",\"mode\":\"fill\"}\"; line: 1, column: 38]"
}

Hold on a minute! Let’s compare those URLs from each of these stacktraces:

�\\u0008��O��퉢�!�\\u0011\\u0013i\\u000B/platform-admin-media.stuff.co.nz/s3fs-public/2024-03/0WTdm6qIbf9bACLSvn1XSp8oqPc_0.jpg
https://platform-adminc¾2�\\u001E�i\\u0009T�-��\\u001DKnz/s�fs-public/2024-03/0WTdm6qIbf9bACLSvn1XSp8oqPc_0.jpg

Surely we can’t just stitch the good bits of each of these together to get a valid URL. Oh goodness, we can!

How Did This Work?

Based upon how the data in the stacktrace is returned, it appears that the big ID in the URL is in fact encrypted using some kind of ECB scheme. Electronic code book, or ECB, is a method of encrypting data based on some secret key. However, ECB encrypts chunks of the data independently from the others and so opens itself up to the kind of interrogation we have just performed.

To learn more about ECB and why pretty much everything else is better than it, have a look at this Stack Exchange post.

As an aside: one could probably figure out what the secret key is and then maybe even use that to do some SSRF.

So We Can Access The Original Images? So What?

In a nutshell: metadata. The images that are served up by this broken endpoint don’t contain any metadata at all; it has all been stripped out. However, the original images contain all the metadata. Take a look for yourself:

The metadata viewed using OnlineExifViewer.

I know that this isn’t that exciting but it does create some interesting opportunities.

Breaking the Law?

Name supression in the New Zealand is meant to keep identifiable information of certain people out of the media. This can be either temporary or permanent and often granted when it is determined that having their name and details published would result in extreme hardship.

Take this article as an example. It an includes an image that we can pull the metadata from by using our little trick.

Whoops!

And this metadata includes this man’s full name. Since this is unintentional I don’t believe that this would count as breaking the law in this instance (sorry for the clickbait!).

Disclosure

There was really only one failing here: never show the end user a stacktrace! (and if you do, then don’t use ECB to encrypt your URLs!)

I reported this to Stuff on Sunday the 17th of March 2024 at 9:30am with specific mention of the name suppression issue. By 1:00pm that same day the image was removed from the article and the root cause was addressed the very next day. Now, messing with the URL gives a generic error page. Fantastic!

The new error page.
Return to the top