Buffer overflows

In computer security, a shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is called "shellcode" because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode. Because the function of a payload is not limited to merely spawning a shell, some have suggested that the name shellcode is insufficient.[1] However, attempts at replacing the term have not gained wide acceptance.

Buffer overflows can be triggered by inputs that are designed to execute code, or alter the way the program operates. This may result in erratic program behavior, including memory access errors, incorrect results, a crash, or a breach of system security. Thus, they are the basis of many software vulnerabilities and can be maliciously exploited.

Buffer overflow, or buffer overrun, is an anomaly where a program, while writing data to a buffer, overruns the buffer's boundary and overwrites memory in adjacent locations. This is a special case of the violation of memory safety.

The techniques to exploit a buffer overflow vulnerability vary by architecture, by operating system and by memory region. For example, exploitation on the heap (used for dynamically allocated memory), differs markedly from exploitation on the call stack.

Stack-based exploitation - Stack buffer overflow

A technically inclined user may exploit stack-based buffer overflows to manipulate the program to their advantage in one of several ways:

by overwriting a local variable that is near the buffer in memory on the stack to change the behavior of the program - which may benefit the attacker. by overwriting the return address in a stack frame. Once the function returns, execution will resume at the return address as specified by the attacker, usually a user-input filled buffer. by overwriting a function pointer[1] or exception handler, which is subsequently executed by overwriting a parameter of a different stack frame or a non-local address pointed to in the current stack context[2]

Programming languages commonly associated with buffer overflows include C and C++, which provide no built-in protection against accessing or overwriting data in any part of memory and do not automatically check that data written to an array (the built-in buffer type) is within the boundaries of that array.

Bounds checking can prevent buffer overflows.

[SOURCE CODE]

================ VULNERABLE CODE ================

/* overflow.c - demuestra un desbordamiento de buffer */

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
  char buffer[10];
  if (argc < 2)
  {
    fprintf(stderr, "MODO DE USO: %s string\n", argv[0]);
    return 1;
  }
  strcpy(buffer, argv[1]);
  return 0;
}
============= SECURE CODE =============
/* mejor.c - demuestra un método de resolver el problema */

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
  char buffer[10];
  if (argc < 2)
  {
    fprintf(stderr, "MODO DE USO: %s string\n", argv[0]);
    return 1;
  }
  strncpy(buffer, argv[1], sizeof(buffer));
  buffer[sizeof(buffer) - 1] = '\0';
  return 0;
}
================ VULNERABLE CODE ================
#include <stdio.h>
#include <string.h>
int main( int argc, char *argv[] )
{
  // Buffer estático en la pila.
  char buffer[1024];
  if ( argc != 2 )
  {
    printf("Uso: %s argumento\n", argv[0] );
    return( -1 );
  }
  // Copiado de cadenas sin control.
  strcpy( buffer, argv[1]);
  printf( "Argumento copiado\n" );
  return(0);
}

Bugs : - A bug is a defect in the implementation - A flaw is a defect in the design

The stdio gets() function does not check for buffer length and always results in a vulnerability.

integer overflow occurs when an arithmetic operation attempts to create a numeric value that is too large to be represented within the available storage space

msfpayload windows/

shell_bind_tcp R | msfencode -a x86 -b "\x00\x0d" -t -cpsexecReturn-to-libc attack

A return-to-libc attack is a computer security attack usually starting with a buffer overflow in which a subroutine return address on a call stack is replaced by an address of a subroutine that is already present in the process’ executable memory, bypassing the NX bit feature (if present) and ridding the attacker of the need to inject their own code.ROP (Return Oriented Proragmming ) Attack

This type of attack was introduced by Hovav Shacham of Stanford University in his paper “The Geometry of Innocent Flesh on the Bone:Return-into-libc without Function Calls (on the x86).”

That means this type of attack is able to perform arbitrary computation without the necessary use of library functions by reusing code chunks which he calls GADGETS.

ROP Attacks (Loading and Storing Data)

There are certain gadgets that allows us to store and load data from one place to another. Modes of transfer include:

Shellcode is commonly written in machine code.

; hello world in 64-bit assembly for Linux
        global  _start
        section .text
_start:
        ; write is system call 1
        mov     rax, 1                  ; system call 1 is write
        mov     rdi, 1                  ; file handle 1 is stdout
        mov     rsi, message            ; address of string to output
        mov     rdx, len                 ; number of bytes
        syscall                         ; invoke syscall

        ; exit(0)
        mov     eax, 60                 ; system call 60 is exit
        xor     rdi, rdi                ; exit code 0
        syscall                         ; invoke operating system to exit
message:
        db      "Hello, Reverser!", 10  ; 10 is a newline      
len:    equ     $ - message
; hello world in 32-bit assembly for Linux
        global  _start
        section .text
_start:
        ; write is system call 4
        mov     eax, 4                  ; system call 4 is write
        mov     ebx, 1                  ; file handle 1 is stdout
        mov     ecx, message            ; address of string to output
        mov     edx, len                ; number of bytes
        int 0x80                    ; invoke syscall

        ; exit(0)
        mov     eax, 1                 ; system call 1 is exit
        xor     ebx, ebx                ; exit code 0
        int 0x80                         ; invoke operating system to exit
message:
        db      "Hello, Reverser!", 10  ; 10 is a newline      
len:    equ     $ - message

Introductory Intel x86: Architecture, Assembly, Applications, & Alliteration

