SBN

The Top C++ Security Vulnerabilities and How to Mitigate Them

C++ Security Vulnerabilities: Types, Meaning, & Examples | GuardRails

C++ is one of the most famous and used programming languages. This high-level and object-oriented programming language has helped developers execute wide-ranging tech projects. 

Security vulnerabilities and threats have become prevalent and pose severe challenges to the tech world. This leads to a disruption in work processes and projects and the futility of developers’ efforts. To prevent this, this article will focus on tackling C++ security vulnerabilities with different mitigation techniques. Common examples of C++ security vulnerabilities and how they occur will also be discussed.

5 Common C++ Security Vulnerabilities

C++ security vulnerabilities include format string vulnerabilities, OS command injection, integer over and underflows, null pointer dereferences, and use-after-free. However, we shall examine the five common ones in this blog post and how to tackle them. You can also learn how to fix common Python security vulnerabilities here

  1. Buffer Overflows

The MITRE Corporation reports that buffer overflows make up 10,000+ different software vulnerabilities. Also, 23% of these vulnerabilities are severe. A buffer overflow occurs when a program writes more data than it is built to hold. In other words, developers will experience buffer overflow if there is no mechanism to accept only a certain length of code, causing overwriting.

Such a mechanism could be a block that accepts a fixed length of code or a specified computer memory. When a developer allows code to overwrite, it flows into the next buffer, causing data to corrupt or programs to crash. 

Here is an example of a code written with C++ without checking for limits:

“`

int main() {

 char *src = EXAMPLE_STR;

 char dest[BUF_SIZE];

 bcopy(src, dest, BUF_SIZE);

 memcpy(dest, src, BUF_SIZE);

}

“`

To prevent buffer overflow, ensure to check bounds before coding. Also, use library functions resistant to buffer overflow like “fgets.” Refrain from using “scanf,” “strcpy,” “printf,” “get,” and “strcaf,” as they are prone to buffer overflows.  

Use stack canaries, ASLR (Address Space Layout Randomization), and DEP (Data Execution Prevention). They help to manage memory spaces for accommodating data and guard against attacks. 

2. Memory Management Errors

Memory management errors that cause C++ security vulnerabilities are:

  • Memory Leaks – Occur when a user allocates memory but does not release it. When a memory leak occurs often, it could cause an application to run out of available memory. This further leads to crashes or termination. Preventing memory leaks requires freeing memory allocated on the heap when you no longer need it.
  • Invalid Memory Access – Occurs when a read/write command references unallocated or deallocated memory. To avoid this, always have object ownership. This will prevent a thread from releasing an object to the heap while another finds the pointer valid. 
  • Uninitialized Memory Access in Heap and Stack – Occurs when your application contains an uninitialized variable. Mitigating this requires you to ensure initializing variables before you use them. 
  • Mismatched Allocation/Deallocation – Occurs when a user attempts to deallocate with a function that does not correspond to their allocation function. To prevent this, always call the right deallocator.
  • Cross-stack Access – Occurs when a thread accesses the stack memory of another thread. Avoid this by ensuring you do not save stack addresses to global variables. 

Memory management errors fall under two major categories: heap memory error and stack memory error.

The example code in Figure 2 below is provided in C++, a language known for having memory security problems:

// Losing access to allocated memory. This is demonstrated in the following code:

int main() {

        int *memory;

        // Allocate 200 ints.

        memory = malloc(200 * sizeof(int));

        // Allocate 100 more ints.

        // ERROR: This will compile, but will leave the previously

        // allocated memory hanging, with no way to access it.

        memory = malloc(100 * sizeof(int));

        // Free second block of 100 ints.

        // The first block is not freed.

        free(memory);

        return 0;

    }

Figure 2: Example Code With Memory Security Problems

The solution, using pointer, as shown in Figure 3:

void use_pointer(int *array) {

        … // Perform calculations on array

        // Now, we think we own the array, so we’ll free it

        free(array);

    }

    int main() {

        int *memory;

        // Allocate 200 ints.

        memory = calloc(200, sizeof(int));

        // Perform calculations on array

        use_pointer(memory);

        // Free the array

        // ERROR: This will compile, but will free already

        // freed memory. The pointed-to memory has already been

        // freed in use_pointer().

        free(memory);

        return 0;

    }

void use_pointer(int *array) {

        … // Perform calculations on array

        // Now, we think we own the array, so we’ll free it

        free(array);

    }

    int main() {

        int *memory;

        // Allocate 200 ints.

        memory = calloc(200, sizeof(int));

        // Perform calculations on array

        use_pointer(memory);

        // Free the array

        // ERROR: This will compile, but will free already

        // freed memory. The pointed-to memory has already been

        // freed in use_pointer().

        free(memory);

        return 0;

    }

