1. SQL Injection?

  1. [설명]
    1. 사용자의 입력값이 서버측에서 코드로 실행되는 ‘코드 인젝션’ 공격 긱법 중 하나입니다
    2. 서버의 데이터 베이스를 대상으로 하는 공격입니다
    3. 사용자 입력값을 제대로 필터링, 이스케이프 하지 않아 발생하는 것을 말합니다
    4. [사건사고]
      1. 2015년 뽐뿌 개인정보 노출 사고
      2. 2017년 여기어때 고객 정보 및 투숙 정보 노출사고
    5. [핵심]
      1. 클라이언트 측에서 SQL 쿼리에 신뢰할 수 없는 데이터가 입력되었을 때, 데이터가 쿼리 로직의 일부로 해석되어 DB에서 실행될 때 발생합니다
  2. [목적]
    1. SQL 구문에 추가 절을 삽입하게 되면 쿼리의 의미가 변경되고 의도하지 않은 데이터의 유출, 변조가 가능합니다
      1. 정보 유출(Information Leakage)
      2. 저장된 데이터 유출 및 조작(Disclosure & Manipulation of stored Data)
      3. 원격 코드 실행(Remote Code Excution)
        1. 일부 DB의 경우 확장 프로시저를 이용하여 원격으로 시스템 명령의 실행이 가능하다
        2. 시스템 명령의 실행은 원격 자원 접근 및 데이터 유출, 삭제가 가능합니다
      4. 인증 우회(Bypassing authorisation controls)
        1. 공격의 대표적인 경우로 로그인 폼 등에서 발생합니다
        2. 상위 권한을 가진 사용자의 권한으로 인증 절차를 우회하여 로그인 정보없이 로그인할 수 있습니다
  3. [공격구분]
    1. Classic SQLi

      1. 가장 일반적인 공격 방법입니다
      2. 공격자가 동일한 통신구간(브라우저)에서 공격을 시도하고 결과를 얻을 수 있습니다
      3. 사용자가 입력한 검색어가 where절 내에 바로 삽입되는 것을 확인하고 공격자는 SQLi공격을 시도합니다
    2. Union-based SQLi

      1. SQL구문에서 union은 두개나 그 이상의 select구문을 결합하여 하나의 결과로 출력합니다
      2. 공격자는 쿼리의 일부로 추가 구문을 삽입하여 HTTP응답으로 결과를 가져 올 수 있습니다
    3. [DB종류 발별법]

      1. Oracle

        1. select version from v$instance
      2. Microsoft

        1. select @@version
      3. PostgreSQL

        1. select version()
      4. MySQL

        1. select @@version
      5. SQLite

        1. select sqlite_version()
      6. [예제]

        ' UNION SELECT 1, 1, 1, version_request --
        
        1. 정확한 컬럼 수 찾기
        GET <https://my-vulnerable-site.com/product.php?id=1> ORDER BY <X>
        # 구문에서 'X'의 숫자를 1씩 늘리면서 시도하면 정확한 열의 수가 일치할 때 HTTP 응답에서 변화를 확인한다.
        
        2. 페이지에서 SQLi에 취약한 영역 찾기
        GET <https://my-vulnerable-site.com/product.php?id=1> UNION ALL SELECT 1,2,3,4,5--
        # 원본 쿼리가 사용자가 입력한 데이터를 검색한 결과를 나타내는 기능이라면 UNION을 사용하여 추가 쿼리를 실행한 결과까지 응답에 포함
        # 열의 개수가 일치하는 경우 숫자 1~5가 각 열에 표시되며 이를 이용해 더 많은 정보를 획득하려면 다음과 같이 사용한다.
        # 그 결과로 기존에 "4"가 보이던 위치에서 DB의 테이블 이름이 보이는 것을 확인할 수 있다.
        GET <https://my-vulnerable-site.com/product.php?id=1> UNION ALL SELECT 1,2,3,group_concat(table_name),5 FROM information_schema.tables WHERE table_schema = database()--
         
        
    4. Error-based SQLi

      1. 기본적으로 공격자가 데이터베이스의 구조를 얻고 이해하기 위해 서버에서 반환되는 에러에 의존합니다
      2. UNION Injection에서 열(Column)의 갯수를 찾기 위해 열의 갯수를 하나씩 올리면서 결과를 살폈던 것도 범위에 포함합니다
      3. 개발 시 응답에 포함되는 에러 정보는 개발자에게 큰 도움이 되지만 운영중인 웹애플리케이션에서의 자세한 에러 정보는 공격자에게 큰 도움됩니다
  4. [대응방법]
    1. 입력값 유효성 검사
      1. 기본적인 대응 전략으로 모든 외부 입력값을 신뢰하지 않으며, 항상 유효성을 검사하는 방법입니다
      2. [2가지 방식]
        1. 블랙리스트
          1. SQL쿼리의 구조를 변경시키는 문자나 키워드, 특수문자를 제한하는 방식입니다
          2. SQL의 예약어인 union, group by와 count등의 함수명, 세미콜론이나 주석등의 특수문자들을 블랙리스트로 미리 정의하고, 블랙리스트로 지정되어 있는 문자나 키워드가 외부 입력값 안에 존재하면 공백등으로 치환하는 방식을 방어해줍니다
          3. 입력값을 검증하지 않는다면 블랙 리스트 방식의 검증을 우회할 수 도 있으니 주의해야합니다
          4. 예시로 외부 입력값에 select라는 표현이 있을 때 중간의 select가 공백으로 치환되면 그 좌우에 있는 문자들이 합쳐져서 다시 select라는 키워드로 완성됩니다
        2. 화이트리스트
          1. 허용된 문자를 제외하고는 모두 허용하지 않는 방식으로 금지된 문자 외에는 모두 허용하는 블랙 리스트 방식보다 보안성 측면에서는 훨씬 더 강력한 방법입니다
          2. 웹 애플리케이션의 기능에 따라 알맞게 화이트 리스트를 작성해야 하는 번거로움이 존재합니다
          3. 번거로움을 극복하기 위해, 유지보수의 편리함을 증진시키기 위해 개별 문자를 일일이 하나씩 모두 정의하는 것보다 정규식 등을 이용해서 화이트 리스트를 범주화/패턴화 시키는 편이 좋다
    2. Prepared Statement사용
      1. 일반적으로 SQL쿼리의 실행과정은 구문분석(parsing) >> SQL최적화(optimization) >> 실행계획을 실행 가능한 코드로 포맷팅(Row Source Generation) >> 실행(Execute) >> 인출(Fatch) 총 다섯단계로 구성되어 있습니다
      2. 매번동적으로 쿼리를 생성하는 일반적인 Statement를 사용하게 되면 구문분석부터 인출까지 모든 과정을 수행한 것입니다
      3. Prepared Statmenet는 미리 쿼리에 대한 컴파일을 수행하고, 입력값을 나중에 넣는 방식을 말합니다
      4. 일반적인 Statement와는 달리 불필요하게 모든 과정을 수행하지 않고, 실행전까지의 과정을 최초 1번만 수행한 후 나중에는 실행전 미리 컴파일되어 있는 Prepared Statement를 가져다 쓰는 것을 말합니다
      5. 쿼리의 문법처리 과정이 미리 컴파일이 되어 있기 때문에, 외부 입력값으로 SQL관련 구문이나 특수문자가 들어와도 그것은 SQL문법으로서 역할을 할 수 없기 때문이다
    3. 오류 메세지 출력 제한
      1. [두가지 방법]
        1. DB관련 오류를 사용자에게 노출되지 않게 커스텀 오류 페이지를 만들어야합니다
        2. 너무 자세한 안내 메세지를 지양합니다
        3. 가령 로그인 실패시 패스워드가 일치하지 않습니다라는 메세지를 띄울 경우, 악의적인 사용자는 ID는 실제로 존재한다는 것을 알 수 있기에 가급적 “로그인에 실패하였습니다”를 메세지로 띄우는 것이 안정성에 좋습니다. 단 추상적인 메세지는 사용자의 편의성 및 사용성을 떨어뜨릴 수 도 있습니다
    4. DB보안
      1. 관리자가 사용하는 DB계정과 웹 애플리케이션 DB에 접근할 때 사용하는 계정을 분리시켜야 합니다
      2. 분리시킬 뿐만 아니라, 분리된 웹 애플리케이션이 사용하는 DB계정에 최소 권한만을 부여해줘야 합니다