Показаны сообщения с ярлыком tls. Показать все сообщения
Показаны сообщения с ярлыком tls. Показать все сообщения

четверг, 29 декабря 2022 г.

SSRF vulnerabilities caused by SNI proxy misconfigurations

  (It's a repost from https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/)

SNI proxies are load balancers that use the SNI extension field to select backend systems. When misconfigured, SNI proxies can be vulnerable to SSRF attacks that provide access to web application backends.

A typical task in complex web applications is routing requests to different backend servers to perform load balancing. Most often, a reverse proxy is used for this. Such reverse proxies work at the application level (over HTTP), and requests are routed based on the value of the Host header (:authority for HTTP/2) or parts of the path.

One typical misconfiguration is when the reverse proxy directly uses this information as the backend address. This can lead to server-side request forgery (SSRF) vulnerabilities that allow attackers to access servers behind the reverse proxy and, for example, steal information from AWS metadata. I decided to investigate similar attacks on proxy setups operating at other levels/protocols – in particular, SNI proxies.

What is TLS SNI?

Server Name Indication (SNI) is an extension of the TLS protocol that provides the foundation of HTTPS. When a browser wants to establish a secure connection to a server, it initiates a TLS handshake by sending a ClientHello message. This message may contain an SNI extension field that includes the server domain name. In its ServerHello message, the server can then return a certificate appropriate for the specified server name. The typical use case for this is when there are multiple virtual hosts behind one IP address.

What is an SNI proxy?

When a reverse proxy (more correctly, a load balancer) uses a value from the SNI field to select a specific backend server, we have an SNI proxy. With the widespread use of TLS and HTTPS in particular, this approach is becoming more popular. (Note that another meaning of SNI proxy refers to the use of such proxies to bypass censorship in some countries.)

There are two main options for running an SNI proxy: with or without SSL termination. In both cases, the SNI proxy uses the SNI field value to select an appropriate backend. When running with SSL termination, the TLS connection is established with the SNI proxy, and then the proxy forwards the decrypted traffic to the backend. In the second case, the SNI proxy forwards the entire data stream, really working more like a TCP proxy.

A typical SNI proxy configuration

Many reverse proxies/load balancers support SNI proxy configurations, including Nginx, Haproxy, Envoy, ATS, and others. It seems you can even use an SNI proxy in Kubernetes.

To give an example for Nginx, the simplest configuration would look as follows (note that this requires the Nginx modules ngx_stream_core_module and ngx_stream_ssl_preread_module to work):

stream {
    map $ssl_preread_server_name $targetBackend {
        test1.example.com backend1:443;
        test2.example.com backend2:9999;
    }

    server {
        listen 443; 
        resolver 127.0.0.11;
        proxy_pass $targetBackend:443;       
        ssl_preread on;
    }
}

Here, we configure a server (TCP proxy) called stream and enable SNI access using ssl_preread on. Depending on the SNI field value (in $ssl_preread_server_name), Nginx will route the whole TLS connection either to backend1 or backend2.

SNI proxy misconfigurations leading to SSRF

The simplest misconfiguration that would allow you to connect to an arbitrary backend would look something like this:

stream {
    server {
        listen 443; 
        resolver 127.0.0.11;
        proxy_pass $ssl_preread_server_name:443;       
        ssl_preread on;
    }
}

Here, the SNI field value is used directly as the address of the backend.

With this insecure configuration, we can exploit the SSRF vulnerability simply by specifying the desired IP or domain name in the SNI field. For example, the following command would force Nginx to connect to internal.host.com:

openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf

In general, according to RFC 6066, IP addresses should not be used in SNI values, but in practice, we can still use them. What’s more, we can even send arbitrary symbols in this field, including null bytes, which can be useful for exploitation. As you can see below, the server name can be changed to an arbitrary string. Though for this specific Nginx configuration, unfortunately, I did not find a way to change the backend port:

Another class of vulnerable configurations is similar to typical HTTP reverse proxy misconfigurations and involves mistakes in the regular expression (regex). In this example, traffic is forwarded to the backend if the name provided via SNI matches the regex:

stream {
    map $ssl_preread_server_name $targetBackend {
        ~^www.example\.com    $ssl_preread_server_name;
    }  

    server {
        listen 443; 
        resolver 127.0.0.11;
        proxy_pass $targetBackend:443;       
        ssl_preread on;
    }
}

This regex is incorrect because the first period character in www.example.com is not escaped, and the expression is missing the $ terminator at the end. The resulting regex matches not only www.example.com but also URLs like www.example.com.attacker.com or wwwAexample.com. As a result, we can perform SSRF and connect to an arbitrary backend. While we can’t use the IP address directly here, we can bypass this restriction simply by telling our DNS server that www.example.com.attacker.com should resolve to 127.0.0.1.

Potential directions for SNI proxy research and abuse

In a 2016 article about scanning IPv4 for open SNI proxies, researchers managed to find about 2500 servers with a fairly basic testing approach. While this number may seem low, SNI proxy configurations have become more popular since 2016 and are widely supported, as evidenced even by a quick search of GitHub. 

As a direction for further research, I can suggest a couple of things to think about for configurations without TLS termination. An SNI proxy checks only the first ClientHello message and then proxies all the subsequent traffic, even if it’s not correct TLS messages. Also, while the RFC specifies that you can only have one SNI field, in practice, we can send multiple different names (TLS-Attacker is a handy tool here). Because Nginx only checks the first value, there could (theoretically) be an avenue to gain some additional access if a backend accepts such a ClientHello message but then uses the second SNI value.

Avoiding SNI proxy vulnerabilities

Whenever you configure a reverse proxy, you should be aware that any misconfigurations may potentially lead to SSRF vulnerabilities that expose backend systems to attack. The same applies to SNI proxies, especially as they are gaining popularity in large-scale production systems. In general, to avoid vulnerabilities when configuring a reverse proxy, you should understand what data could be controlled by an attacker and avoid using it directly in an insecure way.

 

пятница, 17 июня 2016 г.

Remote detection of a user's AV using Flash

Attention, the method works not as well as it should

There is a possibility to find out a vendor of AV installed on a user's PC. Remotely and without detection from the user. This information could be useful for us if we want to attack the user.
The method is based on two main features.

The first feature. The most of modern AVs can detect malware analyzing network traffic. Usually, http and smtp/pop3/imap protocols are analyzed. However, as TLS is used more and more often, then an AV actually has to perform a man in the middle attack against a user application and a remote server. To bypass a certificate chain check, the AV installs its own root CA (root CA's private key is stored too) to the OS and uses it for "on fly" certificate creation for intercepted TLS connections.




The second feature. Flash supports raw TCP sockets. Actually, there is an opportunity to send/receive any tcp packet to any port of a remote server from a swf file in a browser. But as this feature could be an issue in terms of security, Flash supports crossdomain policy for sockets. If a swf file wants to connect a remote server via a raw socket, Flash connects to 843 tcp port on the server and sends a request ("<policy-file-request/>") and gets a crossdomain xml response. The crossdomian file contains information from which ports and from which domains are allowed to connect to the server.

Example of socket crossdomain:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
   <site-control permitted-cross-domain-policies="master-only"/>
   <allow-access-from domain="*" to-ports="443,995,465,587" />
</cross-domain-policy>
The curious thing happens when we use both of these features. If we simulate TLS connection from a swf file to a remote host on a specific port (443,587, etc.), then an AV intercepts it. So, our swf receives a TLS certificate generated by the AV and we detect a vendor of the AV from a root CA name.

The overall scheme of the method:
0) A user visits to our site. Our malicious swf is loaded by the user's browser.
1) Swf requests a socket crossdomain policy from 843 port of our server and gets required permissions.
2) Swf connects to our server (port 443, 465, etc.) and send a 'Client Hello' TLS packet (in raw bytes)
3) The server replies a 'Server Hello' TLS packets with the server’s certificate.
4) AV intercepts connections, generates a new certificate and signs it using the AV's own root CA
5) SWF receives the TLS packet (with a certificate) from AV and resends it to our server where we can parse it and get the name of root CA.




Actually, the idea of method is based on the research of Facebook - https://www.linshunghuang.com/papers/mitm.pdf. They used a special swf for a "real" MitM detection. But they didn't share the sources of the project.

I've created a PoC to test this method (it's far from real implementation) - https://github.com/GrrrDog/FlashAV. It consists of a special swf file and a python server. The swf sends a raw SSLv3 request and resends a response to the python server. The python server is used for certificate "parsing" and for crossdomain socket policy distribution.

Results:
My initial tests have been made on Avast AV. And it works great. I've got AV's certificates for IE and Chrome when Swf connects to 443 port. Avast has not intercepted connections from Firefox to 443 port of a server. However, in case of Firefox if swf connects to 465(587/995/etc) port (SMTPs), AV intercepts it and we can get a version of AV again.

Here is an example


Then I've tested the PoC on Kaspersky AV, but, unfortunately, unsuccessfully. KAV intercepts traffic from browsers, but it doesn't want to intercept connections from the swf (to any port).

I'm not an AV guru, so I'm sure that I've missed something. So I've decided to share this idea and these weird results to get some feedback from you.
You can play with SWF here https://dbggl.pw/flashav.swf  Nginx (443) and ncat (465, 995) are started on the server for testing.