wget stores a file’s origin URL vulnerability (CVE-2018-20483)

최근에 twitter에서 wget의 문제점에 대해 이야기가 좀 돌았었습니다. (https://twitter.com/gynvael/status/1077671412847046657 )

결국은 보안 이슈로 잠정적인 의견이 모이는 분위기였고, 결국 CVE 넘버링을 달게 되었네요. 어떤 이슈고 어떤 리스크를 가질 수 있는지 정리해봅시다.

Vulnerability?

1.20.1 버전 이하에서(거의 대부분의 버전입니다.., 패치가 내려간 것 같아요.) wget 으로 파일을 받아오는 경우 파일 메타 데이터 영역에 origin url 이 남게됩니다.

#> wget https://www.hahwul.com
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: 'index.html'

index.html 파일을 받았는데, 이 html 파일의 메타 데이터를 보면..

#> getfattr -d index.html
# file: index.html
user.xdg.origin.url="https://www.hahwul.com/"

user.xdg.origin.url에 다운로드된 주소가 남아있습니다.

여기까지 보면 별다른게 없는 것 같지만, wget을 어떤 방식으로 운영하냐에 따라서 여러가지 케이스가 존재할 것 같습니다.

1. HTTP Auth를 사용하는 URL에 접근하는 경우

간혹 http 인증을 통해 파일을 다운로드 받는 경우 파일의 메타 데이터를 통해 로그인 정보가 노출될 수 있습니다.

#> wget https://id:pw@www.hahwul.com
#> getfattr -d index.html
# file: index.html
user.xdg.origin.url="https://id:pw@www.hahwul.com/"

메타 데이터 자체가 파일에 기록된 정보다 보니 서버단 이외에 사용자단에서 파일을 접근하거나 가져갈 수 있는 경우 정보가 노출될 가능성이 존재합니다.

2. private url에서 파일을 받는 경우

외부에서 접근 불가능한 도메인에서 파일을 받아 사용자에게 제공하는 형태의 기능이 있다면 url 주소가 노출될 수 있습니다.

#> wget https://iamprivatedomain/image.png

3. url에 인증정보가 포함된 요청인 경우

wget으로 이런 케이스의 파일을 호출할일이 많진 않을 것 같으나, 그래도 있을법한 케이스라 넣어두었습니다. 일부 서비스들은 url에 sessionid나 token같은 중요 데이터를 포함하는 경우가 있는데, 이 또한 다운로드된 파일이 노출되었을 때 해당 정보 획득이 가능할 것 같습니다.

#> wget https://domaindomain/?sessionid=a8a76ba576bb85ab65ab6765a4654d67s5

Code review

wget 코드중 xattr.c 파일 내 set_file_metadata 부분이 문제였습니다. https://github.com/mirror/wget/blob/master/src/xattr.c

아래 함수에서 다운받은 파일에 대해 metadata를 기록하는데, origin_url 값이 쓰여집니다.

int
set_file_metadata (const struct url *origin_url, const struct url *referrer_url, FILE *fp)
{
  /* Save metadata about where the file came from (requested, final URLs) to
   * user POSIX Extended Attributes of retrieved file.
   *
   * For more details about the user namespace see
   * [http://freedesktop.org/wiki/CommonExtendedAttributes] and
   * [http://0pointer.de/lennart/projects/mod_mime_xattr/].
   */
  int retval = -1;
  char *value;

  if (!origin_url || !fp)
    return retval;

  value = url_string (origin_url, URL_AUTH_HIDE);
  retval = write_xattr_metadata ("user.xdg.origin.url", escnonprint_uri (value), fp);
  xfree (value);

  if (!retval && referrer_url)
    {
  struct url u;

  memset(&u, 0, sizeof(u));
      u.scheme = referrer_url->scheme;
      u.host = referrer_url->host;
      u.port = referrer_url->port;

      value = url_string (&u, 0);
      retval = write_xattr_metadata ("user.xdg.referrer.url", escnonprint_uri (value), fp);
      xfree (value);
    }

  return retval;
}

로직 자체에 문제가 있는건 아니지만, 의도했던 기능이 다른 보안적인 문제를 불러오게 되었네요. 그리고 잘 보시면 음? 하셨을 부분이 있는데, referrer.url 또한 조건에 맞으면 메타데이터를 남깁니다. 상황에 따라 이 부분도 문제가 될 수 있겠네요.

How to fix?

우선 wget이 패치가 나왔으니 업데이트 해주시면 해결 가능합니다.

#> wget https://www.hahwul.com
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html’
#> getfattr index.html
# file: index.html
user.xdg.origin.url

그리고.. 패치와 별개로 취약 버전의 wget 으로 받은 파일에 대해선 중요한 정보가 남아있진 않은지 체크가 필요할 것 같네요.