money and time that an opponent
will put into reading traffic."
(Robert Morris)
Continuando as 'brincadeiras' usando OpenSSL, estou colando nesse post outra ferramenta de checagem de um servidor SSL. No entanto, dessa vez estou usando um binário que criei em C para se conectar num servidor SSL e verificar se uma determinada cifra está disponível ou não no mesmo.
Então, se você quer, por exemplo, saber se um determinado servidor está 'vulnerável' ao ataque "Beast", você pode checar se ele possui suporte a TLS1/SSL3 com a cifra AES128-SHA, conforme pode-se ver abaixo:
_________________________________________________________________________________
./ssl-z0mbie XXXXXXXXXXXXXXXX 443 tls1 AES128-SHA
---xxx---xxx---
Connected with AES128-SHA encryption.
SSL version: TLSv1.
---xxx---xxx---
_________________________________________________________________________________
É possível automatizar o uso da ferramenta para listar as cifras disponibilizadas num servidor SSL utilizando o seguinte shell script:
_________________________________________________________________________________
#!/bin/bash
#List ciphers in SSL Server.
#
#Glaudson Ocampos - <glaudson@securitylabs.com.br>
#Marco/2014.
#
#Ubuntu
GREP="/bin/grep"
ECHO="/bin/echo"
OPENSSL="/usr/bin/openssl"
SED="/bin/sed"
SSL_Z0MBIE="./ssl-z0mbie"
MSG_OK="Connected"
function lista_cifras {
${ECHO} "*** Listing ciphers to $versao in $hostname:$porta."
for cifra in `${OPENSSL} ciphers | ${SED} -e 's/:/\n/g'`;
do
${SSL_Z0MBIE} $hostname $porta $versao $cifra | ${GREP} "Connected"
done
${ECHO} "*** Done."
}
EXPECTED_ARGS=2
E_BADARGS=-1
if [ $# -le $EXPECTED_ARGS ]; then
${ECHO} "**** SSL-Z0mbie - SSL Cipher Check v0.1"
${ECHO} "Uso: `basename $0` {versao} {hostname} {porta}"
${ECHO} ""
${ECHO} "versao - Versao SSL. Pode ser: ssl23, ssl3, tls1, tls1_1 ou tls1_2."
${ECHO} "hostname - Servidor SSL a ser checado. Exemplo: www.securitylabs.com.br"
${ECHO} "porta - Porta SSL."
${ECHO} ""
${ECHO} "Exemplo de Uso:"
${ECHO} " $0 tls1 www.securitylabs.com.br 443"
${ECHO} ""
exit $E_BADARGS
fi
versao="$1"
hostname="$2"
porta="$3"
lista_cifras;
_________________________________________________________________________________
Note que ele captura primeiro as cifras disponíveis no seu sistema(openssl ciphers), então, se quiser algo mais robusto é bom enumerar mais cifras. Executando o mesmo, temos:
_________________________________________________________________________________
$ ./brute.sh
**** SSL-Z0mbie - SSL Cipher Check v0.1
Uso: brute.sh {versao} {hostname} {porta}
versao - Versao SSL. Pode ser: ssl23, ssl3, tls1, tls1_1 ou tls1_2.
hostname - Servidor SSL a ser checado. Exemplo: www.securitylabs.com.br
porta - Porta SSL.
Exemplo de Uso:
./brute.sh tls1 www.securitylabs.com.br 443
$ ./brute.sh tls1 www.google.com 443
*** Listing ciphers to tls1 in www.google.com:443.
Connected with ECDHE-RSA-AES256-SHA encryption.
Connected with AES256-SHA encryption.
Connected with ECDHE-RSA-DES-CBC3-SHA encryption.
Connected with DES-CBC3-SHA encryption.
Connected with ECDHE-RSA-AES128-SHA encryption.
Connected with AES128-SHA encryption.
Connected with ECDHE-RSA-RC4-SHA encryption.
Connected with RC4-SHA encryption.
Connected with RC4-MD5 encryption.
*** Done.
_________________________________________________________________________________
Mas o ponto que desejamos repassar é a facilidade que temos em programar um SSL Socket utilizando a OpenSSL. Num futuro próximo, devo liberar um sniffer de SSL que tenho para SSL v2 que demonstra a diferença em se programar usando a OpenSSL em relação a criar código com estruturas do protocolo SSL na mão.
Abaixo segue o código fonte da ferramenta demonstrada acima:
_________________________________________________________________________________
/*
* SSL Z0mbie - analyze tool.
* SecurityLabs Intelligent Research.
* http://www.securitylabs.com.br/
*
* Author: Glaudson Ocampos - <glaudson@securitylabs.com.br>
*
* Compile with:
*
* $ gcc -o ssl-z0mbie ssl-z0mbie.c -lssl -lcrypto -Wall
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <resolv.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define ERROR -1
#define BANNER "SSL-Z0mbie - analyze tool."
#define VERSION "v0.1"
int
OpenConnection(const char *hostname, int port){
int mysock;
struct hostent *host;
struct sockaddr_in addr;
if((host = gethostbyname(hostname)) == NULL){
fprintf(stderr,"Host not found!\n");
fflush(stderr);
_exit(ERROR);
}
mysock = socket(AF_INET, SOCK_STREAM,0);
if(mysock < 0){
fprintf(stderr,"Erro em socket!\n");
fflush(stderr);
_exit(ERROR);
}
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long*)(host->h_addr);
if(connect(mysock, (const struct sockaddr *)&addr, sizeof(addr)) != 0){
fprintf(stderr,"Erro em connect()!\n");
fflush(stderr);
_exit(ERROR);
}
return mysock;
}
SSL_CTX
*InitCTX(char *versao){
SSL_CTX *ctx;
const SSL_METHOD *method;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
/* if(strncmp(versao,"ssl2",4) == 0){
method = SSLv2_client_method();
}
*/
if(strncmp(versao,"ssl3",4) == 0){
method = SSLv3_client_method();
}
if(strncmp(versao,"ssl23",5) == 0){
method = SSLv23_client_method();
}
if(strncmp(versao,"tls1",4) == 0){
method = TLSv1_client_method();
}
if(strncmp(versao,"tls1_1",6) == 0){
method = TLSv1_1_client_method();
}
if(strncmp(versao,"tls1_2",6) == 0){
method = TLSv1_2_client_method();
}
ctx = SSL_CTX_new(method);
if(ctx == NULL){
fprintf(stderr,"Erro em SSL_CTX_new()!\n");
fflush(stderr);
ERR_print_errors_fp(stderr);
_exit(ERROR);
}
return ctx;
}
int
ssl_connect(char *hostname, int portnum, char *versao, const char *cipher){
int server;
SSL_CTX *ctx;
SSL *ssl;
int bytes, ret;
char buf[1024];
ctx = InitCTX(versao);
SSL_CTX_set_cipher_list(ctx, cipher);
server = OpenConnection(hostname, portnum);
ssl = SSL_new(ctx);
SSL_set_fd(ssl, server);
ret = SSL_connect(ssl);
if( ret != 1){
if(ret < 0){
fprintf(stdout,"---###---###---\n");
fprintf(stdout,"%s encryption not supported.\n",cipher);
fprintf(stdout,"SSL version: %s.\n",SSL_get_version(ssl));
fprintf(stdout,"---###---###---\n");
//ERR_print_errors_fp(stderr);
}
if(ret == 2){
fprintf(stderr,"Erro: %d\n", SSL_get_error(ssl,ret));
fflush(stderr);
}
}
else {
char msg[256];
memset(msg,0x0,sizeof(msg));
snprintf(msg,sizeof(msg)-1,"GET / HTTP/1.1\nHost: %s\n\n",hostname);
fprintf(stdout,"---xxx---xxx---\n");
fprintf(stdout,"Connected with %s encryption.\n",SSL_get_cipher(ssl));
fprintf(stdout,"SSL version: %s.\n",SSL_get_version(ssl));
fprintf(stdout,"---xxx---xxx---\n");
fflush(stdout);
SSL_write(ssl,msg,strlen(msg));
bytes = SSL_read(ssl,buf, sizeof(buf)-1);
buf[bytes] = 0;
//printf("%s\n",buf);
SSL_free(ssl);
}
close(server);
SSL_CTX_free(ctx);
return 0;
}
int
checa_versao(char *versao){
int r=1;
if(strncmp(versao,"ssl23",5) == 0){
return 0;
}
if(strncmp(versao,"ssl3",4) == 0){
return 0;
}
if(strncmp(versao,"tls1",4) == 0){
return 0;
}
if(strncmp(versao,"tls1_1",6) == 0){
return 0;
}
if(strncmp(versao,"tls1_2",6) == 0){
return 0;
}
return r;
}
void
banner(char *progname){
fprintf(stdout,"%s - version %s\n", BANNER, VERSION);
fprintf(stdout,"Uso: %s <hostname> <portnum> <versao> <cifra>\n", progname);
fflush(stdout);
}
int
main(int argc, char *argv[]){
char *versao = NULL;
if(argc < 4){
banner(argv[0]);
_exit(0);
}
versao = argv[3];
if(checa_versao(versao) != 0){
fprintf(stdout,"Versao so pode ser:\n\n");
fprintf(stdout,"ssl23 - SSL versao 3 com downgrade para 2.\n");
fprintf(stdout,"ssl3 - SSL versao 3.\n");
fprintf(stdout,"tls1 - TLS versao 1.\n");
fprintf(stdout,"tls1_1 - TLS versao 1.1\n");
fprintf(stdout,"tls1_2 - TLS Versao 1.2.\n");
fflush(stdout);
_exit(ERROR);
}
ssl_connect(argv[1],atoi(argv[2]),argv[3],argv[4]);
return 0;
}
_________________________________________________________________________________
Então, espero com esse exemplo repassar como eu acho fantástica a OpenSSL.
Nenhum comentário:
Postar um comentário
Comentários são moderados visando evitar spams e permitir discussões sadias.