Conditions for SNI to take effect - Supplement the prerequisites for SNI bypass in nginx-host bypass instance recurrence

In the previous article , through a series of analysis, we discovered a SQL injection vulnerability based on the host field injection in a server group system under the LNMP architecture. When solving the HOST bypass problem, we give three solutions. Separate by colon, double write the host field, and use the SNI mechanism.

After testing, the colon split is feasible, and the double-written host field is returned by a higher version of nginx as 400, which cannot be used. The last one is the SNI mechanism.

SNI (Server Name Indication), defined in RFC 4366, is a technology for improving SSL/TLS and is enabled in SSLv3/TLSv1. It allows the client to submit the requested Host information when it initiates an SSL handshake request (specifically, the ClientHello phase in the client's SSL request), so that the server can switch to the correct domain and return the corresponding certificate.

We know that the certificate mechanism exists to encrypt communication traffic and prevent third-party eavesdropping. When configuring multiple websites on the same host, virtual host technology will be used, and the certificates corresponding to each website are also different. So which certificate will be used to communicate when the user establishes a connection with the server for the first time? At first, the default certificate was used, and then in order to meet such needs, RFC introduced the SNI mechanism. In the early stage of the TLS protocol, that is, when the client sends its own client hello message, the host field is added to it for the server to distinguish purposes. website. Select the corresponding certificate.

The certificate then encrypts the communication for both the client and the server, that is. Once the subsequent communication is found to be decrypted with a certain certificate. There is no need to make further judgments, and the data packet can be directly delivered to the corresponding website. That is to say, after a stable https communication is established, the server middleware will not need to analyze the host header, and directly implement directional analysis through the certificate.

Then, we will have a series of thoughts.

First: Will the SNI mechanism be triggered all the time? Single https virtual host -> multiple https virtual hosts

Second: Control the certificate as a variable, and test the impact of the certificate on traffic analysis? —> Prove that the certificate private key is used to distinguish traffic

Third: Control the port number as a variable, and test the impact of the port number on traffic analysis?

1. Pre-environment construction

In this case, we need to prepare two complete sets of nginx parsing https virtual hosts for testing. and a server certificate and private key.

#1.双证书准备
#1.创建证书目录
[root@blackstone nginx]# mkdir certificate
[root@blackstone nginx]# cd certificate/

#2.生成私钥 - 要求你输入这个key文件的密码。给nginx使用。每次reload nginx配置时候都要验证这个PAM密码。
openssl genrsa -des3 -out ssl.key 4096
openssl genrsa -des3 -out sslb.key 4096
#3.生成CA证书文件 -- 此处为了区分证书,我们只好开两份CA证书相当于两个机构的认证
openssl req -new -key ssl.key -out aaa.csr
openssl req -new -key sslb.key -out bbb.csr

#4.利用CA证书签名生成服务器身份证书 - 证书签发有效期365天
openssl x509 -req -days 365 -in aaa.csr -signkey ssl.key -out aaa.crt
openssl x509 -req -days 365 -in bbb.csr -signkey sslb.key -out bbb.crt
#5.检查生成情况 - 此时包含我们自己的私钥,自己的证书.crt文件,以及csrCA证书
[root@blackstone certificate]# ll
total 32
-rw-r--r-- 1 root root 1895 Feb 10 23:34 aaa.crt
-rw-r--r-- 1 root root 1724 Feb 10 23:32 aaa.csr
-rw-r--r-- 1 root root 1907 Feb 11 00:52 bbb.crt
-rw-r--r-- 1 root root 1728 Feb 11 00:51 bbb.csr
-rw-r--r-- 1 root root 3311 Feb 11 00:50 sslb.key
-rw-r--r-- 1 root root 3311 Jan 11 21:24 ssl.key

Web deployment

[root@blackstone www]# mkdir -p /var/www/aaa
[root@blackstone www]# mkdir -p /var/www/bbb
[root@blackstone www]# echo 'this is aaa.com' > /var/www/aaa/index.html
[root@blackstone www]# echo 'this is bbb.com' > /var/www/bbb/index.html

Remember to modify the host file of this machine: C:\Windows\System32\drivers\etc

192.168.2.169 www.bbb.com 
192.168.2.169 www.aaa.com

2. Test SNI effective conditions (time)

1. Single https virtual host

 server {
    
    
        listen       443 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }


    }

Restart nginx, use a browser to access, and perform packet capture analysis.

#后面的所有重启都建议直接把nginx关闭,彻底重启
[root@blackstone www]# /usr/local/nginx/sbin/nginx -s quit
Enter PEM pass phrase:
[root@blackstone www]# /usr/local/nginx/sbin/nginx
Enter PEM pass phrase:

It can be seen that the host name is indeed sent to the server inside the client hello message.
insert image description here
Therefore, sending the host name is a spontaneous behavior of the high-version browser and does not require any triggering conditions. The browser will actively send the server name to support the SNI mechanism. That is, the SNI mechanism does not need to be configured, as long as the server supports it, it can be used.

3. The impact of certificates on SNI

3.1 Both parties use the same certificate:

    server {
    
    
        listen       443 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }


    }

    server {
    
    
        listen       443 ssl;
        server_name  www.bbb.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/bbb;
            index  index.html index.htm;
        }


    }

Test access:

insert image description here
insert image description here
Diversion can be achieved.

3.2 Both parties use different certificates and private keys

At this time, we try to distinguish between certificates and private keys:

server {
    
    
        listen       443 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }


    }
    
server {
    
    
        listen       443 ssl;
        server_name  www.bbb.com;

        ssl_certificate      /usr/local/nginx/certificate/bbb.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/sslb.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/bbb;
            index  index.html index.htm;
        }
    }

