0% found this document useful (0 votes)
16 views

Secure+Coding+in+C C+++Cheat+Sheet

secure codinh

Uploaded by

2023ht01116
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views

Secure+Coding+in+C C+++Cheat+Sheet

secure codinh

Uploaded by

2023ht01116
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Secure Coding in C/C++ Cheat Sheet

SECURE CODING IN C/C++


Your Cheat Sheet
Be proactive
Waiting for something bad to
happen before taking action is
a costly and dangerous
approach. Instead, aim to be
proactive by understanding
the most common
vulnerabilities and their
countermeasures. Taking this
course is an excellent rst step
towards achieving this goal.

Review your code


Errors are inevitable, but
they're also avoidable with a
Greetings
keen second pair of eyes. and welcome to your essential resource for secure coding in C
Frequent code reviews by and C++. The frightening possibility of a system crash at 30,000
team members well-versed in feet serves as a wake-up call—when you're coding in powerful
secure coding can be a strong
languages like C and C++, security should never be an
line of defense against
afterthought; it's paramount.
vulnerabilities.
With this guide, you'll have a concise yet comprehensive resource
Sharpen the saw right at your ngertips.
The world of security is ever-
evolving, so your learning
should be too. Stay in the loop Thank you
with the latest security updates
for investing your time to learn about secure coding in C/C++. I’m
and trends to keep your
honored you chose my course to be part of your educational
coding skills relevant.
journey. Feel free to share this guide and the course link with
others interested in upping their coding game.

1
fi
fi
Secure Coding in C/C++ Cheat Sheet

Principles of Secure C and C++ Programming

Minimizing Attack Surface Area


Reducing the attack surface area is vital in enhancing the security of software. Attack
surface area means the points in your code where an attacker may exploit vulnerabilities.
By minimizing this area, we can lower the chances of successful attacks. In other words, the
smaller the target, the harder it is to hit.

Input validation and sanitization, secure memory management, code reviews and testing and secure coding
practices can help you reduce the attack surface area of your code.

Least Privilege
The Principle of Least Privilege is a key concept in secure programming. It suggests only
granting the minimum necessary privileges required to do a speci c task. By limiting access
rights and privileges, the potential harm that can be caused by an attacker or compromised
component is greatly reduced.

Examples include limiting code permissions, controlling system calls, and restricting access
rights to the necessary minimum.

Fail-safe Defaults
The Principle of Fail-Safe Defaults suggests that access to resources and sensitive
operations must be denied by default. Access should only be granted explicitly with
permission.
To understand why this strategy is effective, consider the opposite scenario where access is
granted by default but turned off if certain conditions are met. In such a case, there is a higher
likelihood of overlooking critical conditions or failing to revoke access promptly, which can lead to potential
security breaches.

Defense in Depth
To secure your C and C++ applications, relying on a single security mechanism isn't enough.
A comprehensive approach is to use multiple layers of defense, known as "Defense in
Depth." By designing your system this way, attackers will have to overcome several security
measures, making it harder to compromise the system.

2
fi
Secure Coding in C/C++ Cheat Sheet

Common Security Pitfalls in C and C++ Programming


1 Buffer Over ows ⚠
2 Risky Type Conversions

One of the most common Despite using a static type system,


security aws in C/C++ programs C and C++ permit risky
are buffer over ows. A buffer operations, such as implicit
over ow occurs when a program conversions and casting between
writes more data to a buffer than incompatible types.
it was designed to hold. Buffer
over ows can happen on the
stack, heap, or in a memory-mapped le.
🦄 Exploitability

🦄 Exploitability Misuse of these features can result in unde ned


behavior, potentially crashing the app or causing
Stack-based buffer over ows can be exploited to
other unwanted side effects.
overwrite the return address on the stack, enabling
an attacker to redirect the program ow to execute
💥 Implicit type conversion example
their own malicious code.
In the following case, an implicit conversion
Heap over ows occur in dynamically allocated happens from a double type to an integer type,
memory on the heap. Executing custom code is not leading to the loss of precision:
usually possible with a heap over ow, but an
double x = 3.14;
attacker could still exploit this vulnerability by int y = x;
overwriting the data used by the application.
✌ Solution
💥 Stack over ow example
Be explicit in your code and avoid implicit
// Triggering a stack-based buffer overflow
char buffer[5]; conversions to ensure type compatibility and
strcpy(buffer, "overflow"); prevent unintended consequences.

