Tag Archives: TLS

Letsencrypt certificates for your python HTTP servers

Back in 2016 I blogged about how to do simple HTTP or HTTPS servers with python. You need to use these if you want to temporarily host files, and to investigate SSRF issues properly.

There my skills sat until recently the user-agent that was making the SSRF request was actually verifying the certificate. How rude! So I needed to up my game and generate a proper certificate.

Here are some caveats to the guide which you need to be aware of before you proceed:

  • My OS was Kali Linux (Good for standardisation for penetration testers but won’t be applicable to every one of you legends who are reading this).
  • The server that I am using has it’s own DNS entry already configured. This is the biggest gotcha. You need to have a valid DNS record. Now is the time to buy a cheap domain! Or maybe investigate a domain allowing anyone to add an A record such as “.tk”.

If you can point a DNS entry at your Kali server then you are going to be able to do this.

In one terminal:

mkdir /tmp/safespace
cd /tmp/safespace
python -m SimpleHTTPServer 80

NOTE: I created a new directory in “/tmp” to make sure that there is nothing sensitive in the folder I am about to share. If you share your “/home” folder you are going to have a bad time. While the HTTP listener is running anyone scanning your IP address will be able to list the contents of the folders and download anything you have saved.

From another terminal you need to use “certbot”

apt-get install certbot
certbot certonly
....
pick option 2
set the domain to <your_domain>
set the directory to /tmp/safespace

The “certbot certonly” command runs a wizard like interface that asks you how to proceed. I have given you the options above. What this does is create a file in your /tmp/safespace folder that letsencrypt can download on their end. This proves that you have write permissions to the web root of the server and allows them to trust the request is legit.

The output of the “certbot certonly” command will list the location of your new TLS certificates. They will be here:

/etc/letsencrypt/live/<your_domain>/fullchain.pem
/etc/letsencrypt/live/<your_domain>/privkey.pem

You can go back to your first terminal and kill that HTTP listener. We will no longer be needing it! We have a proper TLS setup so lets go in a Rolls Royce baby, yeaaaah!

You can use python’s “twisted” HTTPs server as shown below

python -m twisted web --https=443 --path=. -c /etc/letsencrypt/live/<your_domain>/fullchain.pem -k /etc/letsencrypt/live/<your_domain>/privkey.pem

That was it. I was able to browse to my new HTTPS listener and I had a shiny trusted certificate.

Hope that helps

Verifying Insecure SSL/TLS protocols are enabled

If a vulnerability scanner tells you that a website supports an insecure SSL/TLS protocol it is still on you to verify that this is true. While it is becoming rarer, there are HTTPS services which allow a connection over an insecure protocol. However, if you issue an HTTP request it will respond to the user with a message like “Weak cryptography was in use!”.

I think this was an older IIS trait. But I am paranoid and in the habit of making damn sure that a service which offers say SSLv3 will actually handle HTTP requests over it. If there is a warning about poor cryptography then the chances are a user won’t be submitting passwords which will reduce the risk.

This blog post explains how to use openssl to connect using specific SSL/TLS protocols. It also provides a solution to a major gotcha of the process; the version of openssl that ships with your OS cannot issue insecure connections.

Using openssl to connect with an old protocol

The best way to do this, for me, is to use “openssl s_client” to connect to the service. The command supports the flags “-ssl2” “-ssl3” and “-tls1” to enable you to confirm those respectively. Say you want to verify SSL3 is enabled on a target you would do this:

openssl s_client -connect <host>:<port> -ssl3 -quiet

If the server supports the protocol it will now say this the line above where your cursor landed:

verify return:1

Your cursor will be paused there because you have established an SSL/TLS connection and now it is waiting for you to enter data.

Issuing an HTTP request through that connection

Having established your connection you will want to issue an HTTP request. A simple GET request should be sufficient:

GET / HTTP/1.1
Host: <host>

This simple request will return the homepage of any HTTP server. The subtle part is that there are invisible newline characters. In truth the above can be expressed in a single line as:

GET / HTTP/1.1\r\nHost: <host>\r\n\r\n

Here a pair of “\r\n” is representing the newlines. The exchange ends with “\r\n\r\n” because HTTP wants a blank line after all the headers are done to indicate when the server should start responding.

To be easier we can use “printf” to issue the GET request directly through our openssl connection:

printf "GET / HTTP/1.1\r\nHost: <host>\r\n\r\n" | openssl s_client -connect <host>:<port> -ssl3 -quiet

If the server responds without warning the user about insecure cryptography then you have just confirmed it as vulnerable.

Major Caveat

Most operating systems rightly ship with secured versions of “openssl”. This means that they have been compiled to not support these insecure protocols. The reason for doing this is to protect users from exploitation! This is good for us. If fewer clients can even talk SSLv3 then how much more unlikely is it that exploitation will occur?

To solve this problem I suggest you compile a version of openssl which has been compiled to support insecure versions:

wget https://openssl.org/source/openssl-1.0.2k.tar.gz
tar -xvf openssl-1.0.2k.tar.gz
cd openssl-1.0.2k
./config --prefix=`pwd`/local --openssldir=/usr/lib/ssl enable-ssl2 enable-ssl3 enable-tls1 no-shared
make depend
make
make -i install

Doing it this way creates a local binary (in “openssl-1.0.2k/local/bin”) for you which is not then installed over the system’s maintained one. This keeps your every day “openssl” command in your path secure while giving you the opportunity to confirm vulnerable services.

This solution is adapted from the Gist available here:

For ease I choose to then create an alias for the command as shown below:

alias "openssl-insecure"="/<path>/<to>/openssl-1.0.2k/local/bin/openssl"

I can now call the insecure version by using “openssl-<tab>” to complete with insecure.

Happy insecure protocol verifications to you all.