Pyramid CTF Walkthrough
Box의 ip는 192.168.16.19 라는 것을 알아냈다.

ssh 와 http 서비스가 동작 중인것을 확인


SQL Injection 취약점은 없는지 작은 따옴표를 입력해보았다.

이로써 알 수 있는 정보 두가지
1. 사용자가 입력한 값이 웹 애플리케이션의 필터링 없이 데이터베이스 쿼리에 직접 사용되고 있다. (SQL 인젝션 취약점 존재)
2. URL에 index.php?name=? 형태로 파라미터가 노출되는 것은 GET 방식을 사용하여 사용자 입력을 서버로 전송하고 있다.
3. 해당 php는 총 3개의 칼럼을 표시할 수 있다.
(필드명은 차이가 있겠지만 실행되는 쿼리는 대충 SELECT Name, Dynasty, Regnal Period FROM TABLE WHERE NAME='$input_value' 쯤으로 예상된다.)
먼저 가장 기본적인 SQLi를 입력해보았다.
' OR '1'='1
"사용자 이름이 'a'와 같거나 (아니어도 상관없음), 조건 **'1'='1' (참)**이므로, 모든 조건을 무시하고 모든 행을 반환하라."

이로써, OR 등의 SQL 언어가 php에서 필터링 되지않는 것을 확인했다.
이제 본격적으로 테이블 이름을 추출하는 SQLi를 실행해보자.
테이블명을 추출하는 SQLi
' UNION SELECT 1, group_concat(table_name), 3 FROM information_schema.tables WHERE table_schema=database() --

1. 전제 조건 및 쿼리 시작 (' UNION SELECT)
작은따옴표(')
: 사용자가 입력하는 필드가 원래 SQL 쿼리에서 열려 있던 따옴표(')를 닫아주어, 공격자가 삽입한 코드가 구문 오류 없이 실행되도록 만든다.
UNION SELECT
: 앞서 실행된 취약한 원본 SELECT 쿼리의 결과와, 공격자가 뒤에 붙인 새로운 SELECT 쿼리의 결과를 하나로 합치도록 지시하는 핵심 연산자이다.
2. 칼럼 일치 및 데이터 추출 (1, group_concat(table_name), 3)
1, __, 3
: UNION 구문은 앞선 쿼리와 컬럼의 개수와 타입이 일치해야 하는데, 앞에서 칼럼 수가 3개인것을 확인
group_concat(table_name)
: table_name 필드에서 조회된 모든 테이블 이름을 쉼표(,)로 구분된 하나의 긴 문자열로 합쳐서 반환하는 함수
3. 정보원 및 조건 (FROM information_schema.tables WHERE...)
FROM information_schema.tables
: 데이터베이스의 스키마 정보(테이블, 칼럼 정의 등)를 담고 있는 특별한 시스템 데이터베이스
WHERE table_schema=database()
: 현재 사용 중인 데이터베이스의 이름을 반환
4. 나머지 쿼리 무시하고 종료 ( -- )
MySQL을 포함한 SQL에서 -- (뒤에 공백 필수)는 그 뒤에 오는 모든 내용을 주석(Comment) 처리하여 코드로 실행되지 않도록 무시하는 명령어
→ 웹페이지는 원래 데이터를 출력하는 대신, 두 번째 SELECT 문이 반환하는 값인 "1, 현재 모든 데이터베이스 이름, 3" 을 사용자에게 보여주게 된다.
다음은 얻은 테이블명을 바탕으로 칼럼명을 추출하는 SQLi를 실행한다.
칼럼명을 추출하는 SQLi
' UNION SELECT 1, group_concat(column_name), 3 FROM information_schema.columns WHERE table_name='pharaohs' --

1. 쿼리 결합 및 구조 맞추기 (' UNION SELECT 1, ..., 3)
칼럼개수 3개로 일치 시킨 후 UNION SELECT
2. 칼럼 이름 추출의 핵심 (group_concat(column_name))
MySQL에서 사용되는 함수로, 조회된 모든 column_name 값들을 쉼표로 구분된 하나의 긴 문자열로 합쳐서 반환한다. 이 결과가 웹 페이지에 노출되어 공격자가 숨겨진 칼럼명을 알 수 있게 된다.
secret_info 에 담긴 최종 힌트를 얻는 SQLi
' UNION SELECT 1, 2, secret_info FROM pharaohs WHERE id = 6 --

긴 문자열이 표시될 수도 있기때문에 secret_info 값을 세 번째 칼럼 위치에 표시
"where id=?" 부분을 제거하고 전체를 조회한 후 웹 페이지를 Inspect 해도 된다.
획득한 힌트는 어디에서 쓰이는 단서일까?
아까 웹 페이지의 view-source에서 발견한 또 다른 힌트이다.

해당 코드는 ROT13으로 인코딩 된 것을 확인했다.

The Pharaoh's cipher exists not for the gatekeeper's key, but for the logic of the Nile's unfolding map. Follow the flow to the next chamber.
→ "파라오의 암호는 문지기의 열쇠를 위한 것이 아니라, 펼쳐지는 나일강 지도의 논리를 위해 존재한다. 흐름을 따라 다음 방으로 나아가라."
이 문구는 SSH 접속 정보가 아님을 간접적으로 나타내며, 다음 웹 디렉토리를 이동해야 함을 비유적으로 알 수 있다.

최종 힌트를 보면 '/' 표시가 있는데, 이것을 보고 디렉토리 경로라는 것을 유추해볼 수 있다.
얻은 정보들을 바탕으로 "http://pyramidIP/the_architect_of_the_Great_Pyramid" 로 이동하면 다음 단계로 넘어간다.
'프로젝트' 카테고리의 다른 글
| 팀 프로젝트_CTF 만들기 (0) | 2025.09.24 |
|---|---|
| 개인 프로젝트_Network/System Security Full Project (0) | 2025.09.03 |
| 개인 CTF 만들기 아이디어 메모 (0) | 2025.09.02 |
| [8월 21일] 개인 과제_스크립트를 이용한 구구단 만들기 (0) | 2025.08.21 |
| [8월 19일] 팀 프로젝트_DNS서버 구축 (0) | 2025.08.19 |