Hello,

On 31.05.21 18:36, Maxim Dounin wrote:

Thanks for the patch.  You may want to elaborate a bit more on how
do you expect these variables to be used.

[...]


These variables can be used to implement authentication with channel binding in an http application.

There are two channel binding types:

- tls-unique: This is a value which will be different for every connection. Even if an attacker manages to perform a MitM attack (e.g. because he stole the private key of the server) the tls-unique value for the connections client<->attacker and for the connections attacker<->server will be different. This means an authentication protocol which uses channel binding will detect the attacker. This is used e.g. by RFC8120: https://datatracker.ietf.org/doc/html/rfc8120#section-7

- tls-server-end-point: This is a hash over the server certificate. Unlike tls-unique this will not detect an attack where the attacker has stolen the server key, but it will detect e.g. when a CA was compromised or when the user asked the browser to connect despite the certificate being invalid. tls-server-end-point is also used e.g. by SPNEGO-based HTTP authentication (https://datatracker.ietf.org/doc/html/rfc4559, often used single-sign-on in web application using Kerberos). Unlike tls-unique tls-server-end-point can be implemented without support by NGINX (by putting the server certificate into the configuration of the web application), but this is fragile (e.g. when the server certificate is changed) and will not work at all when the server is configured with multiple certificates (because the web application cannot know which one was used).

I've attached a flask application + a client which shows how this can be used, the required configuration in NGINX (when using fastcgi) is:

fastcgi_param SSL_CHANNEL_BINDING_TLS_UNIQUE $ssl_channel_binding_tls_unique; fastcgi_param SSL_CHANNEL_BINDING_TLS_SERVER_END_POINT $ssl_channel_binding_tls_server_end_point;

Running the client will print:
python3 client.py https://localhost:1443
Client tls-unique b'AF6E9B00BE510405DEA0EC53'
Client tls-server-end-point 8cedd6e65cae9d1304163e0331a3e9bc8e0312bee92ac4f1ac5f972ceaddf08e Repsonse from server b'{"SSL_CHANNEL_BINDING_TLS_SERVER_END_POINT":"8cedd6e65cae9d1304163e0331a3e9bc8e0312bee92ac4f1ac5f972ceaddf08e","SSL_CHANNEL_BINDING_TLS_UNIQUE":"af6e9b00be510405dea0ec53"}\n'

(And the values seen by the client and the server should be the same.)


Best regards,
Steffen Kieß
import flask

app = flask.Flask('Test')

@app.route("/", methods=['GET'])
def home():
    data = {
        'SSL_CHANNEL_BINDING_TLS_UNIQUE': flask.request.environ['SSL_CHANNEL_BINDING_TLS_UNIQUE'],
        'SSL_CHANNEL_BINDING_TLS_SERVER_END_POINT': flask.request.environ['SSL_CHANNEL_BINDING_TLS_SERVER_END_POINT'],
    }
    response = flask.make_response(flask.jsonify(data))
    response.headers['Content-Type'] = 'application/json'
    return response
#!/usr/bin/python3

import urllib3
import urllib.parse
import ssl
import base64
import hashlib
import json
import io
import sys

if len(sys.argv) != 2:
    print('Usage: client.py <URL>')
    sys.exit(1)

url = sys.argv[1]
parsed = urllib.parse.urlparse(url)
if parsed.scheme != 'https':
    raise Exception('URL scheme is not https')

#context = ssl.create_default_context()
context = ssl._create_unverified_context()

hostname = parsed.hostname
port = parsed.port or 443

conn = urllib3.connection.VerifiedHTTPSConnection(hostname, port, ssl_context=context)
conn.set_cert()
conn.connect()

conn.sock.do_handshake()
server_certificate = conn.sock.getpeercert(True)
certificate_hash = hashlib.sha256(server_certificate).hexdigest()
certificate_digest = base64.b16decode(certificate_hash.upper())
application_data = b'tls-server-end-point:%s' % certificate_digest

print('Client tls-unique', base64.b16encode(conn.sock.get_channel_binding('tls-unique')))
print('Client tls-server-end-point', certificate_hash)

conn.request('GET', url)
re = conn.getresponse()
re = urllib3.HTTPResponse.from_httplib(re)
print('Repsonse from server', re.data)
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to