Rails에서 배우는 SQL 주입 취약점

4585 단어 Rails보안
웹 보안에 대해 공부 중이므로 학습 내용을 공개합니다.
스카스카 기사이지만 용서해주세요

연습 환경


  • Ruby (2.6.6)
  • Rails (5.2.4.3)
  • database adapter mysql2 (0.5.3)

  • mysql (5.7.30)

  • 기사 투고, 코멘트 투고, 북마크 등을 할 수 있는 연습용 앱 「TARGET」
    GitHub 리포지토리 htps : // 기주 b. 코 m / 후미 타카 1 / 탄 t

    SQL 주입 취약점이란?



    외부로부터 받은 파라미터로부터 SQL문을 작성해, DB를 조작하고 있는 프로그램에 일어날 수 있는 취약성
    예 사용자 목록을 볼 수 있는 사이트가 있습니다.

    '소'로 검색하면 사용자 이름에 '소'를 포함하는 사용자가 표시됩니다.
    발행되는 SQL문 SELECT `users`.* FROM `users` WHERE (name LIKE '%小%')

    아래의 공격용 문자열로 검색하면 해시화된 비밀번호가 표시됩니다.
    &&') UNION SELECT 1, encrypted_password, 3,4,5,6,7,8,9,10,11 FROM target_development.users;#

    발행되는 SQL 문SELECT `users`.* FROM `users` WHERE (name LIKE '%&&') UNION SELECT 1, encrypted_password, 3,4,5,6,7,8,9,10,11 FROM target_development.users;# %')
    ※공격 문자열에 필요한 데이터베이스명이나 컬럼명은 informaiton_schema로부터 취득 가능합니다

    왜 발생하는가



    외부의 매개 변수에 SQL 특수 문자가 포함되어 있고 예상치 못한 SQL 문이 발행되기 때문에
    위의 예에서
    1. 검색 문자열 &&')은 정규 SELECT 문을 잘못 종료합니다.
    2. 연속 문자열 UNION SELECT 1, encrypted_password, 3,4,5,6,7,8,9,10,11 FROM target_development.users;이 그대로 SQL로 발행됩니다.

    연습용 사이트에는 외부로부터의 파라미터를 그대로 받아 SQL문을 발행하는 취약한 처리가 포함되어 있다

    users_controller.rb
      def index
        @users = User.where("name LIKE '%#{params[:q]}%'")
      end
    

    어떻게 막을까



    1. 외부에서 매개변수에 포함된 특수 문자를 안전한 문자로 대체



    users_controller.rb
      def index
        sanitized_q = params[:q].gsub(/\'/,'\\\'') if params[:q]
        @users = User.where("name LIKE '%#{sanitized_q}%'")
      end
    

    2. 자리표시자를 이용하여 SQL문을 발행한다.



    users_controller.rb
      def index
        @users = User.where("name LIKE ?","%#{params[:q]}%")
      end
    

    Rails는 SQL 특수 문자 필터를 제공합니다.


  • Model.find(id)
  • Model.find_by_hoge (fuga)
  • Model.where(hoge: fuga) # 해시를 사용하면 자리 표시자와 동등

  • 배운 것



    SQL 인젝션은 잘 알려진 취약성이기 때문에, 프레임워크 측에서 대응책이 준비되어 있지만, 외부 파라미터로부터 SQL문을 작성하는 경우에는 충분히 주의를 기울인다.
    ORM 덕분에 SQL을 작성할 기회가 적었지만, 이 기회에 SQL을 파고들 수 있었다.

    좋은 웹페이지 즐겨찾기