Skip to content(if available)orjump to list(if available)

A QR code that sends you to a different destination – lenticular and adversarial

Normal_gaussian

I guess an interesting attack would be a screen in a public setting that alters the QR code based on information it has about the current user, without appearing to change significantly.

setup:

- make the QR code as a half/half code

- have a system to decide preference of target based on external input (e.g. camera based characteristic evaluation)

- make slight dynamic alterations to the colours of the code to bias the probability of it being picked up as the desired target. Desirable black/white can be made blacker/whiter, less desirable less so.

Where to use it maliciously:

- anywhere where people provide feedback - present alternate feedback forms to different demographics to engender the most positive (or negative) results.

- pretend to offer some form of probabilistic chance to win a prize, but bias winning to some identifiable characteristic. e.g. race, age, "beauty"

- target a specific person - have them join a different WiFi network, alter a payment page, etc.

In a static setting its less effective. I can't immediately think of a static attack that benefits from siphoning some reduced fraction of users.

I'm doubtful most people would notice a QR code dynamically changing, particularly in most public lighting.

t_mann

All of those could be done much more stealthily server-side, though, I don't get what the QR code modification would add here? Also, neither use case makes use of the hack described in the OP. Where I could see an attack based on that hack would be where an attacker plasters their code over a legitimate one. It would be kind of random which code gets read, so they could send some %-age of users to the original destination, hence possibly delaying detection. But it doesn't seem a given that this would compensate for the reduced traffic to their link.

post-it

Some sort of MITM attack by someone who owns the display but not the server, maybe. Like a malicious ad company.

t_mann

Ok, but then I'd still prefer a method that sends users to a unique URL. OP's method may help with obfuscating the changing of the code, but I'm sure there are ways to better achieve that without having to introduce this quasi-randomness. The simplest would probably be to just to regularly hide/show the code (which would happen anyway on a typical digital ad display that cycles through a number of ads).

michaelmior

But if you own the display, you can send the user to whatever server you want.

dspillett

> All of those could be done much more stealthily server-side, though, I don't get what the QR code modification would add here?

Even if the adversary controls the server side as well, you need to tell the server the information needed to make a decision If you control everything that is easy enough too, but perhaps you want to keep the decision-making process local – for plausible deniability server-side, just to reduce server & bandwidth load, or because you are sending people to completely different destinations not just altering link parameters.

Replacing the QR code more statically sends everyone to the new address, not just the target(s), altering the QR code by a bit or two (and the relevant error correction bits too) in response to a pile of information available at the QR reading site (feeds from cameras, and such) would be how the server knows to react differently without having access to that collection of information itself. You might want to use some clever analysis to minimise the visual effect if you are altering the QR code while it is already displayed – the two examples here look very different, but the change could be much more subtle. If sending to very different destinations, so the codes for the URLs will look very different, then adding a link anonymiser between would keep the change minimal.

> Also, neither use case makes use of the hack described in the OP.

True.

michaelt

There are actually attacks based on changing public QR codes already!

They don't need anything as sophisticated as this dual QR code, though - the attackers just go to a car park with a "pay by phone" sign, slap their own QR code over the "scan to pay" code, and wait for the credit card details to start coming in.

Terr_

Hmmm, there might be some criminal utility in capturing <100% of visitors, so that the true owner doesn't easily realize that activity for that location has ceased. In other words, giving up a certain number of victims in order to keep the attack going for longer.

That said, it'd probably be easier to implement that in software, where the phishing site redirects a certain portion of visits back to the legitimate one.

P.S.: There's also the physical stealth aspect, but I think a lenticular design would probably be easier for a human worker to notice, compared to a regular flat sticker which just happens to encode a typo-squatting URL.

alphan0n

I almost got taken in by a fake parking ticket scam, perfect ticket/envelope, the url printed on the ticket led to a 404 on the legitimate city website, the QR code led to a very convincing website/url, especially on mobile.

The only reason I caught it was that I had gotten a legitimate ticket a month prior for parking too close to the fire hydrant and had marked the curb with chalk at the correct distance. So I tried to dispute the fine and discover that the ticket didn’t actually exist. And the city had no interest in the fake ticket whatsoever. They were just like “yeah, it happens all the time”.

nroets

I guess similarly you can carefully craft a poster with a QR code and put it on a wall in a room with two LED bulbs. The bulbs will have different color temperature and the decoding will be dependent on which bulb is lit.

