'Padding Oracle'에 해당되는 글 2건

반응형

SSLv3이 취약한 HTTPS 프로토콜이라고 하여 어떤 취약점이 존재하는지 알아본 결과 POODLE 취약점(CVE-2014-3566)이 존재하여 취약하다고 하고 있다.


그래서 POODLE 취약점이 무엇인지, 어떤 식으로 동작하는지를 알아보았다.


1. POODLE이란 무엇인가?

 : POODLE은 Padding Oracle On Downgraded Legacy Encryption의 약자이다.

이를 해석하면 다운그레이드된 구식 암호화에 대한 패딩 오라클이라고 할 수 있다. 그렇다면 다운그레이드가 된다는 것은 무엇이며, 패딩 오라클이란 무엇인가에 대한 궁금점이 생긴다.


2. 다운그레이드의 의미와 POODLE 취약점 효과

 이에 대해서는 먼저 아래의 이미지를 보고 가자.


 SSL과 TLS는 서버와 클라이언트 중 한쪽이라도 최신 버전을 호환하지 않는 경우 이전 버전의 프로토콜로 연결을 재시도하는 동작이 있다.


 위의 이미지를 보면 Client에서 Browser를 이용하여 Server쪽으로 최신 버전의 암호화인 TLS를 이용하여 요청을 보내는데 이 때 공격자가 일부러 TLS에 대한 연결을 끊어 SSL 3.0까지 다운그레이드를 시킨다. 이 후 공격자는 패딩을 이용한 공격을 실행하여 Web 서버와 클라이언트 간의 통신을 Sniffing 할 수 있다.


3. Padding Oracle

 패딩 오라클에 대해서는 간단히 하나의 포스팅으로 넘어가기엔 방대한 설명이 필요하여 간단히만 설명하도록 하겠다.


 패딩 오라클이란 [복호화 시스템에 암호문을 넣었을 때 그에 대한 패딩의 올바름 유무를 보여주는 오라클]이라고 할 수 있다. 이 때, 바로 이 패딩이 올바른지에 따른 서버측의 응답을 이용해 암호화된 값을 평문으로 복호화할 수 있는 취약점이라고 할 수 있다.


부르트포싱을 통한 공격이라고는 하나 현재 Padding Oracle 공격을 위한 툴(https://github.com/iagox86/Poracle)도 존재할 뿐더러, 실제로 암호화된 값이 복호화가 되어 값 변경까지 가능하게 된다면 보안상 큰 구멍이 될 가능성이 존재하므로 많은 고객들을 관리하는 기업에서는 SSLv3가 아닌 TLS만을 사용할 것을 권고한다.


4. 대응방안

 대응방안이라고 하면 말그대로 보안상 취약한 SSLv3를 사용하지 않고 최신의 암호화 기법인 TLS(Transport Layer Security)를 이용할 것을 권고한다.


 아래는 서버 별 설정 정보이다.


☞ Apache

Apache SSL 설정 파일에 적용 후 서비스 재시작

- 파일 : /etc/apache2/mods-available/ssl.conf


SSLProtocol ALL -SSLv2 -SSLv3


☞ Nginx

nginx 설정 파일에 아래 내용을 추가한 후 서비스 재시작


ssl_protocols TLSv1 TLSv1.1 TLSv1.2


☞ IIS

regedit(레지스트리편집)을 통해 아래 레지스트리 키 편집

HKey_Local_Machine\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols registry key

-> 하위 키에서 SSL 3.0에 대해 "00 00 00 00"으로 설정


참고)

https://blog.trendmicro.com/trendlabs-security-intelligence/poodle-vulnerability-puts-online-transactions-at-risk/

https://www.opentext.com/file_source/OpenText/en_US/PDF/OpenText-POODLE-Vulnerability-FAQ-KO.pdf

https://www.hahwul.com/2015/10/exploit-sslv3-poodle-attack-check-and.html

- http://bperhaps.tistory.com/attachment/cfile30.uf@21B98D33597949BB36C50B.pdf


반응형

'Hacking > Network' 카테고리의 다른 글

