I have reverse engineered parts of the protocol used by kahoot.it. This repository contains the results of my labor.
Currently, I have implemented the following tools:
First, you must have the Go programming language installed on your machine.
Once you have Go installed and a GOPATH
configured, you can use the following command to install the dependencies:
go get github.com/gorilla/websocket
Download Termux on Android device and type this command line:
apt update
apt install curl
curl https://raw.githubusercontent.com/unixpickle/kahoot-hack/master/kh-tmux-setup.sh > kh-tmux-setup.sh
chmod +x kh-tmux-setup.sh
./kh-tmux-setup.sh
Once you have all the needed dependencies, you can run kahoot-flood/main.go program to execute the kahoot-flood tool. You can run the other tools in a similar fashion.
NOTE: I have contacted Kahoot and they have fixed this bug. It would have posed an actual security threat to teachers using Kahoot.
The XSS hack allows you to run arbitrary JavaScript code on the coordinator's computer. This could be something like alert('hey')
, or it could be something much more devious. The command is dead-simple to use as well; you can do something like go run kahoot-xss/main.go game-pin alert\(\)
. While this seems simple enough, I had to work around some very tough restrictions to get this to work.
The exploit I use only allowed me to execute five-character snippets of JavaScript at a time. Kahoot lets users inject 15 characters of HTML, so we can do something like <script>code
. The problem is that the client code dumps some HTML tags after our script, so if we did <script>XXX
, it would result in an eval like eval("XXX</span></li>")
. To deal with this, the last two characters of our script need to be //
to introduce a comment. This leaves us with five characters of JavaScript per nickname.
The obvious approach is to build a script string using string concatenations and then evaluate it. The problem is that eval(e)
is 7 characters, and even something like e=eval
is 6 characters, one over our limit. In the end, I exploited the fact that Kahoot uses jQuery. Using HTML element construction, I can create a bogus <img>
that executes code (e.g. <img src="https://github.com/unixpickle/kahoot-hack/raw/master/" onerror="MY_CODE">
). Once I get this into a variable Z
, I can do $(Z)
.
I initially tried building strings using a linear approach: a=''
, b='X'
, a+=b
, etc. In theory, this works, but in practice it took way to long to be useful. Now, I use a highly-parallel logarithmic approach. First, I set 32 variables in parallel. Then I join these variables into 16 new variables in parallel (e.g. a=b+c
). I repeat this until all 32 characters are concatenated into one variable. I then repeat the process for the next 32 characters of the string, until I have built the whole thing.
In sum, my program takes your script and puts it in a malicious <img>
tag. It then builds a variable on the coordinator's browser with the contents of that tag. Finally, it puts the plan into action by invoking jQuery's conveniently short function name.
This is released under the 2-clause BSD license. See LICENSE.