Test access effect again:

[root@blackstone certificate]# /usr/local/nginx/sbin/nginx -s reload
Enter PEM pass phrase:
Enter PEM pass phrase:

insert image description here
insert image description here
Each can receive its own certificate and establish its own communication.

4. Port number discrimination test

4.1 Port number distinction, certificate distinction:

server {
    
    
        listen       8443 ssl;
        server_name  www.bbb.com;

        ssl_certificate      /usr/local/nginx/certificate/bbb.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/sslb.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/bbb;
            index  index.html index.htm;
        }


    }
  server {
    
    
        listen       8444 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }


Test results:

[root@blackstone certificate]# vim ../conf/nginx.conf
[root@blackstone certificate]# /usr/local/nginx/sbin/nginx -s reload
Enter PEM pass phrase:
Enter PEM pass phrase:

insert image description here

insert image description here
It can be seen that the certificates have been sent to the two virtual host clients respectively. Realize traffic differentiation

4.2 The port number is distinguished, but the certificate is not distinguished:

server {
    
    
        listen       8443 ssl;
        server_name  www.bbb.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/bbb;
            index  index.html index.htm;
        }


    }


    server {
    
    
        listen       8444 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }

If the effect is not obvious in the middle, you can restart the nginx service, because there may be cache files when the service is always on.

[root@blackstone nginx]# /usr/local/nginx/sbin/nginx -s quit
Enter PEM pass phrase:
Enter PEM pass phrase:
[root@blackstone nginx]# /usr/local/nginx/sbin/nginx
Enter PEM pass phrase:
Enter PEM pass phrase:

Test again to see the effect:

insert image description here
insert image description here
The server passes the same certificate twice to realize communication. Achieve complete virtual hosting offload access.

5. Summarize the operation mechanism of SNI

Through the above tests, we found that regardless of the same port number, the certificates are different. Achieve the effect of differentiated transfer of certificates. Or the certificate is different, the port number is also different to realize the virtual host configuration in the test environment. SNI can always find the target host accurately, even when our certificates are the same.

In fact, this is not puzzling at all. Let's review the TSL communication process we have learned before:

The first handshake: the client sends the protocol version number, random number, and support package. The
second handshake: the server sends the random number, version number, and confirms the support package. At the same time, send the server certificate to indicate your identity (equivalent to sending an ID card).
The third handshake: the client receives the certificate, performs identity verification, and uses the public key taken from the certificate to encrypt and transmit a new string of random numbers pre_master to the server after verification. At this time, the client and the server both share three random numbers, the client random number, the server random number, and pre_master. Therefore, according to the three random numbers, both parties can calculate a common encrypted symmetric key for communication. After the session key is generated, the client sends a "Change Cipher Spec" to tell the server to start using encryption to send messages. Send another "Encrypted Handshake Message (Finishd)" message, make a summary of all the previously sent data, and then encrypt it with the session key (master secret), let the server do a verification to verify whether the encrypted communication is available and the previous handshake information Whether it has been tampered with halfway.
The fourth handshake: The server does the same operation, sending "Change Cipher Spec" and "Encrypted Handshake Message" messages. If both parties verify that the encryption and decryption are OK, the handshake is officially completed.
The last is to use the session key to communicate between the two parties

That is to say, the key in the client-server communication process is newly negotiated. Such a key with unique identification. Then through the SNI mechanism, the server name sent when the client sends the client hello packet for the first time determines which virtual host to visit. In the subsequent communication, the corresponding virtual host can naturally be found through the decryption key. This completes the complete SNI mechanism.

It is realized that this different server certificate can be configured for different virtual hosts.

6. SNI mechanism bypasses host header exploration

The environment where such a bypass occurs is obvious, it must be an nginx server configured with SSL.

Some students have raised questions before, thinking that only a virtual SSL host with port 443 is configured. It is difficult to distinguish whether our request was transferred to the default 443 port processing virtual host, or did we successfully bypass such a detection mechanism? Following the 3.2 environment, we conduct further tests on it:

6.1 SSL virtual host with the same port

#注意那个server在上面,在配置文件里就默认的是默认虚拟主机
    server {
    
    
        listen       443 ssl;
        server_name  www.bbb.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/bbb;
            index  index.html index.htm;
        }


    }

 server {
    
    
        listen       443 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }


    }

insert image description here
Under the same port number and different certificate conditions, after modifying the host file, it jumps to the default bbb.com virtual host. Bypass failure

6.2 SSL virtual hosts with different ports

 server {
    
    
        listen       443 ssl;
        server_name  www.bbb.com;

        ssl_certificate      /usr/local/nginx/certificate/bbb.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/sslb.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/bbb;
            index  index.html index.htm;
        }


    }

 server {
    
    
        listen       8443 ssl;
        server_name  www.aaa.com;

        ssl_certificate      /usr/local/nginx/certificate/aaa.crt;
        ssl_certificate_key  /usr/local/nginx/certificate/ssl.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
    
    
            root   /var/www/aaa;
            index  index.html index.htm;
        }


    }

Access effect:
insert image description here
insert image description here
test again:
insert image description here
this time there is no jump to the default, indicating that it is feasible.

6.3 Summary

The condition for SNI to bypass the host to take effect is actually to bind only one SSL virtual host under a single port. Because we saw in 6.1 that when multiple SSL hosts are bound to the same server with the same port, all requests will be sent to the default page. If the vulnerability is on the default page, it's fine, if not. It cannot be bypassed using SNI.

But at the same time, if the server is a single ssl virtual host configured with port 443, then the HOST header of the SNI mechanism can be bypassed.

Guess you like

Origin blog.csdn.net/qq_55316925/article/details/128988215
Recommended