The Link: My Solution

Tags: The Link, NUSSOC, National University of Singapore School of Computing, nussoc.com, Hacking challenge

0x00: What is The Link?

Thumbnail

Link: http://nussoc.com/

0x01: Level 1.

code is in the code.

— From the official hint

From the source of level 1, we can see an AJAX request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$(document).ready(function(){
$('#submit').click(function(){
if($('.password').val().trim() != ''){
$.ajax({
type: 'GET',
url: 'submit.php',
data:{pass:$('.password').val()},
success:function(html)
{
window.location.href="process.php?unique_code="+$('.password').val();
}
});
} else {
alert('Please enter code!');
}
});

When the “code” is submitted, it firstly checks against a webpage called submit.php and pass pass as a parameter.

In page submit.php?pass=mypass, there’s a piece of JS code as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function a(){
var pass = 'mypass';
var passwd;
passwd = 'wewanttohireyou';
passwd= passwd + 'showuswhatyougot';
passwd= '';
passwd='youdidit';
passwd=passwd+'_welldone';
if (passwd==pass)
{
return 'Challenge Passed';
}
else
{
return 'Challenge Failed';
}
}

Basically, the passcode supposed to be the value of passwd. Throwing it into a console. (actually can just read, I just kinda lazy). The pass code is youdidit_welldone.

You did it. Well done.

0x02: Level 2

Okay, in level 2, there’s quite some obstacles. let’s solve them one by one.

0x0200: User-agent

Browse “The Link” using “Link”

— [Official hint](https://www.facebook.com/NusSchoolOfComputing?sk=app_202980683107053&app_data=1f07b25f-f4b3-4e09-bca6-8f5621f3c6df%3A0)

When the level is first opened, the box shows “BROWSER NOT SUPPORTED”. When checking its source code, there’s a commented “tinyurl” link that points to an article on Wikipedia.

1
<!-- http://tinyurl.com/5ru8yvp -->

It’s about a browser called Links). (Maybe it just happen that there’s such a browser that have the same name as the hacking event, and with an extra s.) I tried to google for links user agent, then I come across with this site that happened to have the UA string for that classical browser. I then grabbed the first line of it, says:

Links (6.9; Unix 6.9-astral sparc; 80x25)

Using Chrome’s DevTools Device Emulator to change my UA string to it. I successfully accessed the correct page.

0x0201: QR codes.

On the puzzle window, there’s 2 QR codes, and between them, there’s some spacing. Firing up the view-source window, I see this few lines.

1
2
3
<div style="padding:10px;float:left;"><img src="images/qrcode1.svg" width="100px" height="100px"/></div>
<!-- http://nussoc.com/challenges/2/images/qrcode2.svg -->
<div style="padding:10px;float:left;"><img src="images/qrcode3.svg" width="100px" height="100px"/></div>

Obviously, there’s a 1, a 3, and hidden in between, there’s a 2.

Scanning them one by one, this is the result i get.

QR code 1: b25lc3RlcGZ1cnRoZXI=

QR code 2: _tojoin_

QR code 3: a236210022be614ff79d33a8268093ac

So, first one we can see there’s an equal sign at the end, likely it’s a base64 encoded string. In the JS console, I typed:

1
2
> atob("b25lc3RlcGZ1cnRoZXI=");
< "onestepfurther"

So here, we got the first portion.

Nothing much to say about the second one. _tojoin_ is _tojoin_.

The last part is a 32-char hexadecimal string. What does it reminds you? MD5, right? Throw it into google, I got this. There’s only 4 results at the time of writing, where the first two of them gives the result of thelink. So, we’ve also got the last portion.

Joining them together, we can easily get the passcode, onestepfurther_tojoin_thelink.

0x03: Level 3

This is a super tough level. I didn’t manage to solve it at the time of writing. But I do get something.

EDiT: Seems I have made a careless mistake. runningkeycipherentrytothelink is the code.

When entering the level, there’s nothing special hidden in the source code. The only clues are:

  • In the URL, there’s a parameter says ctext=syfgmcvsreubduijxbuzezskhxeipuadeab
  • On the picture, there’s a book titled “Web application security for Dummies”

In the first 5 hours, no one have solved it. The admin has posted quite a lot of hints in the forum.

Did you notice the book in the background? That might give you a hint .

Saying the book is useful.

Heard of “Tabula Recta”?

That is one of the encryption methods used.

Use the book to find the key! http://www.bradreese.com/qualys-web-application-security-for-dummies.pdf

A download link to the book.

How many possible ciphers using book ? We have used one of them ..

A book-related encryption method is used.

Some researches has been done on google, and through trial and error, I found out that the encryption method they used is called Running Key Cipher.

To crack the key using computer, I have found this site (1, 2) which provides a Python script for auto cracking Vigenere Cipher (the base cipher used by Running key).

In fact, what we need to use is only a few things:

  • english_quintgrams.txt.zip as a dictionary for language analysis
  • ngram_score.py for calculating match score with N-gram algorithm
  • pycipher for Vigenere decryption algorithm

To prepare the book, we need some pre-processing to the PDF file. After downloading it, we need to convert it to a txt file. There’s plenty of such tools, just google for it. Then we need to filter out all other characters, left only with letters, and convert them to uppercase. We can do this with Python.

1
2
3
4
5
6
import re
f = open("WAS.txt").read() # read the file
f = re.sub(r'[^A-Z]', '', f.upper()) # convert the string to uppercase and remove other chars
of = open("WAS.out.txt", 'w')
of.write(f) # create a new file and write to it

Then we can write our own script for decryption.

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
from ngram_score import ngram_score
from pycipher import Vigenere
from itertools import permutations
wl = file("WAS.out.txt").read() # the book
g = ngram_score("english_quintgrams.txt") # the scorer
ct = 'SYFGMCVSREUBDUIJXBUZEZSKHXEIPUADEAB' # the ctext
def w(key):
"""Calculate the key"""
a = Vigenere(key).decipher(ct)
return (a, key)
d = [] # used to store all the results
def s(t):
"""Store the deciphered text, score, and key used"""
s = g.score(t[0])
d.append((t[0], s, t[1]))
for i in range(len(wl)-len(ct)+1): # for all possible keys
s(w(wl[i:i+len(ct)])) # calculate the key
d = sorted(d, key=lambda a: a[1]) # sort by their score
print d[-10:] # Print the best 10 results
```
After calculation, the best result obtained is:
```python
('RUNNINGKEYCIPHERENTRYTOTHELINKIPNHN', -151.94413608449415, 'BESTEPPINGSTONESTOBIGGERATTACKSORTO')
  • 'RUNNINGKEYCIPHERENTRYTOTHELINKIPNHN' is the plain text
  • 'BESTEPPINGSTONESTOBIGGERATTACKSORTO' is the key, found on page 34(40) of the book. (“be stepping stones to bigger attack or to leak sensitive …”)
  • Highest score of -151.94


After several attempts, none of the codes below are the answer:

  • RUNNINGKEYCIPHERENTRYTOTHELINKIPNHN
  • runningkeycipherentrytothelinkipnhn
  • runningkeycipherentrytothelink
  • ipnhn
  • IPNHN
  • rho
  • isrho
  • runningkeycipherentrytothelinkisrho # it’s not rho.

Removing the unreadable 5 letters, the key is runningkeycipherentrytothelink.

0x04: Level 4

Somehow easier.

This time there’s an MP3 file on the webpage. The filename of it reads OWASP Appsec Tutorial - Appsec Basics - Challenge. After googling, that’s extracted from a YouTube video.

Through Observation, the audio file is 9 minutes long, but the video is only 8:31. By comparing the difference, there’s some weird sound heard in between.

By googling ‘hide message in MP3’, I found out an method that can hide image in the spectrogram of the audio file. Using a tool to show out the spectrogram, words can be seen.

Screenshot
I forgot to include the “One” in the beginning.

The tool I used is called Sonic Visualiser

So the passcode is GoodJob_AllSetForLastOne.

0x05: Level 5

Not as difficult as Level 3.

Nothing special on the webpage. Checking the source code, I see a link of .pcap packet file.

1
<!-- http://nussoc.com/challenges/5/files/challenge5.pcap -->

Open it with Wireshark, I see some HTTP packets. Filtering all the HTTP packets, this is what I get:

Packets

Reading them one by one, I observed there’s a web app that allows file uploads, and the client is keep uploading something.

In fact, only two of the packets are useful.

No. 32: POST /app/uploader.php HTTP/1.1 (application/octet-stream)

A file is uploaded. (That’s the Hex of the file)

1
2
3
4
5
6
7
8
9
10
52 61 72 21 1a 07 00 cf 90 73 00 00 0d 00 00 00
00 00 00 00 b9 60 74 24 94 35 00 50 00 00 00 3c
00 00 00 02 9d 58 3d cd f2 93 28 47 1d 33 08 00
20 00 00 00 63 32 56 6a 63 6d 56 30 fe 64 5e 03
8d 9b fd b3 00 b0 02 b0 4c 46 eb 7c 93 d3 a0 06
9f 3e 88 d2 67 5e 6a 78 1c 3f 28 19 50 5e b1 aa
cd d2 18 ee 89 88 b4 9e fb 3d 33 1e 24 b6 ac 4c
24 86 73 67 f0 64 c5 34 8b 41 5e 67 9f 6f 40 66
a8 a5 50 7d b7 4c d5 af 91 ef b0 69 19 86 f1 4e
1c 3c d4 49 2b dc 2a fc 1b c4 3d 7b 00 40 07 00

52 61 72 71 is Rar!, so we can confirm it’s an RAR file.

Opening the archive, there’s a file called c2VjcmV0, password protected.

No. 52: POST /app/uploader.php HTTP/1.1 (text/plain)

A plain text file is uploaded. iamhere.txt which says:

1
password is welcome

Okay, password is welcome.

Using this password, we can open the file in that RAR archive. It says:

VFdsemMybHZia052YlhCc1pYUmxaRjlYWld4amIyMWxWRzlVYUdWTWFXNXI=

Umm… [A-Za-z0-9]+={0,2}, yet another Base64.

1
2
> atob("VFdsemMybHZia052YlhCc1pYUmxaRjlYWld4amIyMWxWRzlVYUdWTWFXNXI=")
< "TWlzc2lvbkNvbXBsZXRlZF9XZWxjb21lVG9UaGVMaW5r"

Another Base64?! I just don’t know why the setter like Base64 so much. Well…

1
2
> atob("TWlzc2lvbkNvbXBsZXRlZF9XZWxjb21lVG9UaGVMaW5r")
< "MissionCompleted_WelcomeToTheLink"

Nothing special, that’s the key. MissionCompleted_WelcomeToTheLink.

0x06: Afterwords

Despite I have spent quite short time to finish the last level, I didn’t manage to get into the ranking. Well, whatever. I got it solved.

And I hope this could help you.

Just outside of the ranking, my score is 1573.