codehaus


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Openstack-security] [Bug 1765834] Re: Need to verify content of v4-signed PUTs


Reviewed:  https://review.openstack.org/629301
Committed: https://git.openstack.org/cgit/openstack/swift/commit/?id=3a8f5dbf9c49fdf1cf2d0b7ba35b82f25f88e634
Submitter: Zuul
Branch:    master

commit 3a8f5dbf9c49fdf1cf2d0b7ba35b82f25f88e634
Author: Tim Burke <tim.burke at gmail.com>
Date:   Tue Dec 11 15:29:35 2018 -0800

    Verify client input for v4 signatures
    
    Previously, we would use the X-Amz-Content-SHA256 value when calculating
    signatures, but wouldn't actually check the content that was sent. This
    would allow a malicious third party that managed to capture the headers
    for an object upload to overwrite that with arbitrary content provided
    they could do so within the 5-minute clock-skew window.
    
    Now, we wrap the wsgi.input that's sent on to the proxy-server app to
    hash content as it's read and raise an error if there's a mismatch. Note
    that clients using presigned-urls to upload have no defense against a
    similar replay attack.
    
    Notwithstanding the above security consideration, this *also* provides
    better assurances that the client's payload was received correctly. Note
    that this *does not* attempt to send an etag in footers, however, so the
    proxy-to-object-server connection is not guarded against bit-flips.
    
    In the future, Swift will hopefully grow a way to perform SHA256
    verification on the object-server. This would offer two main benefits:
    
      - End-to-end message integrity checking.
      - Move CPU load of calculating the hash from the proxy (which is
        somewhat CPU-bound) to the object-server (which tends to have CPU to
        spare).
    
    Change-Id: I61eb12455c37376be4d739eee55a5f439216f0e9
    Closes-Bug: 1765834


** Changed in: swift
       Status: New => Fix Released

-- 
You received this bug notification because you are a member of OpenStack
Security SIG, which is subscribed to OpenStack.
https://bugs.launchpad.net/bugs/1765834

Title:
  Need to verify content of v4-signed PUTs

Status in OpenStack Security Advisory:
  Won't Fix
Status in OpenStack Object Storage (swift):
  Fix Released
Status in Swift3:
  New