* [IntroX86](   - http://opensecuritytraining.info/IntroX86.html)
* [Exploit tutorial: Buffer Overflow](https://www.reddit.com/r/hacking/comments/1wy610/exploit_tutorial_buffer_overflow/)
* [Exploit writing tutorial part 1 : Stack Based Overflows](https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/)
* [Introduction To Software Exploits](http://opensecuritytraining.info/Exploits1.html)
* [Protostar Exploits Exercises](https://exploit-exercises.com/protostar/)
* [security.web](https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml) 
* [pubs.opengroup.org](http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html)

[Wargames]

[Vulnerable Server]

Common vulnerabilities guide for C programmers

Most vulnerabilities in C are related to buffer overflows external link and string manipulation. In most cases, this would result in a segmentation fault, but specially crafted malicious input values, adapted to the architecture and environment could yield to arbitrary code execution.


Function gets

The stdio gets() function does not check for buffer length and always results in a vulnerability.


Vulnerable code

#include <stdio.h>
int main () {
    char username[8];
    int allow = 0;
    printf external link("Enter your username, please: ");
    gets(username); // user inputs "malicious"
    if (grantAccess(username)) {
        allow = 1;
    }
    if (allow != 0) { // has been overwritten by the overflow of the username.
        privilegedAction();
    }
    return 0;
}

Mitigation

#include <stdio.h>
#include <stdlib.h>
#define LENGTH 8
int main () {
    char* username, *nlptr;
    int allow = 0;

    username = malloc(LENGTH * sizeof(*username));
    if (!username)
        return EXIT_FAILURE;
    printf external link("Enter your username, please: ");
    fgets(username,LENGTH, stdin);
    // fgets stops after LENGTH-1 characters or at a newline character, which ever comes first.
    // but it considers \n a valid character, so you might want to remove it:
    nlptr = strchr(username, '\n');
    if (nlptr) *nlptr = '\0';

    if (grantAccess(username)) {
        allow = 1;
    }
    if (allow != 0) {
        priviledgedAction();
    }

    free(username);

    return 0;
}

Function strcpy

strcpy
The strcpy built-in function does not check buffer lengths and may very well overwrite memory zone contiguous to the intended destination. In fact, the whole family of functions is similarly vulnerable: strcpy, strcat and strcmp.


Vulnerable code

char str1[10];
char str2[]="abcdefghijklmn";
strcpy(str1,str2);

Mitigation

The best way to mitigate this issue is to use strlcpy if it is readily available (which is only the case on BSD systems). However, it is very simple to define it yourself, as shown below:

#include <stdio.h>

#ifndef strlcpy
#define strlcpy(dst,src,sz) snprintf((dst), (sz), "%s", (src))
#endif

enum { BUFFER_SIZE = 10 };

int main() {
    char dst[BUFFER_SIZE];
    char src[] = "abcdefghijk";

    int buffer_length = strlcpy(dst, src, BUFFER_SIZE);

    if (buffer_length >= BUFFER_SIZE) {
        printf external link("String too long: %d (%d expected)\n",
                buffer_length, BUFFER_SIZE-1);
    }

    printf external link("String copied: %s\n", dst);

    return 0;
}
Another and may be slightly less convenient way is to use strncpy, which prevents buffer overflows, but does not guarantee

`\0'-termination`.

enum { BUFFER_SIZE = 10 };
char str1[BUFFER_SIZE];
char str2[]="abcdefghijklmn";

strncpy(str1,str2, BUFFER_SIZE); /* limit number of characters to be copied */
// We need to set the limit to BUFFER_SIZE, so that all characters in the buffer
// are set to '\0'. If the source buffer is longer than BUFFER_SIZE, all the '\0'
// characters will be overwritten and the copy will be truncated.

if (str1[BUFFER_SIZE-1] != '\0') {
    /* buffer was truncated, handle error? */
}
For the other functions in the family, the n variants exist as well: strncpm and strncat


Function sprintf

sprintf

Just as the previous functions, sprintf does not check the buffer boundaries and is vulnerable to overflows.

Integer Overflow


What is an integer?

An integer, in the context of computing, is a variable capable of representing a real number with no fractional part. Integers are typically the same size as a pointer on the system they are compiled Consequences.

Integers, like all variables are just regions of memory.

As well as binary and decimal, hexadecimal (base sixteen) is often used in computing as it is very easy to convert between binary and hexadecimal.

An integer overflow condition exists when an integer, which has not been properly sanity checked, is used in the determination of an offset or size for memory allocation, copying, concatenation, or similarly. If the integer in question is incremented past the maximum possible value, it may wrap to become a very small, or negative number, therefore providing a very incorrect value.

Availability: Integer overflows generally lead to undefined behavior and therefore crashes. In the case of overflows involving loop index variables, the likelihood of infinite loops is also high.

Integrity: If the value in question is important to data (as opposed to flow), simple data corruption has occurred. Also, if the integer overflow has resulted in a buffer overflow condition, data corruption will most likely take place.

Access control (instruction processing): Integer overflows can sometimes trigger buffer overflows which can be used to execute arbitrary code. This is usually outside the scope of a program's implicit security policy.

msfpayload windows/shell_bind_tcp R | msfencode -a x86 -b "\x00\x0d" -t -cReturn-to-libc attack

Example 1:

    /* width1.c - exploiting a trivial widthness bug */
    #include <stdio.h>
    #include <string.h>

    int main(int argc, char *argv[]){
            unsigned short s;
            int i;
            char buf[80];

            if(argc < 3){
                    return -1;
            }

            i = atoi(argv[1]);
            s = i;

            if(s >= 80){            /* [w1] */
                    printf("Oh no you don't!\n");
                    return -1;
            }

            printf("s = %d\n", s);

            memcpy(buf, argv[2], i);
            buf[i] = '\0';
            printf("%s\n", buf);

            return 0;
    }

Sources