SMTP Open Mail Relay vulnerability  (5) 2020.12.07
usage of Docker  (0) 2020.03.10
NIST, TDES 암호알고리즘의 사용제한 권고  (0) 2019.05.06
SSH Dynamic Port Forwarding with SOCKS  (0) 2017.03.10
WPE 활용 SQL Injection  (0) 2017.03.08
블로그 이미지

rootable

,
반응형


문제에 접근하면 padding oracle vulnerability에 대해 알고 있는지 물어본다.

해당 기법을 이용하여 문제를 해결해야 한다는 것을 알 수 있다.


해당 기법에 대해서는 아래 블로그에 설명이 잘 나와있다.

해당 블로그를 참고하여 패딩 오라클 에 대해 잘 숙지하고 문제에 접근해보자.


한마디로 정리하자면 오라클이란 올바른지 확인하는 것이라 생각하면 되고 이에 따라 패딩 오라클이란 암호화된 값을 복호화했을 때 패딩이 올바르게 되어 있는지 확인해주는 것이다. 


암호화된 값을 복호화과정 없이 변조가 가능하다는 것이 크리티컬한데 그 과정을 간단히 설명하면 암호화된 값을 복호화하면 IV(Initialization Vector)와 평문을 Xor한 값이 나오고 여기에 IV를 Xor하면 평문이 나온다. 단, 우리는 키 값을 모르기 때문에 복호화를 진행할 수가 없으므로 IV의 값을 바꿔가며 IV와 평문을 Xor한 값을 찾고 이를 통해 평문값을 찾을 수 있으며 변조까지 가능하다.


참고) 서버측에서는 PlainText의 padding이 잘 되어있다면 padding이 잘못되어 있을 때와 다른 응답을 보낸다.

 암호화 경우

 서버측 응답 

 정상적인 암호문

 200 OK 

 비정상적인 암호문

 500 Internal Server Error 

 정상적인 암호문 + 복호화 시 비정상적인 데이터

 Custom Error message 200 OK 혹은 404 Not Found


이 취약점은 ASP.NET에서 세션을 변조할 수 있는 취약점으로 나온지가 꽤 된 취약점으로 RealWorld에서는 자주 발견되기 힘들 것으로 보이긴합니다. (워낙 크리티컬해야지;;)


해당 문제에 접근하면 guest와 그에 해당하는 패스워드가 적혀있는데 로그인을 하면 아래와 같이 admin의 세션을 얻는 것이 목표라고 말하고 있다.


버프를 통해 세션값을 얻어보면 아래와 같이 L0g1n이라는 쿠키값이 참 의심스럽게 생겼다.



해당 값의 길이를 세어보니 총 24바이트로 12바이트씩 블럭이 되어있음을 예상할 수 있다.

해당 값의 앞 블럭의 값을 바꿔보면 invalid user 라는 에러가 뜨고 뒷 블럭의 마지막 값을 바꾸면 padding error라는 에러가 뜸을 볼 수 있다.


일단 뒷 블럭의 마지막 값을 바꿔가며 브루트포싱을 하여 invalid user가 나오는 값이 무엇인지 00~FF를 넣어보자.


후.... 더러운 코드지만 잘 될줄 알았지만 값을 넣어도 안되네 ㅠㅠ

import urllib

import urllib2

from urllib import quote,unquote

import base64


url='http://wargame.kr:8080/dun_worry_about_the_vase/login_ok.php'

data = {"id":"guest","ps":"guest"}

data = urllib.urlencode(data)

request = urllib2.Request(url,data)

request.add_header("Cookie", "ci_session=a%3A10%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%228a1e8bd46581d8503958676735c11a70%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A8%3A%2210.0.2.2%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A114%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F66.0.3359.139+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1525236407%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A4%3A%22name%22%3Bs%3A8%3A%22R00t%40ble%22%3Bs%3A5%3A%22email%22%3Bs%3A17%3A%22air0700%40naver.com%22%3Bs%3A4%3A%22lang%22%3Bs%3A3%3A%22kor%22%3Bs%3A11%3A%22achievement%22%3Bs%3A7%3A%22default%22%3Bs%3A5%3A%22point%22%3Bs%3A4%3A%228850%22%3B%7Debaa3718c2c73df7bab9171deca20b7994ca8280")