Another idea would be a poster that's not quite flat: Each pixel that is different is slightly raised (pyramid shaped) and the sides of the pyramid is colored differently. So the QR code scans differently from different sides.

One of the dominant banks here in Tbilisi allows sharing of IBAN number as QR codes. In theory, the trick could be used to steal money, but in practice, there are many safeguards such as the banking app displaying the name of the beneficiary before completing the process.

chii

> banking app displaying the name of the beneficiary

and the scammer make an account with a name that look similar at a glance (e.g., swap the l with a 1, or something of the sort).

fxtentacle

Most likely, they have <1s bank transfers, too, like pretty much all of Asia. That way, if you pay someone with a QR code, they'll immediately get the notification that they received your payment. And if they don't, you immediately know that something went wrong.

heeen2

you could use glossy/matte or metallic finish, then the reflected light could appear brighter than the white parts

hnlmorg

> alters the QR code based on information it has about the current user, without appearing to change significantly.

I doubt many people would notice if your average QR code was to change significantly. Most machine readable formats are just indistinguishable white noise to most people.

eieio

I appreciate you laying out malicious use-cases instead of just having the setup section; I would have struggled to think of those!

FWIW the place my brain went was some kind of magic trick, since having control of this could function kind of like a forcing a specific card or something

alan

Static a/b testing?

tbrownaw

> pretend to offer some form of probabilistic chance to win a prize, but bias winning to some identifiable characteristic. e.g. race, age, "beauty"

