https://bernsteinbear.com/blog/how-to-mess-with-your-roommate/ home blog lisp favorites pl resources bread recipes rss How to mess with your roommate May 29, 2018 Before I explain what I did to hurt poor Logan, I must explain our apartment's media setup. You will see why shortly. Logan, if you're reading this, I hope you're more entertained than not. The media setup We have a computer running Ubuntu desktop connected to a TV. This acts as our media server. Because it is also generally useful for it to be internet-connected, it also serves a couple of webpages, an SSH server, and handful of other services. Since the TV is 4K and the desktop computer is salvaged, the graphics card it had was not acceptable. Logan decided to purchase a several-generations-old NVIDIA graphics card (which was far better than our existing one) to display smooth 4K video. The prank Shortly after the installation, we had a couple of driver glitches, at which point I thought it would be humorous if there was a way to manually launch error messages. After some internet searching, it became apparent that remotely displaying a message on the TV is as simple as: 1. SSH into the box as the user displaying the content 2. DISPLAY=:0 zenity --info --text 'Hello!' (The DISPLAY=:0 bit is necessary because there is no display on the session I am connected to, and I want to show it on the primary viewing display.) Since we were having trouble with the NVIDIA graphics card, however, I went with something more similar to: DISPLAY=:0 zenity --warning --text 'Display is running in low-graphics mode.' I gave this a go (and it worked), but manually logging into the server from an SSH client every time I wanted to bother Logan was a pain. So I decided to get crafty. I thought about making a cron job to bother him regularly, but that has two problems: 1. It's just that -- regular 2. We have other real cron jobs, which makes the sneaky new one too discoverable Other options like a SysVInit script were also out for similar reasons. So I decided on instead making a publicly-accessible webpage that has a button on it: "Fuck with Logan". The prank setup In order to execute, I figured I needed a couple things: 1. Something that can handle user input 2. Something that can execute arbitrary commands on the web user's behalf Which ends up being: 1. NGINX 2. The NGINX FPM extension 3. PHP 4. The PHP FPM package So I went and set up a website at http://our.apartment.server with a landing page (logan.html) and an "action page" (zenity.php):
There are some nonsense meta tags in there to make the page easier to use on phones (I was making this easier to use on-the-go, remember?). For those who can't render HTML in their heads (most people, I imagine), that page looks like this: The button When the button is clicked, it POSTs to another page that does the heavy lifting: /dev/null &"); include 'logan.html'; ?>
This page does a number of things:
1. Pick a semi-random error message to display
2. Pick the type of dialog box that will appear
3. Display the box for a certain period of time (10 seconds)
4. Render the button and also an explanation of what just happened -
all accompanied by a fun picture of Logan himself
For those who can't render HTML in their heads (again, hopefully most
people), that page looks like this:
The button
If you're wondering why the webpage allows code execution in such a
fashion, and how the web server owner (www-data) could possibly
execute commands as the display user (thedisplayuser), you will
probably be happy to know that I strictly limit it in the sudoers
file:
# /etc/sudoers
www-data ALL=(thedisplayuser) NOPASSWD: /usr/bin/zenity
This particular bit of configuration allows for www-data to execute
only /usr/bin/zenity as thedisplayuser, and without a password.
I deployed it after squashing some annoying PHP and NGINX
configuration nonsense. Then, I sent the URL to a couple of friends
on campus who know Logan.
The prank result
Thank goodness Logan reacted as strongly as he did. If he'd been
mildly irritated, I would have been peeved that all my efforts were
for nothing. But no! He lost his cool.
I cannot count how many reboots, driver re-installations, kernel
modifications there were. I only wish I had filmed how angry he got
when, after opening VLC, someone in the apartment popped up a bunch
of windows with graphics card errors.
But I got too amused, and Chris, another roommate, decided to
intervene...
The pranker pranked
Step 1
I noticed one day when Logan was asleep that an error message that
said "Max is behind all this" showed up. What??? I had been
reverse-pranked! So I investigated, and found that somebody (Chris),
had edited that message into zenity.php to be chosen at random. I
promptly removed it (Logan couldn't figure out the prank just yet),
and assumed the fun was over. BUT NO.
Step 2
A week or so later, the messaged popped up again. I assumed Chris had
noticed and decided to re-add it to the list. Nope. Wasn't there.
After carefully checking the file, I noticed that it was now calling
/usr/sbin/zenity instead of /usr/bin/zenity (the system default) and
there was an accompanying entry in the sudoers file to allow it. What
was /usr/sbin/zenity? A shell script:
#!/bin/bash
echo '.' >> /tmp/log.txt
if [ 0 -eq $((RANDOM % 100)) ];
then /usr/bin/zenity --error --display=:0 --text "Max is responsible for these." --timeout 10 > /dev/null &
else /usr/bin/zenity "$@"
fi
Well, that's some next-level shit if I've ever seen it. Ninety nine
percent of the time, it does the right thing -- and the other one
percent it displays "Max is responsible for these." I deleted the
file (a mistake, I now know) and sudoers entry, and changed
zenity.php to the way it was. The messages stopped appearing. BUT
THEN THEY CAME BACK.
Step 3
I checked zenity.php. Nothing new. /usr/sbin/zenity? Gone. Color me
confused.
So I decided I'd peek into /usr/bin/zenity:
#!/bin/bash
# --- SOME BINARY JUNK ---
# --- SOME BINARY JUNK ---
# --- SOME BINARY JUNK ---
# --- SOME BINARY JUNK ---
# --- SOME BINARY JUNK ---
if [ 0 -eq $((RANDOM % 70)) ];
then /usr/bin/rpmdb-client --error --display=:0 --text "M""a""x"" ""i""s r""e""s""p""o""n""s""i""b""l""e"" f""o""r ""t""h""e""s""e." --timeout 10 > /dev/null &
else /usr/bin/rpmdb-client "$@"
fi
The crafty little fucker. He'd edited the zenity binary directly to
BE A BASH SCRIPT and work 1/70th of the time. What the hell. And what
even is rpmdb-client?? So I fought back. I modified it:
#