✌ Solution 1 In this speci c case, by using the static_cast


operator, our code explicitly states that we perform
Use the safer strncpy() function to avoid buffer
a narrowing conversion on purpose.
over ows. Don’t forget to add the null terminator
because strncpy() won’t add it in case of over ow. // Explicit conversion from double to int
double a = 3.14;
strncpy(buffer, "overflow", sizeof(buffer) - 1); int b = static_cast<int>(a);
// add terminating 0
buffer[sizeof(buffer) - 1] = 0;

✌ Solution 2
Alternatively, you can use snprintf() to avoid buffer
over ows. This function will also add the null
terminator automatically.

// adds the terminating zero


// even in case of overflows
snprintf(buffer, sizeof(buffer), "%s",

3
fl
fl
fl
fl
fl
fl
fi
fl
fl
fl
fl
fl
fl
fi
fi
fl
Secure Coding in C/C++ Cheat Sheet

Common Security Pitfalls in C and C++ Programming


3 Uncontrolled Format Strings ⚠
4 Improper Error Handling

When a program uses an Failing to handle errors properly can leave your code
unchecked format string as an vulnerable to security risks and impact program
argument to the printf() command reliability. Ignoring errors, failing to check the return
or similar functions, it can lead to values of functions that can fail, or exposing internal
the problem known as uncontrolled system details or valuable information in
format string, a common issue that error messages are common
can compromise security. mistakes in error management.

🦄 Exploitability 🦄 Exploitability
An attacker could use format strings as arguments Subpar error handling might
for printf() to reveal sensitive information stored in jeopardize the stability of your
memory or execute arbitrary code. application, and revealing con dential data could
offer hints to would-be attackers. Resource leaks
💥 Uncontrolled format string example could drain system capabilities and open the door to
The user_input string may include format speci ers possible denial-of-service risks.
like %s or %d, printf() will try to use additional
arguments that aren't there, resulting in unde ned 💥 Ignored error example
behavior. In the following code, the return value of fopen() is
not checked. If the le fails to open, the subsequent
And using the %x and %s format speci ers will call to fscanf() will read data from an uninitialized or
cause printf() to print out values from the stack, incorrect le stream, leading to unde ned behavior:
revealing sensitive information.
char buffer[MAX_BUFFER_SIZE];
FILE *file = fopen("data.txt", "r");
The %n speci er commands printf() to write the
number of characters successfully written so far to fscanf(file, "%s", buffer);
cout << "First word: " << buffer << endl;
an address pointed to by the corresponding
argument. As there's no corresponding argument, fclose(file);
printf() will write to whatever location is at the top of
the stack, leading to a potential security ✌ Solution
vulnerability. The improved code handles the failed le opening
// user_input may contain format specifiers scenario and logs the error:
printf(user_input);
char buffer[256];
FILE *file = fopen("data.txt", "r");
✌ Solution
if (!file)
Using printf("%s", user_input) prevents any format {
printf("Failed to open the file.\n");
speci ers in user_input from being interpreted by return;
printf(). }

fscanf(file, "%s", buffer);


// format specifiers cout << "First word: " << buffer << endl;
printf("%s", user_input);
fclose(file);

4
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
Secure Coding in C/C++ Cheat Sheet

Common Security Pitfalls in C and C++ Programming


5 Race Conditions ✌ Solution
A race condition occurs when two Introduce a mutex and use std::lock_guard to lock
or more threads compete to and unlock the mutex during the critical section. This
access or modify shared data way we ensure that only one thread can access and
simultaneously. This can cause modify the counter variable at a time, preventing
sporadic bugs and severe security data corruption caused by a race condition.
vulnerabilities. Paying close
#include <iostream>
attention to concurrency and #include <thread>
handling it with care is crucial to avoid such risks. #include <mutex>
using namespace std;

🦄 Exploitability int counter = 0;


mutex counterMutex;
Race conditions can cause data corruption,
void increment_counter()
potentially leading to incorrect program behavior {
and security vulnerabilities such as unauthorized lock_guard<mutex> lock(counterMutex);
++counter;
access to protected resources. }

int main()
💥 Race condition example {
thread t1(increment_counter);
In this example, both threads access and modify the thread t2(increment_counter);
counter variable simultaneously without proper t1.join();
synchronization. As a result, the integrity of the t2.join();
counter variable is compromised, potentially cout << "Counter value: " << counter << endl;
leading to incorrect program behavior and other
return 0;
issues. }

#include <iostream>
#include <thread>
using namespace std;

int counter = 0;

void increment_counter()
{
++counter;
}

int main()
{
thread t1(increment_counter);
thread t2(increment_counter);

t1.join();
t2.join();

cout << "Counter value: " << counter << endl;

return 0;
}

5
Secure Coding in C/C++ Cheat Sheet

Common Security Pitfalls in C and C++ Programming


6 C/C++ Memory Management Mistakes 💥 Referencing freed memory
Unlike other languages, C and In this code snippet, we rst allocate memory to store
C++ do not have automatic an integer and save the address of this memory block
garbage collection. Instead, in the variable value. Later, we free the allocated
developers must manage memory using the free() function.
memory manually—a powerful
Later, we attempt to write the value 5 to the same
but also risky feature. Thus, it’s
memory location that has already been freed. This
the responsibility of the
can cause unpredictable behavior and data
programmer to. Failure to do so can result in
corruption, as the memory block may now be used
vulnerabilities such as memory leaks, buffer
for other purposes by the system.
over ows, and dangling pointers.
int *value = malloc(sizeof(int)); // use new int()
🦄 Exploitability in C++

The side-effects of sloppy memory management free(value); // use operator delete in C++
// ... Perform some operations
can cause a wide range of problems with various // forget that value was freed and try to use it
degrees of severity, including: *value = 5;

• reduced system performance ✌ Solution


• denial-of-service attacks due to resource Implementing defensive coding practices, such as
exhaustion setting pointers to NULL can help reduce the risk of
• data corruption accessing freed memory.
• security vulnerabilities
Accessing a NULL pointer will instantly trigger a
💥 Null pointer dereference runtime error, which is far easier to debug and x
than unpredictable behavior resulting from
A null pointer is a pointer that does not point to any
dereferencing a dangling pointer. This approach
valid memory address. Dereferencing such a
turns a subtle bug into a blatant one, making it less
pointer can lead to unde ned behavior and
likely to go unnoticed and thereby improving your
crashes.
application's overall security posture.
int *ptr = NULL; // use nullptr in C++
// ... Perform some operations int *value = malloc(sizeof(int));
*ptr = 10; // this will cause a runtime error free(value); // use operator delete in C++
// Set value to NULL to make sure we don't use it
by mistake
value = NULL; // use nullptr in C++
✌ Solution // ... Perform some operations
*value = 5; // this will cause a runtime error
The simplest way to avoid dereferencing null
pointers is to check whether the pointer is null
before accessing its memory: Accessing a NULL pointer will instantly trigger a
runtime error, which is far easier to debug and x
int *ptr = NULL; // use nullptr in C++
// ... Perform some operations than unpredictable behavior resulting from
if(value != NULL) // use nullptr in C++ dereferencing a dangling pointer.
{
*value = 5;
}

6
fl
fi
fi
fi
fi
Secure Coding in C/C++ Cheat Sheet

Wrapping Up

Consider these examples as just a snapshot of what you've already encountered in the course on Secure
Coding in C/C++.

If you found these insights valuable and want to revisit any topics or perhaps share them with your
network, the course is always there for you to go through again.

Feel free to share this guide and the course link with others interested in upping their coding game.

Thanks again for being a part of this learning journey with me. Take care and happy coding! 😊

Best regards,
Karoly Nyisztor

You might also like