Do a facial recognition lookup against the RealID database (I'm sure someone must be selling a leaked or hacked copy by now) and make the prize depend on the first letter of the person's last name.

Normal_gaussian

Identifying this should be relatively easy in the core libraries; finding alternate valid QR codes using "less optimal" grids.

Of course the API confusion here becomes non-trivial, which hampers securing against it. And with existing libraries being widespread, its going to linger as an attack for a long time.

jdoe1337halo

Hey guys I made a website so yall can try this out yourself! I don't have the exact methodology that Christian uses, so here is how I did it:

The ambiguous QR code in this application works by combining two different QR codes into a single image using a diagonal split pattern. When two QR codes have different patterns at the same position, the cell is split diagonally - one half represents the first QR code and the other half represents the second QR code. When both QR codes have the same pattern at a position (both black or both white), the cell is filled with a solid color. Due to the high error correction capability of QR codes (using error correction level 'H'), QR code scanners can still read either URL depending on the scanning angle, though as noted in the UI, it tends to favor the second URL more frequently.

https://dualqrcode.com/

HenryBemis

It didn't work for me. I generated two links (BBC, CNN) and tried on my Android, with the app "QR & Barcode Scanner" v2.2.47. I also tried with the stock camera of an iPhone 13. In both they couldn't 'read' them.

jdoe1337halo

Strange, I am using an iPhone 12 pro max and it works for me. I am going to keep playing around with different pixel painting techniques and see if I can get a more reliable, 50/50 split on both links. Thanks for trying!

nixpulvis

The most interesting thing about this to me is that on iOS a long press on the image claimed it's going to github.com, while the preview itself was for mastadon. This indicates that it's parsing the QR code twice and getting different results? I could see this being used to mislead some people, though I'm not sire how many people look at the long press dropdown URL.

codetrotter

Tangential but once in a blue moon I come by some situation where I’m on my phone and I’m looking at something that has a QR code showing on the screen of the phone itself.

And so I do something silly like airdropping a screenshot of it to my laptop so I can scan it with my phone camera, or I get someone else (friends, family) to use their phone to scan the code from my phone screen with the camera app on their phone.

And all this time I was annoyed why I couldn’t just get the link directly from the image on my phone without involving another device, and without having to install yet another third-party app.

And today I learned that all I had to do was long press the QR code in the screenshot in my camera roll and it would actually parse it and make it so I could visit the link!

I think I must have tried long pressing QR code in an image in the camera roll years ago because it always seemed like something that would make sense to support via long press. Maybe they introduced this feature after I had tried to long press a QR code in an image in the past. Or maybe it was always possible and I didn’t actually ever try to long press it. Or maybe I long pressed the wrong part of the image that first one or two times I ever tried to do it in the past. Either way, very happy to have learned that this is actually possible.

kccqzy

Long pressing still doesn't work for me. Perhaps because I turned off some features related to image intelligence.

poglet

On iOS I believe the option is in Settings > General > Language & Region > Live Text. This was introduced in iOS 15.

davchana

Yes, I usually share it with Google App, and Lens tab.

russellbeattie

I can totally see two parts of the OS both using their own QR parsing code - SmartText using one, and the imaging system another. Apparently each one has their own slightly different error correction implementation.

I bet it'd be possible to create a standard QR Code with a deliberate error that does the same thing. You'd just have to figure out how they're correcting the error differently.

Seems like you discovered a bug-bounty bug just waiting for someone to claim.

the_arun

QRCode should also show the target url in text, so the user knows where it is taking - something like explicit consent.

efreak

Google lens and other apps do this.

I've seen apps that read QR codes that don't, however. Usually they're single-purpose and just don't recognize unexpected data (scan the magic code to get a character in a game, etc) but if the expected data is formatted as a URL, maybe it tries to fetch resources there (character information and image).

I can also see someone making a browser extension that allows scanning a QR code to immediately open it so you don't have to leave your current app.

jimjimwii

Yep, like how browsers show users urls in their location bars.

_august

When I long-press on iOS, it shows me the mastadon link as the main "Open" link, as well as "Open in Github" (app link) in the context menu.

layer8

This is likely the typical case of related code calling the same function or getter method twice in a context where it is imperative for both calls to return the same result.

It is reminds me of code like

   if someCondition(getFoo()) 
   then doSomethingWith(getFoo())
or even just

    doSomethingWith(getFoo())
    doAnotherThingWith(getFoo())
which is always a code smell, as opposed to

    foo := getFoo()
    if someCondition(foo) 
    then doSomethingWith(foo)
and

    foo := getFoo()
    doSomethingWith(foo)
    doAnotherThingWith(foo)

pas

layer8

I often see it in multiple-time-of-use scenarios as well that need to be consistent, i.e. no check vs. use involved.

efreak

Shouldn't the compiler optimize this into a single call if they're called so close together?

noitpmeder

now THIS sounds like an exploit

null

[deleted]

re

(Scroll up from the starting position to see the lenticular one)

dang

Should we change the top link to https://mstdn.social/@isziaui/113874436953157913?

winternewt

Yes please

dang

Weirdly, it already is! I don't understand what's going on there. Are we getting sent to a different spot on the page depending on what angle we click from?

ShakataGaNai

That is gnarly. My iPhone tended to lock into one or the other, rotating the phone seemed to help it go one way or the other. But a couple times it did flash back and forth between the Mastadon and GitHub links.

andrewla

If you want to try it out, here's some quick and dirty code.

Install the qrcode python package and run this code:

    import qrcode

    bar = qrcode.QRCode(border=0)
    bar.add_data('bar')
    bar.make()
    bar_mat = bar.get_matrix()

    foo = qrcode.QRCode(border=0)
    foo.add_data('foo')
    foo.make()
    foo_mat = foo.get_matrix()

    for l, r in zip(foo_mat, bar_mat):
        line = ''
        for lc, rc in zip(l, r):
            line = line + (lc and '\u2588' or ' ')
            line = line + (rc and '\u2588' or ' ')
        print(line)
        print(line)
What you get is indeed a dualing qrcode (which I can't quite paste here because no unicode on HN, and using "8" or "0" isn't enough to get my phone to recognize it).

dwheeler

Shouldn't one of the URLs implement a Rick Roll :-) ?

65

This would be cool to use in a scavenger hunt.

TOMDM

Maybe make it so that you need the results of both (all?) QR codes to get the final code/link/key.

rhet0rica

I summon QR Exodia!

johnea

QR codes, like shortened URLs, are just begging to exploit.

It's an inherently unreadable URL, you really have no idea where you will be sent, or how many times you will be redirected.

I don't use them...

danvoell

This is such a cool concept! If you're focusing on the end goal, another approach could be using a "switch" at the URL destination—something that redirects users to a different page based on a randomizer, user data, or other criteria. For anyone exploring this kind of functionality and interested in testing physical stickers for their projects, I work with a lot of SaaS companies on variable labels and would be happy to share insights, print some samples or collaborate.

mkl

My phone (Samsung Galaxy Note 20) seems to reject almost all of these, and not recognise them as QR codes. I got one to work for one URL by moving way away from the screen.

trebligdivad

Someone needs to define a human-readable attachment to QR that can be checked by the QR reader; e.g. the root of the URL printed above the QR code at a specific position offset or with a specific mark; so then the QR decoder could OCR it and verify it matched the URL encoded. Only the root of the URL would be included so the QR could include a specific to that location complex path. Now, we just need to backronym SPQR to fit...