Archive for the ‘Security’ Category

BlankMediaGames/Town Of Salem Data Breach (2020 Update)

06 Jan 2020


Town of Salem, a video game produced by BlankMediaGames was breached around 1 year ago on the 3rd of January 2019. It is reported that the total row count of that database that was breached is 8,388,894 which included some 7,633,234 unique email addresses.

Shortly after this breach in early 2019, hackers attacked and successfully cracked ~2.4 million passwords from the breach due to the weak MD5 encryption used. These cracked passwords were initially sold on the black market but were later released to the public on public forums.

Shockingly however, these passwords were never reset as part of the breach. Exactly one year later, a huge number of accounts are still working with the same credentials that were exposed during the breach. This has led to malicious bot writers creating Town of Salem bots with the only purpose of joining ranked games to:

  • intentionally game throw,
  • post hate speech/racial slurs,
  • spam chat to advertise,
  • impersonate other players in hopes of getting them falsely reported/banned,
  • afk / idle


Validating the breach (1 Year Later)

The cracked dump included 2,418,341 cracked entries in email:user:password format.
I decided to write a script to categorise these breached accounts. This script would iterate all user:password combinations and attempt to authenticate with the main Town of Salem game server at There is no login rate limiting in place so we could bruteforce the credentials at full throttle.

For each authentication attempt, one of the following responses was sent back by the server:

  • LOGIN_SUCCESS (successfully authentication)
  • LOGIN_FAILED (invalid credentials, password has been changed since breach)
  • LOGIN_BANNED (account is banned)
  • LOGIN_PASSWORD_CHANGE_REQUIRED (account has been marked as requiring a password change)


We are only interested in accounts that return LOGIN_SUCCESS as these are the only accounts that can be used by bot makers to ruin games.
Running a quick scan shows that many of the very first entries are still authenticating successfully.

Out of the 2,418,341 accounts scanned, it was discovered that as of 29/12/2019:

  • 961,874 accounts returned LOGIN_SUCCESS
  • 1,048,665 returned LOGIN_FAILED
  • 29,159 returned LOGIN_BANNED


Responsible Disclosure

These findings were reported to BlankMediaGames via email.
Shapesifter13 (community manager) also reached out via Discord to help fast-track the process (thanks!):



On 03/01/2020, the Town of Salem game servers were restarted for an update to address this issue:

It is important to note that it appears that BlankMediaGames were already addressing this issue coincidentally at the same time I was researching it and they moved a lot of accounts from the LOGIN_SUCCESS state to the LOGIN_PASSWORD_CHANGE_REQUIRED state. However, they did not initially address every exposed password I had access to in the first batch of database patches.

After the patches, previously cracked passwords now require the user to go through the password change recovery process.

Hopefully this resolves the problematic botting situation in Town of Salem for now.


29/01/2019 – Obtain breach dump to perform analysis
01/01/2020 – Finish running script and gather results. Report to BMG via email.
03/01/2020 – BlankMediaGames perform database patch addressing majority of leaked passwords.
10/01/2020 – BlankMediaGames perform database patch addressing remaining leaked passwords.

No Comments

Posted in Exploitation


BlankMediaGames/Town Of Salem XSS

03 Jan 2020

While looking on the website (creators of Town Of Salem) I came across an api.php file which one inside one of the folders listed in the sites robots.txt  file.

The file in question is:

Upon visiting the page we get the following output with a 200 response code:

At first I thought this was a hidden API but it turns out to be nothing more than a simple echo script. I suspected the script takes in some input as GET or POST parameters so we use a script called parameth to bruteforce the GET and POST parameters using a dictionary attack.

We run the script with the following parameters:

The argument --sizeignore  allows us to ignore responses that have a particular size (in our case 19 bytes). Typically we’d use the response code to filter out default responses but in this case the response code was always 200.

We find the following inputs:

Therefore, the two input GET parameters are hello and request. These parameters are echo’d to the page without any input sanitation meaning the original PHP script would look something like this:

As a result this script is vulnerability to XSS:





01/01/2019 – Reported to BMG
03/01/2019 – Patched by BMG.

No Comments

Posted in XSS


Creating an Extremely Strong and Unique Password

10 Dec 2015

In this post I’ll give you a method to create a really strong and flexible password.

