Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

99% Invisible found out that Mazda has a bug in their radio that cannot parse special characters. See their article here: https://99percentinvisible.org/episode/the-roman-mars-mazda-...


Mazda’s response at the time was pretty disheartening too. Pay us for a firmware update and it’ll probably fix it. The owner said ‘no thanks’ because it was too expensive (and honestly ridiculous in principle in my opinion). Now Roman Mars, the owner of 99% Invisible, releases a separate version of every episode with “Mazda safe titles”


Seems like he should do the opposite, Only release versions with Mazda unsafe titles with a note "Doesn't work on Mazda. Contact their customer support here to complain"


It was the % in the show title that fouled up the Mazdas, so they were already doing that before the fix.

Even then it was a nearly invisible problem for the podcast itself, not something that would have been significant enough to investigate and correct for if that wasn't also content for the show.


The % sign broke mazda's infotainment system? That's really bad, I mean the % is even in the basic ascii character set. Unless they try to interpret titles as JS or HTML or something. That too would be bad.


% is used in C style format strings, which are famously a source of footguns.



That sounds like you would be able to exploit the bug... does it happen to use a libc that implements %n?

If so, just include a payload in the title that fixes the bug by patching the code :)


You don't need to exploit it, at least you didn't before...

They used to autorun specifically named files on a USB stick.

Then some busybody journalists picked up on that and Mazda was forced to lock it down despite the fact that there is complete physical separation from safety systems, and that situations like this article are exactly where it helps.


Although I don't disagree with your thought here and that was actually the podcast host's/other contributor's original hunch too, this wasn't actually an issue with interpolation. I know it sounds bizarre, but the paraphrasing of the podcast hosts and comments from the infotainment system code author suggest that he was treating all strings as percent encoded[0] without any checks or guards in place. Since "% I" isn't a valid character reference, it chokes on it.

[0]: https://datatracker.ietf.org/doc/html/rfc3986#section-2.1


Oooooh.

HackRF + open source DAB modulation stack + <carefully chosen combination of ASCII characters> = OTA... DoS? Jailbreak? Other miscellaneous interestingness?

In an age where everything's a computer, FM radio is just just another source of unsanitised input.


The % bug is a separate bug to do with a Podcasts's title, I suspect you just need a phone and an MP3 file with a suitably prepared title tag.

The original articles issue is a HD Radio (not DAB) issue to do with images, although it might still be a string parse issue of some kind as it apparently involves "image files with no extension", so presumably filenames? So the RF side can indeed be fun on consumer electronics with modern digital standards. Another example is this claimed RCE over DVB-T: https://twitter.com/David3141593/status/1481963959532011520


Even more sadly, HD Radio is a closed, propretiary format.

Unlike DAB or DAB+ which are open standards with FOSS implementations out there.


HD Radio is closed and proprietary, but there is at least one FOSS receiver out there: https://github.com/theori-io/nrsc5

The protocol itself is actually standardized: https://www.nrscstandards.org/standards-and-guidelines/docum...

It's just the audio codec that's proprietary, but it's basically just a slightly modified version of AAC so it's been decoded.


My understanding was that the implementation was protected by patents. And can one call something a standard if the codec is not documented and needs to be reverse engineered?


Like I said, it's the protocol that is standardized. HD Radio as a whole is not, because of the codec. I think it's absolute BS that the FCC went down the path of a proprietary format, but it's the way things are. And the fact is, we do have at least one FOSS implementation. Since it's not DRM, I believe (but IANAL) that it's perfectly legal to reverse-engineer it.

I doubt Xperi really cares, since HD Radio is a trademark so it's not like you could build, sell and market an "HD Radio" device without licensing from them anyway.


You're sort of on the right track if you're familiar with URL/percent encoding, actually. I have no idea why, but paraphrased comments by the podcast hosts from the code author (they contacted him) suggest that he was attempting to decode all incoming strings as if they were percent encoded[0] without any failsafes in place. Since "% I" isn't a valid character reference (or even hexadecimal), it chokes on it.

[0]: https://datatracker.ietf.org/doc/html/rfc3986#section-2.1


Given other people saying there's Javascript and Opera involved, my guess is that the % is ending up unescaped in a URL.


> a nearly invisible problem

99% invisible


Talk about cutting off your nose to spite your face.


That’s right. When a podcaster forces their stuff to not work on my car, I spend my time contacting the car company to get collective action through for change. I don’t hit the next button and listen to something else. This is how I and most other humans function.


He wasn't forcing it. He was just accurately using the title of his damn podcast. The suggestion is that he stop issuing a special Mazda-safe version.

