1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
# Rickstodon - Rickroll Your Friends (or Foes) With A Fake Mastodon Registration Page
## -- Introducing a new way to present an old prank
![screenshot with most of the buttons and links on the page pointing to the signature rickroll cover image on youtube](img/rickstodon/rickstodon.webp)
See [video demo](https://fkfd.me/static/rickstodon.mp4); hosted on [social.fkfd.me](https://social.fkfd.me); see [Codeberg repo](https://codeberg.org/fakefred/rickstodon)
> Edit 2022-01-07: social.fkfd.me is now defunct.
## How to host it?
Because Mastodon is licensed under AGPL, and the frontend is not explicitly excluded, I doubt the legitimacy to redistribute it unlicensed. Therefore, this repo only contains a guide to make your own Rickstodon in N easy steps. You need either a working nginx, or python+pyramid.
## Prepare a place for your prank
Get a domain. If you already have one, you can always add a subdomain record into its DNS settings, typically available in the registrar's web panel. For example, `social.[your.domain]` is a subdomain that seems totally legit. Set up an A/AAAA record pointing to your server IP. Let's call this domain `social.legit.website` throughout the tutorial.
## Capture the Mastodon
Go to a Mastodon instance you are logged out of. You will be redirected to its about page, which looks like the screenshot above. Download the page using your browser, including the files. Chromium seemed to be unable to fetch the files? idk. Firefox works fine. Press ctrl+s to save `about.html`, as well as its embedded files into a directory called `about_files`.
You will see your files in a structure like:
```
about.html
about_files/
common-9fa4342b.css
d96d39a0abb45b92.png # admin avatar
f6a76f37d508b407.png # user avatar
fc87edd00a925e4c.png # user avatar
56270e3bbd5ef1a4.png # user avatar
vlcsnap-2018-08-27-16h43m11s127.png # the mastodon-paper planes-trumpet picture
common-a45d1c15f1388e6b8338.js
default-78232038.css
favicon.ico
locale_en-0b1defbea6f42c8f057f.js
public-5e7c276e9e232153d9c4.js
```
Open `about.html` in your browser. The files should load in their respective place because the filepaths are substituted with `/about_files/xxx`, except for external links, which are retained, e.g. `Documentation` links to `https://docs.joinmastodon.org/` unchanged.
Now that you've shut the mastodon in the cage, this is where the fun begins.
## Teaching the Mastodon to rickroll
Open and edit `about.html`. It is quite large for some text editors (~25 KiB). It's unindented by default. Format it using a code formatter to save your eyes from burning.
Remember the site you fetched the page from? Change all occurrences of that site (for example, `mastodon.social` to yours: `social.legit.website`. For example, in `<head></head>`, you may see the following:
```html
<link href="https://mastodon.social/about" rel="canonical" />
<meta
content="Server run by the main developers of the project It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!"
name="description"
/>
<meta content="Mastodon hosted on mastodon.social" property="og:site_name" />
<meta content="https://mastodon.social/about" property="og:url" />
<meta content="website" property="og:type" />
<meta content="Mastodon" property="og:title" />
<meta
content="Server run by the main developers of the project It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!"
/>
```
Edit the URL's, edit meta content, you name it. The meta content also goes into the visible `<div class="hero-widget">`; search for it and replace its text.
Done? Good! Now when you check out your site, it has your domain on it. But things are not right! People won't believe that this instance, unexpectedly under Eugen's administration, could attract 503k users in two short days. You need to modify those data as well. Search for `Administered by:` and `Server stats:`. These data are right under them. A value like 41 users/32 MAU is adequately deceiving.
But waaaaait. You still have Eugen's avi beside your name. This is easy: get your avi, place it under `about_files`, change those filenames in `about.html` accordingly. Same for other people's avis you wish to show. Under the `Administered by:` there is:
```html
<div
class="account__avatar"
style="width: 36px; height: 36px; background-size: 36px 36px; background-image: url('/about_files/d96d39a0abb45b92.png')"
></div>
```
Replace `d96d39a0abb45b92.png` with your image, under the same directory. Alternatively, just name your avi `d96d39a0abb45b92.png`, overwriting the original.
Find an element called `<div class="directory">`. Below are at most three user avatars. You can modify their avis if you wish. Perhaps include yours in them. It's like this:
```html
<div class="directory">
<div class="directory__tag">
<a href="/explore">
<h4>
<i class="fa fa-address-book fa-fw"></i>
Discover users
<small>Browse a profile directory and filter by interests</small>
</h4>
<div class="avatar-stack">
<img
alt=""
class="account__avatar"
src="about_files/d96d39a0abb45b92.png"
width="48"
height="48"
/>
<img
alt=""
class="account__avatar"
src="about_files/f6a76f37d508b407.png"
width="48"
height="48"
/>
<img
alt=""
class="account__avatar"
src="about_files/fc87edd00a925e4c.png"
width="48"
height="48"
/>
</div>
</a>
</div>
<!--other stuff-->
</div>
```
Yeah, it's literally just all the `*.png`s.
Now for the final step tampering the frontend, we need to reconfigure the buttons so they take unsuspecting visitors to the classic music video for a classic song. Search for the button called `Sign up`. It is in an HTML form, so clicking it will take us to `/auth`; no good! We want to rickroll the visitors, not sign up an account for them. Scroll up till you meet with this line:
```html
<form
class="simple_form new_user"
id="registration_new_user"
novalidate="novalidate"
action="/auth"
accept-charset="UTF-8"
method="post"
></form>
```
You see, the `action="/auth"` is the command that takes us to `/auth`. Remove it, along with `novalidate="novalidate"` and `accept-charset="UTF-8" method="post"`, because we're making it no longer a real form that sends requests. Keep the class, for it is used by stylesheets. Without it the form will look primitive, and people will find out. Then, find the `</form>` after it. It shouldn't be far away. Change `<form ...>` to `<div ...>`, `</form>` to `</div>`. This prevents form submission from being invoked when the button is clicked. Find another form below, with a button called `Log in`. Do the same to it. An example:
```html
<div class="simple_form new_user" id="login_new_user">
<input name="utf8" type="hidden" value="✓" /><input
type="hidden"
name="authenticity_token"
value="..."
/>
<div class="fields-group">
<div class="input email optional user_email">
<!--email-->
</div>
<div class="input password optional user_password">
<!--password-->
</div>
</div>
<div class="actions">
<button name="button" type="submit" class="btn button button-primary">
Log in
</button>
</div>
<p class="hint subtle-hint">
<a href="/auth/password/new">Trouble logging in?</a>
</p>
</div>
```
Remember the buttons? Yes, the `Sign up` and `Log in`. We need them to, when clicked, rickroll the visitors. Therefore, add an `onclick` action to both of them:
```html
<button name="button" <!--add this line below-->
onclick="window.location.replace('https://www.youtube.com/watch?v=dQw4w9WgXcQ')"
class="btn button button-primary"> Sign up
</button>
```
Done! Now we've officially set up the frontend to rickroll visitors if they ever try to sign up or log in. You can test it in a browser. But waaaaaiit. What if they clicked on stuff like "Discover users" or the admin's profile? We need to set up redirections; they are called 301's, taken from their HTTP response code. I will introduce two ways to do it: nginx and python+pyramid. Feel free to fork and add stuff like python+flask, node.js+express, apache, etc.
## Pretending innocent (2 methods)
### nginx
1. Check out `nginx.config`. What you see here is a server block for nginx. Place it either in your existent config file (typically in `/etc/nginx/sites-available`), or alongside with it renamed as something else.
2. Look into the file:
```
# ...
# redirect the following paths to rickroll video
# the tilde (~) means regex; vertical bar (|) means 'or'.
# add more user names if necessary.
location ~ (/terms|/about/more|/public|/explore|/@USERNAME|/auth/password/new) {
return 301 https://www.youtube.com/watch?v=dQw4w9WgXcQ;
}
```
The chain of paths catch all the links visitors will likely take a peek at. Replace `USERNAME` with your own username.
3. symlink this file to /etc/nginx/sites-enabled: `ln -s /etc/nginx/sites-available/FILENAME /etc/nginx/sites-enabled`
4. Check if there are any blatant problem.
5. Restart nginx: `nginx -s restart`
6. Go to your prank domain/subdomain to check result. Click on links to see if it works.
> "it doesn't work... why?"
> Look, I'm not an nginx expert. Maybe you can try using python+pyramid?
### python+pyramid (plus a little nginx reverse proxy)
1. Install python3 and pyramid (`pip3 install pyramid`). If pip says requirements are satisfied, but anything goes wrong later, run this with `--upgrade` to see if it's because of an ancient version.
2. Put `web.py` in the same directory as `about.html`.
3. Open and edit the file, just like the nginx one.
4. Run `web.py` as a background process. Use a screen, tmux etc session or a process manager for it. This is out of scope.
5. You still need to configure nginx for a bit. Sure, there are other reverse proxies but nginx is the only one I possess knowledge of. Add this block to your nginx config file:
```
server {
server_name [host]; # [host] is the domain of your rickstodon page, e.g. social.legit.website
root /var/www/html; # whatever
index index.html; # whatever
location / {
# if port 3904 is already taken, change this value both here and in web.py
# if so, re-run the modified python script
proxy_pass http://localhost:3904;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
6. Restart nginx: `nginx -s restart`
7. Go to your prank domain/subdomain to check result. Click on links to see if it works.
## Additional steps
1. Use HTTPS on your website for best deception. A mastodon instance without it is bound to raise suspicion. Use Let's Encrypt to generate a certificate for your (sub)domain. Sorry, LE.
## Drawbacks and vulnerabilities
1. If you have set up Rickstodon with nginx, the browser may make a GET request to youtube.com that reveals your intention. Like this:
![screenshot of a GET request to https://www.youtube.com/watch?v=dQw4w9WgXcQ in devtools](img/rickstodon/rickstodon-youtube-GET.webp)
If the user's network is slow, they may notice youtube.com loading in the bottom bar in a desktop browser.
## Summary
By now you should have already be savoring the joy from imaginary scenarios where people shout "whoa what the fuck" at a dancing dude. I have played this trick on my mastodon account this April Fool's day. It went... *nicely*. This repo is unlicensed, so you are always welcome to try and improve, and invent better ways to rickroll people. Thank you for coming to my TED talk.
|