Now i’ve personally only gone through 5-6 passwords in the last 8 years. The first 2 passwords were insanely weak (6 digit numbers!). I then started picking stronger passwords but unfortunately I’ve had to change my password multiple times due to database leaks on websites i’ve joined.
However, my current password fixes all of these problems!

Desirable requirements for passwords

  • No dictionary words or simple phrases (so no QWERTY or password!)
  • No obvious patterns (ie 12345679, abcdef)
  • No obvious substitutions (ie hello -> he11o)
  • Length greater than 8
  • Length lower than 16 (unfortunately password length limits exist on many services so this is needed)
  • Starts with capital letter
  • Contains 1+ capital letter
  • Contains 1+ number
  • Contains 1+ special characters
  • Easy to remember
  • Unique for every website
  • Can be used with systems that make your password expire (without need for a new password)

The password we will make will meet all of the criteria above!

Step by Step Guide

  1. First, pick an easy easy to remember dictionary word or a phrase that means something to you. Make sure it is around 5-6 characters long. As an example, I will secure.
  2. Chose a position to split the phrase on. Don’t just split the phrase at its syllables! I’ll decide to split at secu so I have secu and re.
  3. Now capitalize the first letter in the first string. So se becomes Se. (This is so we meet the start with capital requirement on many websites)
  4. Now pick two 2-3 digit numbers. I’ll pick 101 and 42. Add these in between your strings! Thus far we have Secu101re42 (length 11)
  5. Now pick a few other lowercase letters and capitalise them. I go with: SecU101Re42
  6. At this stage, all we need is 1-2 special characters. I decide to go with # and add it in somewhere: SecU101#Re42.
    The password is already a very strong password at this stage but still fails to meet the unique requirement.
  7. For the unique requirement, you have to come up with a system for creating unique passwords for each service you use. I came up with the following, look at the domain of the website you are using and take the first 2 letters from the domain. So on you would take fa. Capitalize the first or last letter of this. Then add this to the start or end of your password or put 1 character at the start and 1 at the end. I decide to capitalize the last letter and put the 2 characters at the end of my password. So our password for Facebook is: SecU101#Re42fA ( length 14). The benefit of this is that even if someone manages to get your plaintext password on a service, they are unlikely to notice your system and will be unable to access your other services.
    Note: You can also use a 2 letter prefix that works with many websites so Facebook becomes fb. Furthermore, you can vary the length of the tag for each service as this will also make your password vary in length from service to service which is another bonus!
  8. If your password expires on a service and you are not allowed to reuse the password again, simply add the year, semester, term, quarter or something similar to the start or end of the password. I usually add the year to the end: ie 15 for 2015


Remembering your password…is easy!

I came up with this system in such a way that remembering the password is no issue at all. Most people fail to remember passwords because they have so many different ones across various services. In our case, the domain gives you a tiny bit of the password. All that left to remember is your phrase (in our case secure), the selected split position, the few letters that are uppercase and two 2-3 digit numbers. It turns out that this system is very easy to remember. Simply typing your password over and over again for 2 minutes will get it stuck in your head and then you can begin using it on all of your services.

Password Strength

I put the above password through various password strength websites. The passwords do very well in these tests.
Here are some results from online tests:

The Password Meter


How Secure is my password Dot Net

My1login Password Checker


Final thoughts

Again these passwords are great because they are unique for every service you use (a few may clash but that is generally not an issue, however ensure you keep the number of clashes to a minimum and ensure important websites DO NOT clash). If your password gets compromised on a service you can rest easy knowing all your other passwords are secure.

Just for fun, there are the SHA1 sums for the password we created together below. If one hash gets compromised, the risk is almost nothing. If one plaintext password gets compromised, the risk is low if automated tools are used (often the case with large database leaks for major services). If someone is targeting you specifically, then it will take them a while to figure out your system but chances are they won’t.

Oh and my password isn’t the password above so don’t try to hack me 😀

 SHA1 sums for our password on various services


1 Comment

Posted in Security


Simple Buffer Overflow Example

23 Nov 2015

I’m posting this example because the current buffer overflow examples on the web are not that good. This is a step by step guide to how to exploit a program that is vulnerable to a buffer overflow attack.

The Code

This is the vulnerable code that we will be attacking. In this case, the call to strcpy is unsafe as the number of bytes that we copy into buffer (buf) is controlled by the caller which allows us to write more bytes than the size of the buffer (ie more than 1024 bytes).

Test Machine