I agree, this is a problem for the makers of the broken radio. But Roman Mars is just a nice guy.


Probably.

I started to unsubscribe every podcast with annoying ads or hosted at megaphone.fm, but I'm in minority.


> the owner of 99% Invisible

Nit: he sold it.

https://www.theverge.com/2021/4/26/22403852/siriusxm-roman-m...


Ah, I see, so host and producer but not owner. Good to know!


I have a Mazda, and it also parses ogg metadata strangely; if you have multiple fields starting with "ARTIST" then it will fill the artist field with all of them, but without erasing the buffer first.

When I first loaded my music collection, it stuck in a reboot loop, so I have a script that sanitizes the metadata for exporting to my car


My Citroen does that. If you connect to it with BT and play anything with Cyrillic characters in the title from Apple Music it trashes the display trying to render it.


My Toyota - a Japanese car - cannot display song titles in Japanese. I kind of assume this is a localisation issue rather than something that would happen in Japan though, although the car entertainment is terrible in many other ways too so who knows.


Most likely because the embedded system does not use UTF-8, just like the phones before iPhone, a Nokia phone sold in US sometimes cannot even be flashed to display CJK characters due to CJK support require more ROM space.


My Garmin watch is like that. If you want Japanese language support you have to buy the japanese model which is obiviously only for sale in Japan. So dumb that I can't just flash the japanese firmware on. Instead I have support for Russian which I have no need for.


Wow. Not many automakers can claim to have an infotainment system notorious enough to get coverage on local public radio and a design-oriented podcast.

Weird intersection.


Maddeningly, that episode never arrives at the actual bug. Via a thread the Mazda owner posted on Reddit, I found this great writeup: https://github.com/Hamled/mazda-format-string-bug#readme

TLDR: The problem is the `% In`, and specifically the `%n` - when printf sees that, it tries to store data in memory. Failing to do so, it crashes.


Oh god. Format string bugs in infotainment systems that can be triggered by careless radio stations. What could possibly go wrong.


This is so weird.

I read [1] which someone linked to, and it all seems to make sense. But it doeesn't!

I tried compiling this with gcc 11.2.0:

    #include <stdio.h>

    int main(void)
    {
      printf("%99 Invisible", NULL);
      return 0;
    }
And it won't compile. I get:

    test.c: In function ‘main’:
    test.c:5:14: warning: unknown conversion type character ‘ ’ in format [- 
   Wformat=]
        5 |   printf("%99 Invisible", NULL);
          |              ^
    test.c:5:10: warning: too many arguments for format [-Wformat-extra-args]
        5 |   printf("%99 Invisible", NULL);
          |          ^~~~~~~~~~~~~~~
which I would expect; you can't have a field width (the "99") and then the space-padding flag; flags go first. Also I can't find any coverage of %I (capital 'I', as in "Invisible") in the manual page for printf(3) on that system but that might just be an old manual page, GCC does seem to recognize it.

Removing the cruft and trying plain %In gives a warning, but I guess whoever built the car's radio UI ignores warnings.

I guess it's possible that the system doesn't use a standard-compliant enough C library, so it's printf() implementation does something ... creative with this string.

Anyway, classic case of the lovely foot-gunnery that is %n in the wild! Sorry for all the car owners, of course. :/

EDIT: A commenter pointed out that the above are "just warnings", oops. :) More oops on me for not spelling the freaking title correctly, of course it's "99%" and not "%99" .. .need more coffee, clearly. Sorry.

For people less used to C, the error here more or less seems to boil down to passing an untrusted string as the special "format string" for the printf() function. That function will interpret the contents of the string, and the percent symbol is how its special formatting directives start. Characters following a percent symbol will cause it to do stuff. The proper fix is usally to change

    printf(string);
to

    printf("%s", string);
or use some other I/O function altogether. The above simply says "here's a string", by using the programmer-selected string "%s" as the format, instead of the untrusted string coming from the outside.

[1] https://github.com/Hamled/mazda-format-string-bug#readme


The name of the podcast is "99% Invisible", not "%99 Invisible".

"99% Invisible" produces the expected result: https://godbolt.org/z/Mc9zPKWdq


You should also keep in mind that the string is essentially user input at runtime for the radio, so the compiler can't throw warnings or errors for it even if it wanted to.


Clang gives you this warning if you do that:

    <source>:6:12: warning: format string is not a string literal (potentially insecure) [-Wformat-security]


> And it won't compile.

Just are just warnings, it builds fine despite them.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: