Encryption, Stacktraces, and Name Suppresion
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:
{
"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:
- The shape of this stacktrace tells us that this endpoint is likely written in Java.
- It looks like we have a partial URL in there that might contain the original image.
- And if that’s the case, then from
s3fs-public
we can assume that there is an S3 bucket out there somewhere with all of the photos sitting in it.
So, what happens if we change a character later 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:
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.
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!