anomalizer / ngx_aws_auth

nginx module to proxy to authenticated AWS services
BSD 2-Clause "Simplified" License
470 stars 144 forks source link

SignatureDoesNotMatch for encoded URI with special character '+' #87

Closed thindrs closed 1 year ago

thindrs commented 1 year ago

Details

Good day.

Noticing the SignatureDoesNotMatch issue when accessing a S3 key with special character '+' in it. Able to repro the issue consistently. S3 keys that do not have '+' special character work fine.

Steps to Repro:

<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>
...
<CanonicalRequest>
GET /libstdc%20%20-docs.x86_64.rpm host:XXXXX-test-bucket01.s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20231004T172751Z host;x-amz-content-sha256;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
</CanonicalRequest>

nginx.conf

server {
        listen       8082;
        server_name  localhost;

        aws_access_key XXXXXXXXX; # Example AKIDEXAMPLE
        aws_key_scope 20231004/us-west-2/s3/aws4_request; #Example 20150830/us-east-1/service/aws4_request
        aws_signing_key XXXXXXXXXXXXXXXXXXX; 
        aws_s3_bucket XXXXXXXX-test-bucket01;

        location / {
            root   html;
            index  index.html index.htm;
            aws_sign;
            proxy_pass http://XXXXXXXX-test-bucket01.s3.amazonaws.com;
        }

Versions

$ sudo /usr/local/nginx-from-src/nginx -V
nginx version: nginx/1.24.0
built by gcc 7.3.1 20180712 (Red Hat 7.3.1-17) (GCC)
built with OpenSSL 1.1.1v  1 Aug 2023
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx-from-src --sbin-path=/usr/local/nginx-from-src/nginx --conf-path=/usr/local/nginx-from-src/nginx.conf --pid-path=/usr/local/nginx-from-src/nginx.pid --with-pcre=../pcre2-10.40 --with-zlib=../zlib-1.3 --with-http_ssl_module --with-stream --with-mail=dynamic --add-module=../ngx_aws_auth --with-debug

Nginx Logs

# Request
2023/10/04 17:27:51 [error] 30944#0: *1 canonical url extracted before URI encoding is /libstdc++-docs.x86_64.rpm, c
lient: 10.187.171.30, server: localhost, request: "GET /libstdc++-docs.x86_64.rpm HTTP/1.1", host: "172.19.24.58:808
2"
2023/10/04 17:27:51 [error] 30944#0: *1 canonical url extracted after URI encoding is /libstdc%2B%2B-docs.x86_64.rpm
, client: 10.187.171.30, server: localhost, request: "GET /libstdc++-docs.x86_64.rpm HTTP/1.1", host: "172.19.24.58:
8082"
2023/10/04 17:27:51 [debug] 30944#0: *1 malloc: 0000000000FA8160:10000
2023/10/04 17:27:51 [error] 30944#0: *1 canonical req is GET
/libstdc%2B%2B-docs.x86_64.rpm

host:XXXXXXX-test-bucket01.s3.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20231004T172751Z

host;x-amz-content-sha256;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855, client: 10.187.171.30, server: localhost, request:
 "GET /libstdc++-docs.x86_64.rpm HTTP/1.1", host: "172.19.24.58:8082"
 2023/10/04 17:27:51 [debug] 30944#0: *1 posix_memalign: 0000000000FAA880:4096 @16
2023/10/04 17:27:51 [debug] 30944#0: *1 header name host, value XXXXXXX-test-bucket01.s3.amazonaws.com4<9F>
2023/10/04 17:27:51 [debug] 30944#0: *1 header name x-amz-content-sha256, value e3b0c44298fc1c149afbf4c8996fb92427ae
41e4649b934ca495991b7852b855
2023/10/04 17:27:51 [debug] 30944#0: *1 header name x-amz-date, value 20231004T172751Z
2023/10/04 17:27:51 [debug] 30944#0: *1 header name authorization, value AWS4-HMAC-SHA256 Credential=AKIAXCGE7VOLQ7W
JG4Z6/20231004/us-west-2/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=73286ab0026b5f
17749ba6720f748a069085380883bb077571996265838d8fa42a8a9b8dfd65cf2^D

2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "authorization: AWS4-HMAC-SHA256 Credential=AKIAXCGE7VOLQ
7WJG4Z6/20231004/us-west-2/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=73286ab0026b
5f17749ba6720f748a069085380883bb077571996265838d8fa4"
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header:
"GET /libstdc++-docs.x86_64.rpm HTTP/1.0
Host: XXXXXXX.s3.amazonaws.com
Connection: close
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date: 20231004T172751Z
authorization: AWS4-HMAC-SHA256 Credential=AKIAXCGE7VOLQ7WJG4Z6/20231004/us-west-2/s3/aws4_request,SignedHeaders=hos
t;x-amz-content-sha256;x-amz-date,Signature=73286ab0026b5f17749ba6720f748a069085380883bb077571996265838d8fa4

"
# Response

2023/10/04 17:27:51 [debug] 30944#0: *1 http upstream request: "/libstdc++-docs.x86_64.rpm?"
2023/10/04 17:27:51 [debug] 30944#0: *1 http upstream process header
2023/10/04 17:27:51 [debug] 30944#0: *1 malloc: 0000000001003A90:4096
2023/10/04 17:27:51 [debug] 30944#0: *1 recv: eof:0, avail:-1
2023/10/04 17:27:51 [debug] 30944#0: *1 recv: fd:10 257 of 4096
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy status 403 "403 Forbidden"
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "x-amz-request-id: N8BNZZ83W06NCYW8"
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "x-amz-id-2: iuwOkkVNCq7wrW/xUBGtJTa644jGBG5uba1QDi1Nz343
7jbXFiKIfvjQXzSvbf0YSOE0GSEq808="
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "Content-Type: application/xml"
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "Date: Wed, 04 Oct 2023 17:27:51 GMT"
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "Server: AmazonS3"
2023/10/04 17:27:51 [debug] 30944#0: *1 posix_memalign: 0000000001004AA0:4096 @16
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header: "Connection: close"
2023/10/04 17:27:51 [debug] 30944#0: *1 http proxy header done
2023/10/04 17:27:51 [debug] 30944#0: *1 HTTP/1.1 403 Forbidden
Server: nginx/1.24.0
Date: Wed, 04 Oct 2023 17:27:51 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Connection: keep-alive
x-amz-request-id: N8BNZZ83W06NCYW8
x-amz-id-2: iuwOkkVNCq7wrW/xUBGtJTa644jGBG5uba1QDi1Nz3437jbXFiKIfvjQXzSvbf0YSOE0GSEq808=

Help much appreciated. Thanks in advance.

thindrs commented 1 year ago

And just to add, have gone through other related issues, and tried the proxy_pass solutions suggested there. proxy_pass to another nginx for example serves GET /libstdc++-docs.x86_64.rpm HTTP/1.0 correctly. However above problem happens when using aws_sign.

Example below config fetches the package fine from another nginx on the same machine:

location = /libstdc++-docs.x86_64.rpm {
            proxy_pass http://127.0.0.1:8081;
}
thindrs commented 1 year ago

For others facing similar problem, here is a workaround fix. Basically a combination this post and making sure the client that sends the request is already encoding the request.

Added following to the nginx conf:

        location /test-repo {
           aws_sign;
           proxy_pass http://BUCKET_NAME.s3.amazonaws.com;
        }

        location /v1/ {
            rewrite ^ $request_uri;
            rewrite /v1/(.*) /test-repo/$1 break;
            return 400;
            proxy_pass http://127.0.0.1:8082$uri;
        }

make sure client encodes the request:

Works

curl -v "http://172.19.24.58:8082/v1/hello-c%2B%2B-0.0.1-1.amzn2int.x86_64.rpm"

Does not work

curl -v "http://172.19.24.58:8082/v1/hello-c++-0.0.1-1.amzn2int.x86_64.rpm"

thindrs commented 1 year ago

Workaround fix shared above.