Code was compiled on and exploited on a Ubuntu 14.04 64-bit machine.


Compile the C program using gcc with the following flags:

This turns off stack execution and the stack protector which are anti-exploit features built into GCC. This particular example will require executing code from the stack.

We also compiled for 32 bit architecture for the purposes of this example.

Furthermore, we must turn off Address Space Layout Randomization (ASLR), a memory protection feature implemented in most modern UNIX operating systems. You can review all the different Ubuntu security features here.

To disable ASLR on Ubuntu:

You can also try this to spawn a shell with ASLR disabled:

Step by step guide

At this stage you should have compiled your program and have disabled ASLR. I decided to call my program exploit.

Start up gdb with your program like this:

Then run:


In this case we know strcpy returns a pointer to its destination (which is our buffer) and this pointer will be stored in EAX register after strcpy returns. So we want to put a breakpoint after strcpy returns so we can look at the values of the registers. So we note the next
address which in this case is: 0x080484c8

Now make a breakpoint by typing:


Okay, now let’s feed our program enough bytes to cause it to crash! Our buffer size is 1024 so let’s pick a number larger than that like 1050 to try and get a segmentation fault.

Note: Here we are using perl to easily print 1050 bytes. The character we are printing (raw) is the ‘\x90’ character which corresponds to the NOP assembly instruction. The NOP instruction is the no operation instruction which does nothing but take up a clock cycle. You will see why this is important later.
Now, gdb should stop at the breakpoint that we set earlier.

Now type:


This shows you the registers at this point in the code (right after strcpy has returned). So we know EAX will hold the result of strcpy which will be the pointer to our buffer! We always want to determine the location of our buffer in this type of buffer overflow attack. This is easily done with ASLR off but becomes more challenging when ASLR is left on (see ret2libc exploits).

Note down EAX address. EBP (Extended Base Pointer) is important too but you don’t need to remember it at this stage, just know that we will be overwriting the data at that address later on (EBP overwrite).
Press c to continue and to go past the breakpoint, the program should then end in a segmentation fault. The reason the program is seg faulting is because we have written enough bytes to overwrite the EBP (Extended Base Pointer). So when our C program returns, the IP (instruction pointer) points to the EBP which will contain \x90\x90\x90\x90.  The computer will try to execute assembly inst ructions at this address but will run into invalid instructions resulting in a crash.

Now we need to discover what the smallest number of NOP’s that can be fed to the program that still causes a segmentation fault is.
This is done by trial and error (answer depends on buffer size), simply run the following from gdb until you close in on an answer (obviously substituting in a number for ‘some num’):

Note: Actually its usually buffer size plus 12 bytes (ie 1024+12 bytes) on a typical x86 machine but this is not the case on all architectures. Note that this relies on the buffer variables position in the code. If there was an integer declared before the buffer with a size of 4 bytes then you would have to write 4 bytes more to reach the EBP and cause a segmentation fault.

In this case, we seg fault with exactly 1036 NOPs. So if we feed in 1035 NOPs, no segmentation fault occurs and all is fine.

Now its time for some calculations.
You want to write 1036 NOPs and then (after 1036 NOPs) you want to write 4 bytes (for the return address of EBP we wish to overwrite). Essentially, we want the IP to point to somewhere on the stack that has data that is controlled by us. So lets make it point to the buffer and add valid assembly instructions there which are then executed! This assembly code is our payload or shellcode (because it will spawn a shell).

Our 1036 bytes should also include our shellcode. The shell code we will use is 35 bytes long.

Shell code (standard x86 shellcode):


So, we have:

1036 – 35 = 1001 bytes

So we will write 1001 NOP’s! The reason we do this is simple. We are going to be jumping to a location on the stack (somewhere in our buffer). There is no need to be precise and jump to the exact starting byte of our shell code. We can utilise many NOP operations that are valid assembly instructions that do nothing and put our shellcode at the end of the buffer where it will eventually be executed. This leaves us some margin for error. The sequence of many NOPs is refereed to as a NOP sled.

So our payload now looks like this:

1001 NOPs + 35 bytes (shell code) + 4 bytes (return address which will overwrite EBP)
So now we will construct our almost complete payload, we have:


Now we used AAAA as a dummy address because it’s easy to see in gdb as it shows up as 0x41414141 and is 4 bytes large.
So go back to gdb and run your program using the above arguments like we have done before:

If prompted to start the program from the beginning, press yes .
gdb should have stopped at the breakpoint again. Press c to continue.
Now the program should have seg faulted. Inspect the address in which the program segfaulted. It should be 0x41414141 (which is the “AAAA”, our dummy address). If you see this then you have completed all steps correctly thus far, otherwise you did not.

The final step is to look into memory to find a good address (somewhere in the middle of the NOP sled is best) to use as our actual overwrite address.


This will show you the memory contents at the ESP (extended stack pointer). Now because we went past our breakpoint and let the program end, our base pointer would have been changed to some garbage. The stack pointer (ESP) still points to the
top of the stack though so that is why we are looking around there.

Press ENTER a few times to inspect memory at higher addresses.
Eventually you will see our 1001 NOPs, once you see our NOPs (series of 0x90 byte values), stop and pick one address that is within the NOP sled. Again, try to pick an address corresponding to somewhere near the middle of the NOP sled.


In this case I pick: 0xffffd0a0 which is nice because it is roughly in the middle of the NOP sled.

Finally, exit gdb by typing q and confirming.
We can now create our full payload:

Remember to reverse the address (due to little endianness). So FF FF D0 A0 becomes A0 D0 FF FF.

Make sure the address you picked doesn’t contain a null (0x00) or a space (0x20) as that could break your exploit. This is because a null would stop the assembly instructions from being executed and a space (0x20) would cause your argument to the program to be treated as two arguments.
Now in terminal, simply run your program (exploit) with that argument. And you should see a shell spawn!

Now run whoami, if you see root or another user then you successfully entered their account without a password which demonstrates the severity of the exploit.


Some things to note

If you manage to spawn a shell within gdb that could mess up the static addresses of various things so you might want to restart gdb in order to continue to inspect memory etc.

The addresses from gdb and terminal will be somewhat different. So if you pick an address right in the middle of the NOP sled your address could work right off the bat. If you pick an edge address (not a middle one) then it might not work but you can manually try and change the address. So if I pick an edge address in gdb of: 0xffffcf60 and then I go into terminal and it doesn’t work then I could try 0xffffcf80 , then maybe 0xffffcfff , then maybe 0xffffd100 . So I am just increasing the address until it works (ie going up in memory until I land within the NOP sled).

If there is something that is unclear in this guide or incorrect, please let me know!

No Comments

Posted in Exploitation


Finland MSN XSS Vulnerability

08 Sep 2014

The search bar on this page fails to encode the quotes () and as a result a onMouseOver event tag can be attached to the search bar which allows an XSS attack to occur.

Finland MSN XSS Vulnerability



No Comments

Posted in XSS


CSE.UNSW.EDU.AU XSS Vulnerability

08 Sep 2014

The staff search page does not sanitise the input of the ID field allowing an XSS attack to be executed.


UNSW (CSE) XSS Vulnerability




No Comments

Posted in XSS


Mashable XSS Vulnerability

08 Sep 2014

The Mashable subscription script fails to sanitise the email field and prints the invalid email on an error page.

Mashable XSS Vulnerability




No Comments

Posted in XSS


ABC Mail XSS Vulnerability

08 Sep 2014

The ABC Mail subscription script fails to sanitise the email field or check that a valid email was provided. An attack can easily be executed as the unsanitized “invalid email” is printed on the produced error page.

ABC Mail XSS Vulnerability

No Comments

Posted in XSS XSS Vulnerability

03 Sep 2014

The help document search form on does not correctly sanitise user input allowing an XSS attack to be executed.

The follow symbols are converted to to their URL encoded counterparts: ‘<‘, ‘>‘, ‘/
Evasion string used (before encoding):  /><script>alert(/XSS/)</script> XSS Vulnerability

No Comments

Posted in XSS


NineMSN Flights XSS Vulnerability

10 Nov 2012

After browsing around on the NineMSN website for a little while (for about 10 minutes) I found a XSS vulnerability on a very common page. The NineMSN flights page is located here:

The page did not sanitise input from the depart and return input. The form was expecting a date but any string could be provided as input to execute an XSS attack.

Here is the vulnerability:

Ninemsn Flights From  Ninemsn Flights To


Vulnerable Code:


This vulnerability has been reported and I have been added to the Microsoft Hall of Fame for October 2012.

Why not have a look around Microsoft’s websites and see if you can find one too.

No Comments

Posted in XSS