Bug description:
  This issue is being treated as a potential security risk under
  embargo. Please do not make any public mention of embargoed (private)
  security vulnerabilities before their coordinated publication by the
  OpenStack Vulnerability Management Team in the form of an official
  OpenStack Security Advisory. This includes discussion of the bug or
  associated fixes in public forums such as mailing lists, code review
  systems and bug trackers. Please also avoid private disclosure to
  other individuals not already approved for access to this information,
  and provide this same reminder to those who are made aware of the
  issue prior to publication. All discussion should remain confined to
  this private bug report, and any proposed fixes should be added to the
  bug as attachments.

  When we added support for v4 signatures, we (correctly) require that
  the client provide a X-Amz-Content-SHA256 header and use it in
  computing the expected signature. However, we never verify that the
  content sent actually matches the SHA! As a result, an attacker that
  manages to capture the headers for a PUT request has a 5-minute window
  to overwrite the object with arbitrary content of the same length:

  [11:50:08] $ echo 'GOOD' > good.txt

  [11:50:12] $ echo 'BAD!' > bad.txt

  [11:50:36] $ s3cmd put --debug good.txt s3://bucket
  DEBUG: s3cmd version 1.6.1
  DEBUG: ConfigParser: Reading file '/Users/tburke/.s3cfg'
  DEBUG: ConfigParser: access_key->te...8_chars...r
  DEBUG: ConfigParser: secret_key->te...4_chars...g
  DEBUG: ConfigParser: host_base->saio:8080
  DEBUG: ConfigParser: host_bucket->saio:8080
  DEBUG: ConfigParser: use_https->False
  DEBUG: Updating Config.Config cache_file ->
  DEBUG: Updating Config.Config follow_symlinks -> False
  DEBUG: Updating Config.Config verbosity -> 10
  DEBUG: Unicodising 'put' using UTF-8
  DEBUG: Unicodising 'good.txt' using UTF-8
  DEBUG: Unicodising 's3://bucket' using UTF-8
  DEBUG: Command: put
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  INFO: Compiling list of local files...
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: Unicodising '' using UTF-8
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: Applying --exclude/--include
  DEBUG: CHECK: good.txt
  DEBUG: PASS: u'good.txt'
  INFO: Running stat() and reading/calculating MD5 values on 1 files, this may take some time...
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: doing file I/O to read md5 of good.txt
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  INFO: Summary: 1 local files to upload
  DEBUG: attr_header: {'x-amz-meta-s3cmd-attrs': 'uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212'}
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: String 'good.txt' encoded to 'good.txt'
  DEBUG: CreateRequest: resource[uri]=/good.txt
  DEBUG: Using signature v4
  DEBUG: get_hostname(bucket): saio:8080
  DEBUG: canonical_headers = content-length:5
  content-type:text/plain
  host:saio:8080
  x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  x-amz-date:20180420T185102Z
  x-amz-meta-s3cmd-attrs:uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212
  x-amz-storage-class:STANDARD

  DEBUG: Canonical Request:
  PUT
  /bucket/good.txt

  content-length:5
  content-type:text/plain
  host:saio:8080
  x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  x-amz-date:20180420T185102Z
  x-amz-meta-s3cmd-attrs:uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212
  x-amz-storage-class:STANDARD

  content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-meta-s3cmd-attrs;x-amz-storage-class
  e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  ----------------------
  DEBUG: signature-v4 headers: {'x-amz-content-sha256': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'content-length': '5', 'x-amz-storage-class': 'STANDARD', 'x-amz-meta-s3cmd-attrs': 'uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212', 'x-amz-date': '20180420T185102Z', 'content-type': 'text/plain', 'Authorization': 'AWS4-HMAC-SHA256 Credential=test:tester/20180420/US/s3/aws4_request,SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-meta-s3cmd-attrs;x-amz-storage-class,Signature=e79e1dd2fcd3ba125d3186abdbaf428992c478ad59380eab4d81510cfc494e43'}
  DEBUG: Unicodising 'good.txt' using UTF-8
  upload: 'good.txt' -> 's3://bucket/good.txt'  [1 of 1]
  DEBUG: DeUnicodising u'good.txt' using UTF-8
  DEBUG: Using signature v4
  DEBUG: get_hostname(bucket): saio:8080
  DEBUG: canonical_headers = content-length:5
  content-type:text/plain
  host:saio:8080
  x-amz-content-sha256:d43cf775e7609f1274a4cd97b7649be036b01a6e22d6a04038ecd51811652cf7
  x-amz-date:20180420T185102Z
  x-amz-meta-s3cmd-attrs:uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212
  x-amz-storage-class:STANDARD

  DEBUG: Canonical Request:
  PUT
  /bucket/good.txt

  content-length:5
  content-type:text/plain
  host:saio:8080
  x-amz-content-sha256:d43cf775e7609f1274a4cd97b7649be036b01a6e22d6a04038ecd51811652cf7
  x-amz-date:20180420T185102Z
  x-amz-meta-s3cmd-attrs:uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212
  x-amz-storage-class:STANDARD

  content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-meta-s3cmd-attrs;x-amz-storage-class
  d43cf775e7609f1274a4cd97b7649be036b01a6e22d6a04038ecd51811652cf7
  ----------------------
  DEBUG: signature-v4 headers: {'x-amz-content-sha256': 'd43cf775e7609f1274a4cd97b7649be036b01a6e22d6a04038ecd51811652cf7', 'content-length': '5', 'x-amz-storage-class': 'STANDARD', 'x-amz-meta-s3cmd-attrs': 'uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212', 'x-amz-date': '20180420T185102Z', 'content-type': 'text/plain', 'Authorization': 'AWS4-HMAC-SHA256 Credential=test:tester/20180420/US/s3/aws4_request,SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-meta-s3cmd-attrs;x-amz-storage-class,Signature=63a27138d8f6fd0320a15f8ef8bf95474246c80a38ed68693c58173cefd8589b'}
  DEBUG: get_hostname(bucket): saio:8080
  DEBUG: ConnMan.get(): creating new connection: http://saio:8080
  DEBUG: non-proxied HTTPConnection(saio:8080)
  DEBUG: format_uri(): /bucket/good.txt
   5 of 5   100% in    0s   373.44 B/sDEBUG: ConnMan.put(): connection put back to pool (http://saio:8080#1)
  DEBUG: Response: {'status': 200, 'headers': {'content-length': '0', 'x-amz-id-2': 'tx98be5ca4733e430eb4a76-005ada3696', 'x-trans-id': 'tx98be5ca4733e430eb4a76-005ada3696', 'last-modified': 'Fri, 20 Apr 2018 18:51:03 GMT', 'etag': '"f9d9dc2bab2572ba95cfd67b596a6d1a"', 'x-amz-request-id': 'tx98be5ca4733e430eb4a76-005ada3696', 'date': 'Fri, 20 Apr 2018 18:51:02 GMT', 'content-type': 'text/html; charset=UTF-8', 'x-openstack-request-id': 'tx98be5ca4733e430eb4a76-005ada3696'}, 'reason': 'OK', 'data': '', 'size': 5L}
   5 of 5   100% in    0s    56.02 B/s  done
  DEBUG: MD5 sums: computed=f9d9dc2bab2572ba95cfd67b596a6d1a, received="f9d9dc2bab2572ba95cfd67b596a6d1a"
  /Users/tburke/.virtualenvs/Python27/lib/python2.7/site-packages/magic/identify.py:62: RuntimeWarning: Implicitly cleaning up <magic.api.LP_Cookie object at 0x110369050>
    CleanupWarning)

  [11:51:02] $ curl -v http://saio:8080/bucket/good.txt -T bad.txt -H 'x-amz-content-sha256: d43cf775e7609f1274a4cd97b7649be036b01a6e22d6a04038ecd51811652cf7' -H 'x-amz-storage-class: STANDARD' -H 'x-amz-meta-s3cmd-attrs: uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212' -H 'x-amz-date: 20180420T185102Z' -H 'content-type: text/plain' -H 'Authorization: AWS4-HMAC-SHA256 Credential=test:tester/20180420/US/s3/aws4_request,SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-meta-s3cmd-attrs;x-amz-storage-class,Signature=63a27138d8f6fd0320a15f8ef8bf95474246c80a38ed68693c58173cefd8589b'
  *   Trying 192.168.8.80...
  * TCP_NODELAY set
  * Connected to saio (192.168.8.80) port 8080 (#0)
  > PUT /bucket/good.txt HTTP/1.1
  > Host: saio:8080
  > User-Agent: curl/7.54.0
  > Accept: application/json;q=1, text/*;q=.9, */*;q=.8
  > x-amz-content-sha256: d43cf775e7609f1274a4cd97b7649be036b01a6e22d6a04038ecd51811652cf7
  > x-amz-storage-class: STANDARD
  > x-amz-meta-s3cmd-attrs: uid:501/gname:staff/uname:tburke/gid:20/mode:33188/mtime:1524250212/atime:1524250212/md5:f9d9dc2bab2572ba95cfd67b596a6d1a/ctime:1524250212
  > x-amz-date: 20180420T185102Z
  > content-type: text/plain
  > Authorization: AWS4-HMAC-SHA256 Credential=test:tester/20180420/US/s3/aws4_request,SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-meta-s3cmd-attrs;x-amz-storage-class,Signature=63a27138d8f6fd0320a15f8ef8bf95474246c80a38ed68693c58173cefd8589b
  > Content-Length: 5
  > Expect: 100-continue
  >
  < HTTP/1.1 100 Continue
  * We are completely uploaded and fine
  < HTTP/1.1 200 OK
  < Content-Length: 0
  < x-amz-id-2: tx348d466b04cd425b81760-005ada3718
  < Last-Modified: Fri, 20 Apr 2018 18:53:13 GMT
  < ETag: "6cd890020ad6ab38782de144aa831f24"
  < x-amz-request-id: tx348d466b04cd425b81760-005ada3718
  < Content-Type: text/html; charset=UTF-8
  < X-Trans-Id: tx348d466b04cd425b81760-005ada3718
  < X-Openstack-Request-Id: tx348d466b04cd425b81760-005ada3718
  < Date: Fri, 20 Apr 2018 18:53:13 GMT
  <
  * Connection #0 to host saio left intact

  ---

  I've attached a fix, but it could use tests :-/

To manage notifications about this bug go to:
https://bugs.launchpad.net/ossa/+bug/1765834/+subscriptions