Figure 3: Example of a Solution Using Pointer

3. Unvalidated Input

While using C++, inputs often undergo tests. These tests are usually a set of commands which will either allow or deny inputs made on an application. This procedure helps to prevent vulnerabilities, threats, and attacks. 

When an application or system is not set up to allow or prevent inputs based on specific parameters, invalid inputs are extremely likely to occur. Unvalidated input can pose numerous threats and attacks on a system, especially if it receives input from external parties. Common input validation attacks are SQL injection and cross-site Scripting (XSS). 

In the example below, the user is prompted for the height and breadth of a gaming board that can have up to 100 squares in length:

#include <stdio.h>

#if !defined (MESSAGE)

#define MESSAGE “You wish!”

#define MAX_DIM 100

#endif

int main(void){

int m,n, error;

board_square_t *board;

printf(“Please specify the board height: \n”);

error = scanf(“%d”, &m);

if ( EOF == error ){

die(“No integer passed: Die evil hacker!\n”);

}

printf(“Please specify the board width: \n”);

error = scanf(“%d”, &n);

if ( EOF == error ){

die(“No integer passed: Die evil hacker!\n”);

if ( m > MAX_DIM || n > MAX_DIM ) {

die(“Value too large: Die evil hacker!\n”);

}

board = (board_square_t*) malloc( m * n * sizeof(board_square_t));

return 0;

}

The developer checked for null value and handled it, but forgot to check for negative input. If a negative value is passed, it will automatically increase the balance.

To mitigate unvalidated input risks, set parameters for every input such as integers and URLs.

4. Integer Overflows

Integer overflow is a C++ security vulnerability in which a user can input a longer value than an integer can hold. In C++, integers can only accommodate values based on the allocated number of bits. When the integer receives more data than it is built to take, there will be an overflow. 

Below is an example of an integer overflow:

int addsi ( int lhs , int rhs ) {

2 errno = 0;

3 if (((( lhs+rhs )^ lhs ) &(( lhs+rhs )^ rhs ))

4 >> ( sizeof ( int ) * CHAR_BIT -1) ) {

5 error_handler ( ” OVERFLOW ERROR ” , NULL , EOVERFLOW );

6 errno = EINVAL ;

7 }

8 return lhs + rhs ;

9 }

To prevent integer overflow, conduct overflow checks regularly. Likewise, run a value sanity test to detect where overflow issues could arise. 

5. Injection Attacks

Injection attacks are insecure activities that involve feeding an application with malicious inputs or commands. This attack often occurs when a bad actor injects malware into a program to modify it. Types of injection attacks are SSI injection, format string attack, SQL injection, XPath injection, OS Commanding, and LDAP (Lightweight directory access protocol) injection. 

Below is an example of an injection attack:

// C program to demonstrate Command Injection attack

// The purpose of the program to print contents of a

// file provided as command line argument.

#include <stdio.h>

#include <unistd.h>

int main(int argc, char **argv)

{

    char cat[] = “cat “;

    char *command;

    size_t commandLength;

    commandLength = strlen(cat) + strlen(argv[1]) + 1;

    command = (char *) malloc(commandLength);

    strncpy(command, cat, commandLength);

    strncat(command, argv[1], (commandLength – strlen(cat)) );

    system(command);

    return (0);

}

Used normally 

$ ./a.out exploit.txt

my name is akash

Used as injection attack

if we add a semicolon and another command to the end of this line, the command is executed by catWrapper with no complaint:

$ ./a.out “exploit.txt; ls”

my name is akash

exploit.txt               doubFree.c              nullpointer.c

unstosig.c              www*                    a.out*

format.c                strlen.c                useFree*

catWrapper*             misnull.c               strlength.c             useFree.c

commandinjection.c      nodefault.c             trunc.c                 writeWhatWhere.c

Prevention techniques for this C++ security attack include using a firewall and conducting regular security testing and scanning. You can check our guide on protecting your team from XSS attacks.

Mitigating C++ Security Vulnerabilities 

C++ security vulnerabilities contribute to the numerous security issues we encounter as individuals and organizations. The silver lining to this is that we can mitigate these vulnerabilities. GuardRails is on standby to help mitigate all C++ security vulnerabilities. We offer contextual Just-in-Time training to guide developers when they need it, and we integrate security scanning seamlessly within your workflow. This prevents you from falling victim to C++ security vulnerabilities and other threats with the accompanying consequences. Reach out to us today to stay ahead of bad actors who launch security threats. 

DevSecOps Pipeline

The post The Top C++ Security Vulnerabilities and How to Mitigate Them appeared first on GuardRails.

*** This is a Security Bloggers Network syndicated blog from GuardRails authored by GuardRails. Read the original post at: https://blog.guardrails.io/the-top-c-security-vulnerabilities-and-how-to-mitigate-them/