Remote stack overflow attack explained

by Sergey Lyubka, Cesanta

@CesantaHQ

Simple web server


    // Example of a simple Web server. Listening loop
    for (;;) {
      struct sockaddr_in remote_sa = {};
      socklen_t slen = sizeof(remote_sa);
      int new_sock = accept(sock, (struct sockaddr *) &remote_sa, &slen);
      printf("New connection from %s\n", inet_ntoa(remote_sa.sin_addr));
      if (new_sock != -1 && fork() == 0) {
        serve_new_connection(fdopen(new_sock, "rb+"));
        exit(0);
      }
      close(new_sock);
    }
  • Server spawns child processĀ for each incoming connection
  • Handling code parses HTTP request and replies

Handling code



    static void serve_new_connection(FILE *fp) {
      char method[10], uri[100], protocol[20];
      fscanf(fp, "%s %s %s", method, uri, protocol);
      fprintf(fp, "HTTP/1.0 200 OK\r\n\r\nURI: [%s]\n", uri);
    }
  • fscanf() function does not check for buffer boundaries
  • That makes it possible to pass a very large URI and have uri buffer overflow

Vulnerability check



  $ curl '127.0.0.1:8000/hi_there!'
  URI: [/hi_there!]

  $ curl 127.0.0.1:8000/$(base64 < /dev/urandom | dd bs=1 count=50 2>/dev/null)
  URI: [/PpplU0i6FlxHD763gKNqA1Wam4nyWfB38b6B+oMkq+6Qc2kfQw]

  $ curl 127.0.0.1:8000/$(base64 < /dev/urandom | dd bs=1 count=150 2>/dev/null)
  curl: (52) Empty reply from server
  • fscanf() function does not check for buffer boundaries
  • That makes it possible to pass a very large URI and have uri buffer overflow
  • Last curl example sends 150 character long URI

How function call works



  +-----------------+  <-- auld SP
  | param1          |
  +-----------------+
  | param2          |
  +-----------------+
  | return address  |
  +-----------------+  <-- FP
  | saved registers |
  +-----------------+
  | local variable1 |
  +-----------------+
  | local variable2 |
  +-----------------+
  | local variable3 |
  +-----------------+  <-- SP

Acquiring control



  +-----------------+  <-- auld SP
  | param1          |
  +-----------------+
  | param2          |
  +-----------------+
  | return address  |
  +-----------------+  <-- FP
  | saved registers |
  +-----------------+
  | local variable1 |
  +-----------------+
  | local variable2 |
  +-----------------+
  | local variable3 |
  +-----------------+  <-- SP
  • Why fscanf() and fprintf() succeed, and crash happens on function return?
  • How return from the function happens?
  • Overriding RVA

Remote command execution

  • Left as an exercise for the audience :-)

Thank You!

contact me at

sergey.lyubka@cesanta.com

Remote stack overflow attack explained

By Sergey Lyubka

Remote stack overflow attack explained

Explanation of the remove buffer overflow attack

  • 787