response = urllib2.urlopen(request)

headers = response.info().headers

data = response.read()


for s in headers:

    if "Set-Cookie" in s:

        Llocation = s.find("L0g1n")

        Rlocation = s.find("\r")

        #print s[Llocation+6:Rlocation]

        Key = s[Llocation+6:Rlocation]


url2='http://wargame.kr:8080/dun_worry_about_the_vase/main.php'

request2=urllib2.Request(url2)


Key1 = unquote(Key[0:Key.find("%3D")+3])    #urldecodeing

#print Key1

Key2 = unquote(Key[Key.find("%3D")+3:])     #urldecodeing

#print Key2

        

hexKey1 = (base64.decodestring(Key1)).encode("hex")

# print hexKey1

hexKey2 = (base64.decodestring(Key2)).encode("hex")


iv="0000000000000000"


iv_Temp = iv


for j in range(1,9):

    for i in range(0,256):

        iv_Temp = iv_Temp[:-2*j]+format(i,'02x')+iv_Temp[16-2*(j-1):]

        print iv_Temp

        result = base64.encodestring(iv_Temp.decode("hex"))+Key2

        result = result.replace("\n","")

        #print result

        request2.add_header("Cookie","L0g1n="+result+"; ci_session=a%3A10%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%228a1e8bd46581d8503958676735c11a70%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A8%3A%2210.0.2.2%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A114%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F66.0.3359.139+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1525236407%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A4%3A%22name%22%3Bs%3A8%3A%22R00t%40ble%22%3Bs%3A5%3A%22email%22%3Bs%3A17%3A%22air0700%40naver.com%22%3Bs%3A4%3A%22lang%22%3Bs%3A3%3A%22kor%22%3Bs%3A11%3A%22achievement%22%3Bs%3A7%3A%22default%22%3Bs%3A5%3A%22point%22%3Bs%3A4%3A%228850%22%3B%7Debaa3718c2c73df7bab9171deca20b7994ca8280")

        response = urllib2.urlopen(request2)

        data = response.read()

        print format(i,'02x')+" : " +data


        if(data.find("invalid user")!=-1):

            print str(j) + "'s result=" +result

            #hexKey1 = hexKey1[:-2*j]+hex(i^(j+1))[-2:]+hexKey1[16-2*(j-1):]

            iv= iv[:-2*j]+format(i^j,'02x')+iv[16-2*(j-1):]

            print "[+]iv= " + iv

            if(j==1):

                iv_Temp = iv[:-2*j]+format((i^j)^(j+1),'02x')

                

            elif(j==8):

                print "[+]iv_Temp = " + iv_Temp

                print "[+]IV = " + hexKey1

                print "[+]encrypted Text = " + hexKey2

                break

            

            else:

                Temp = ''

                for k in range(j+1,1,-1):

                    print "jjjjj: " + str(j)

                    Temp += format(int(iv[16-2*(k-1):16-2*(k-2)],16)^(j+1),'02x')

                iv_Temp = iv_Temp[:-2*j]+Temp    

            print "[+]iv_Temp = " + iv_Temp

            break



#print "[+]decrypted Text = " + iv_Temp ^ hexKey1


술먹고 집가다가 갑자기 깨달음이 ㅋㅋㅋㅋ

코드 결과 나온 값은 hex값이므로 디코딩 후 base64로 인코딩해줘야 답이 된다.


클리어~


참고 ) 
- https://m.blog.naver.com/PostView.nhn?blogId=wlstngus0504&logNo=220392135701&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
- http://bperhaps.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%8C%A8%EB%94%A9-%EA%B3%B5%EA%B2%A9-%EA%B8%B0%EC%B4%88-%EC%84%A4%EB%AA%85-Oracle-Padding-Attack

반응형

'Solve Problem' 카테고리의 다른 글

[SuNiNaTaS] 7번 문제  (0) 2018.05.10
[wargame.kr] QnA  (0) 2018.05.06
[RedTiger's Hackit] 올클리어  (0) 2018.02.03
[RedTiger's Hackit] 10번 문제  (0) 2018.02.03
[RedTiger's Hackit] 9번 문제  (0) 2018.02.01
블로그 이미지

rootable

,