top of page

How cybersecurity breaches could infect the C programming language.

Vulnerable Code:


c

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

void vulnerable_function(char *user_input) {
    char buffer[50];  // Fixed-size buffer
    strcpy(buffer, user_input); // No bounds checking
    printf("You entered: %s\n", buffer);
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s <input>\n", argv[0]);
        return 1;
    }
    vulnerable_function(argv[1]);
    return 0;
}

How an Attacker Can Exploit This:

The function strcpy() does not check the length of user_input before copying it into buffer, allowing an attacker to input a string longer than 50 characters, causing a buffer overflow.

If an attacker crafts an input containing shellcode (malicious machine code) along with carefully placed return addresses, they can overwrite the return address of vulnerable_function() and execute arbitrary code.

Example of an Exploit Input:

 

     ./vulnerable_program $(python -c 'print("A"*60 + "\xef\xbe\xad\xde")')

 


Here, "A"*60 overflows the buffer, and "\xef\xbe\xad\xde" represents a malicious return address in little-endian format, potentially pointing to an attacker-controlled payload.

Mitigation Strategies

 

​

  1. Use safer string functions like strncpy() or fgets() instead of strcpy().

  2. Enable stack protection (-fstack-protector in GCC).

  3. Use Address Space Layout Randomization (ASLR) to make it harder for attackers to predict memory locations.

  4. Implement Bounds Checking before copying input.

Here is an example of secure code that prevents buffer overflow attacks

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

​

void secure_function(char *user_input) {
    char buffer[50];  // Fixed-size buffer

​

    // Use strncpy to limit input size and ensure null-termination
    strncpy(buffer, user_input, sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination

​

    printf("You entered: %s\n", buffer);
}

​

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s <input>\n", argv[0]);
        return 1;
    }
    secure_function(argv[1]);
    return 0;
}

How cybersecurity breaches could infect the C++ programming language.

​1. Buffer Overflows - Using strcpy() to copy user input into a fixed-size C-style array without bounds checking. Attackers can overwrite adjacent memory, causing crashes or arbitrary code execution.

2. Use of new and Manual Memory Management - Forgetting to delete memory allocated with new causes a memory leak. An attacker may exploit this to exhaust memory resources (denial of service).

3.Use-After-Free:

​

 

 

 

 

​​​​

4.Integer Overflows - A program validates file size with an expression like if (offset + length < buffer_size). If offset is large enough, the addition overflows, bypassing the check.​​​​​​​

5.Race Conditions - A program modifies a shared resource without proper locking mechanisms, causing a race condition that attackers can exploit to modify sensitive data.

6.Improper Exception Handling - An exception thrown in a destructor during stack unwinding could terminate the program, causing denial of service.

7.Vulnerable Use of STL - Using std::string to concatenate untrusted user input for SQL queries can result in SQL injection.

8.Insecure Polymorphism - An attacker overwrites a virtual table pointer (vtable) to redirect execution to malicious code.

9.Command Injection:

​

​

​

​

​

​

​10.Deserialization Vulnerabilities - An attacker crafts a serialized object that, when deserialized, causes the program to execute malicious code.

11. Insecure Cryptography - Using an insecure random number generator (like rand()) for cryptographic purposes makes encryption predictable.

12. Weak Smart Pointer Management - Circular references between std::shared_ptr instances can lead to memory leaks                                                                                 

13. Insecure File Handling

​

​

​

​

 

​​​14. Dependency Vulnerabilities - A linked library has a known buffer overflow vulnerability, allowing attackers to execute arbitrary code.

15. Out-of-Bounds Access:

​

​

​

​

​

​16. Default Object Copying -  A class managing sensitive resources does not implement a custom copy constructor, leading to resource duplication or leaks.

17. Overloaded Operators - Overloaded + operator inadvertently allows integer overflow in arithmetic operations.

18. Privilege Escalation:

​

​​

​

​

​

19. Misconfigured Threads:

​​

​

​

​

​​​

20. Lack of Boundary Checking

​

​

​​​

int* ptr = new int(5);
delete ptr;
std::cout << *ptr; // Use-after-free vulnerability.

std::string command = "ls " + user_input;
system(command.c_str()); // User-controlled input leads to command injection.

std::ofstream ofs("/tmp/" + user_input); // Allows directory traversal attacks.

std::vector<int> v(10);
int value = v[20]; // Out-of-bounds access, leading to undefined behavior.

std::thread t([] { /* Critical section */ });
t.
detach(); // No synchronization or error handling.

system("/bin/cp secret_file /tmp/"); // Command execution without validation.

int arr[10];
arr[
11] = 42; // Buffer overflow due to lack of bounds checking.

Strategies to mitigate C++:

  • Implement strict input validation.

  • Use encrypted communication protocols.

  • Regularly update and patch libraries and systems.

  • Employ strong authentication and access control mechanisms.

  • Perform regular security audits and testing.

How cybersecurity breaches could infect the C# programming language.

 

Example 1:  The case of Insecure Deserialization​

​

 

 

 

 

​​

​

​

​

​

​

​

​

​

​

​

​​

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace VulnerableApp
{
    [Serializable]
    public class UserData
    {
        public string Username { get; set; }
        public string Password { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter serialized user data:");
            string serializedData = Console.ReadLine();

            byte[] data = Convert.FromBase64String(serializedData);
            UserData user = Deserialize(data);

            Console.WriteLine($"Welcome {user.Username}!");
        }

        static UserData Deserialize(byte[] data)
        {
            using (var memoryStream = new MemoryStream(data))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                return (UserData)formatter.Deserialize(memoryStream);
            }
        }
    }
}
 

[Serializable]
public class MaliciousPayload
{
   
public MaliciousPayload()
    {
        // Execute arbitrary code, e.g., delete files
        System.IO.File.Delete(
"C:\\important_file.txt");
    }
}

How The code above can Be exploited:​

An attacker can craft malicious serialized data that executes arbitrary code when deserialized.

  • Create a malicious class that performs an unauthorized action (e.g., deletes files or executes shell commands).

  • Serialize an instance of the malicious class into a Base64 string.

  • Supply this string to the application as input.​

When the application deserializes the data, the malicious payload is executed.

​

​For Example, with this code structure below, let's assume an attacker sends a Serialized payload as Base64:​

AAEAAAD/////AQAAAAAAAAAMAgAAAFxNYWxpY2lvdXNQYXlsb2FkAAAAAAAAAAAAAAAAAAMBAAAACk1hbGlj
aW91c1BheWxvYWQCAAAACk1hbGljaW91cw==

Here is the attacker's payload.  When deserialized, the application executes the constructor of the MaliciousPayload class, performing the attacker's action:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace SecureApp
{
    [Serializable]
    public class UserData
    {
        public string Username { get; set; }
        public string Password { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter serialized user data:");
            string serializedData = Console.ReadLine();

            byte[] data = Convert.FromBase64String(serializedData);

            try
            {
                UserData user = SafeDeserialize(data);
                Console.WriteLine($"Welcome {user.Username}!");
            }
            catch
            {
                Console.WriteLine("Invalid or unsafe data provided.");
            }
        }

        static UserData SafeDeserialize(byte[] data)
        {
            // Use secure serializers or perform strict validation
            throw new NotImplementedException("Secure deserialization logic should go here.");
        }
    }
}
 

This attack can be fixed by implementing secure deserialization:

This fixes insecure deserialization by:

  • Using a safe deserialization method (e.g., JSON or XML with strict schema validation).

  • Validating and sanitizing data before deserialization.

  • Use whitelisting to allow only specific types during deserialization.

bottom of page