Secure coding
- 7 min read
- 4 chapters
Related on Lably
Through Software, Computer security and Parsing
Some scholars have suggested that in order to effectively confront threats related to cybersecurity, proper security should be coded or “baked in” to the systems. With security being designed into the software, this ensures that there will be protection against insider attacks and reduces the threat to application security.
Buffer-overflow prevention
Buffer overflows, a common software security vulnerability, happen when a process tries to store data beyond a fixed-length buffer. For example, if there are 8 slots to store items in, there will be a problem if there is an attempt to store 9 items. In computer memory the overflowed data may overwrite data in the next location which can result in a security vulnerability (stack smashing) or program termination (segmentation fault).
An example of a C program prone to a buffer overflow is
<span id="mwHQ"></span><span class="kt" id="mwHg">int</span><span class="w" id="mwHw"> </span><span class="nf" id="mwIA">vulnerable_function</span><span class="p" id="mwIQ">(</span><span class="kt" id="mwIg">char</span><span class="w" id="mwIw"> </span><span class="o" id="mwJA">*</span><span class="w" id="mwJQ"> </span><span class="n" id="mwJg">large_user_input</span><span class="p" id="mwJw">)</span><span class="w" id="mwKA"> </span><span class="p" id="mwKQ">{</span> <span class="w" id="mwKg"> </span><span class="kt" id="mwKw">char</span><span class="w" id="mwLA"> </span><span class="n" id="mwLQ">dst</span><span class="p" id="mwLg">[</span><span class="n" id="mwLw">SMALL</span><span class="p" id="mwMA">];</span> <span class="w" id="mwMQ"> </span><span class="n" id="mwMg">strcpy</span><span class="p" id="mwMw">(</span><span class="n" id="mwNA">dst</span><span class="p" id="mwNQ">,</span><span class="w" id="mwNg"> </span><span class="n" id="mwNw">large_user_input</span><span class="p" id="mwOA">);</span> <span class="p" id="mwOQ">}</span>If the user input is larger than the destination buffer, a buffer overflow will occur. To fix this unsafe program, use strncpy to prevent a possible buffer overflow.
<span id="mwPQ"></span><span class="kt" id="mwPg">int</span><span class="w" id="mwPw"> </span><span class="nf" id="mwQA">secure_function</span><span class="p" id="mwQQ">(</span><span class="kt" id="mwQg">char</span><span class="w" id="mwQw"> </span><span class="o" id="mwRA">*</span><span class="w" id="mwRQ"> </span><span class="n" id="mwRg">user_input</span><span class="p" id="mwRw">)</span><span class="w" id="mwSA"> </span><span class="p" id="mwSQ">{</span> <span class="w" id="mwSg"> </span><span class="kt" id="mwSw">char</span><span class="w" id="mwTA"> </span><span class="n" id="mwTQ">dst</span><span class="p" id="mwTg">[</span><span class="n" id="mwTw">BUF_SIZE</span><span class="p" id="mwUA">];</span> <span class="w" id="mwUQ"> </span><span class="c1" id="mwUg">// copy a maximum of BUF_SIZE bytes</span> <span class="w" id="mwUw"> </span><span class="n" id="mwVA">strncpy</span><span class="p" id="mwVQ">(</span><span class="n" id="mwVg">dst</span><span class="p" id="mwVw">,</span><span class="w" id="mwWA"> </span><span class="n" id="mwWQ">user_input</span><span class="p" id="mwWg">,</span><span class="w" id="mwWw"> </span><span class="n" id="mwXA">BUF_SIZE</span><span class="p" id="mwXQ">);</span> <span class="w" id="mwXg"> </span><span class="c1" id="mwXw">// set the last character in the buffer to NUL.</span> <span class="w" id="mwYA"> </span><span class="n" id="mwYQ">dst</span><span class="p" id="mwYg">[</span><span class="n" id="mwYw">BUF_SIZE</span><span class="w" id="mwZA"> </span><span class="mi" id="mwZQ">-1</span><span class="p" id="mwZg">]</span><span class="w" id="mwZw"> </span><span class="o" id="mwaA">=</span><span class="w" id="mwaQ"> </span><span class="sc" id="mwag">'\0'</span><span class="p" id="mwaw">;</span> <span class="p" id="mwbA">}</span>Another secure alternative is to dynamically allocate memory on the heap using malloc.
<span id="mwcQ"></span><span class="kt" id="mwcg">char</span><span class="w" id="mwcw"> </span><span class="o" id="mwdA">*</span><span class="w" id="mwdQ"> </span><span class="nf" id="mwdg">secure_copy</span><span class="p" id="mwdw">(</span><span class="kt" id="mweA">char</span><span class="w" id="mweQ"> </span><span class="o" id="mweg">*</span><span class="w" id="mwew"> </span><span class="n" id="mwfA">src</span><span class="p" id="mwfQ">)</span><span class="w" id="mwfg"> </span><span class="p" id="mwfw">{</span> <span class="w" id="mwgA"> </span><span class="kt" id="mwgQ">size_t</span><span class="w" id="mwgg"> </span><span class="n" id="mwgw">len</span><span class="w" id="mwhA"> </span><span class="o" id="mwhQ">=</span><span class="w" id="mwhg"> </span><span class="n" id="mwhw">strlen</span><span class="p" id="mwiA">(</span><span class="n" id="mwiQ">src</span><span class="p" id="mwig">);</span> <span class="w" id="mwiw"> </span><span class="kt" id="mwjA">char</span><span class="w" id="mwjQ"> </span><span class="o" id="mwjg">*</span><span class="w" id="mwjw"> </span><span class="n" id="mwkA">dst</span><span class="w" id="mwkQ"> </span><span class="o" id="mwkg">=</span><span class="w" id="mwkw"> </span><span class="p" id="mwlA">(</span><span class="kt" id="mwlQ">char</span><span class="w" id="mwlg"> </span><span class="o" id="mwlw">*</span><span class="p" id="mwmA">)</span><span class="w" id="mwmQ"> </span><span class="n" id="mwmg">malloc</span><span class="p" id="mwmw">(</span><span class="n" id="mwnA">len</span><span class="w" id="mwnQ"> </span><span class="o" id="mwng">+</span><span class="w" id="mwnw"> </span><span class="mi" id="mwoA">1</span><span class="p" id="mwoQ">);</span> <span class="w" id="mwog"> </span><span class="k" id="mwow">if</span><span class="w" id="mwpA"> </span><span class="p" id="mwpQ">(</span><span class="n" id="mwpg">dst</span><span class="w" id="mwpw"> </span><span class="o" id="mwqA">!=</span><span class="w" id="mwqQ"> </span><span class="nb" id="mwqg">NULL</span><span class="p" id="mwqw">)</span><span class="w" id="mwrA"> </span><span class="p" id="mwrQ">{</span> <span class="w" id="mwrg"> </span><span class="n" id="mwrw">strncpy</span><span class="p" id="mwsA">(</span><span class="n" id="mwsQ">dst</span><span class="p" id="mwsg">,</span><span class="w" id="mwsw"> </span><span class="n" id="mwtA">src</span><span class="p" id="mwtQ">,</span><span class="w" id="mwtg"> </span><span class="n" id="mwtw">len</span><span class="p" id="mwuA">);</span> <span class="w" id="mwuQ"> </span><span class="c1" id="mwug">// append null terminator </span> <span class="w" id="mwuw"> </span><span class="n" id="mwvA">dst</span><span class="p" id="mwvQ">[</span><span class="n" id="mwvg">len</span><span class="p" id="mwvw">]</span><span class="w" id="mwwA"> </span><span class="o" id="mwwQ">=</span><span class="w" id="mwwg"> </span><span class="sc" id="mwww">'\0'</span><span class="p" id="mwxA">;</span> <span class="w" id="mwxQ"> </span><span class="p" id="mwxg">}</span> <span class="w" id="mwxw"> </span><span class="k" id="mwyA">return</span><span class="w" id="mwyQ"> </span><span class="n" id="mwyg">dst</span><span class="p" id="mwyw">;</span> <span class="p" id="mwzA">}</span>In the above code snippet, the program attempts to copy the contents of src into dst, while also checking the return value of malloc to ensure that enough memory was able to be allocated for the destination buffer.
Sign in to keep reading
3 more chapters are free with a Lably account.
Format-string attack prevention
A Format String Attack is when a malicious user supplies specific inputs that will eventually be entered as an argument to a function that performs formatting, such as printf(). The attack involves the adversary reading from or writing to the stack.
The C printf function writes output to stdout. If the parameter of the printf function is not properly formatted, several security bugs can be introduced. Below is a program that is vulnerable to a format string attack.
<span id="mw2g"></span><span class="kt" id="mw2w">int</span><span class="w" id="mw3A"> </span><span class="nf" id="mw3Q">vulnerable_print</span><span class="p" id="mw3g">(</span><span class="kt" id="mw3w">char</span><span class="w" id="mw4A"> </span><span class="o" id="mw4Q">*</span><span class="w" id="mw4g"> </span><span class="n" id="mw4w">malicious_input</span><span class="p" id="mw5A">)</span><span class="w" id="mw5Q"> </span><span class="p" id="mw5g">{</span> <span class="w" id="mw5w"> </span><span class="n" id="mw6A">printf</span><span class="p" id="mw6Q">(</span><span class="n" id="mw6g">malicious_input</span><span class="p" id="mw6w">);</span> <span class="p" id="mw7A">}</span>A malicious argument passed to the program could be "%s%s%s%s%s%s%s", which can crash the program from improper memory reads.
Integer-overflow prevention
Integer overflow occurs when an arithmetic operation results in an integer too large to be represented within the available space. A program which does not properly check for integer overflow introduces potential software bugs and exploits.
Below is a function in C++ which attempts to confirm that the sum of x and y is less than or equal to a defined value MAX:
<span id="mw9Q"></span><span class="kt" id="mw9g">bool</span><span class="w" id="mw9w"> </span><span class="nf" id="mw-A">sumIsValid_flawed</span><span class="p" id="mw-Q">(</span><span class="kt" id="mw-g">unsigned</span><span class="w" id="mw-w"> </span><span class="kt" id="mw_A">int</span><span class="w" id="mw_Q"> </span><span class="n" id="mw_g">x</span><span class="p" id="mw_w">,</span><span class="w" id="mwAQA"> </span><span class="kt" id="mwAQE">unsigned</span><span class="w" id="mwAQI"> </span><span class="kt" id="mwAQM">int</span><span class="w" id="mwAQQ"> </span><span class="n" id="mwAQU">y</span><span class="p" id="mwAQY">)</span><span class="w" id="mwAQc"> </span><span class="p" id="mwAQg">{</span> <span class="w" id="mwAQk"> </span><span class="kt" id="mwAQo">unsigned</span><span class="w" id="mwAQs"> </span><span class="kt" id="mwAQw">int</span><span class="w" id="mwAQ0"> </span><span class="n" id="mwAQ4">sum</span><span class="w" id="mwAQ8"> </span><span class="o" id="mwARA">=</span><span class="w" id="mwARE"> </span><span class="n" id="mwARI">x</span><span class="w" id="mwARM"> </span><span class="o" id="mwARQ">+</span><span class="w" id="mwARU"> </span><span class="n" id="mwARY">y</span><span class="p" id="mwARc">;</span> <span class="w" id="mwARg"> </span><span class="k" id="mwARk">return</span><span class="w" id="mwARo"> </span><span class="n" id="mwARs">sum</span><span class="w" id="mwARw"> </span><span class="o" id="mwAR0"><=</span><span class="w" id="mwAR4"> </span><span class="n" id="mwAR8">MAX</span><span class="p" id="mwASA">;</span> <span class="p" id="mwASE">}</span>The problem with the code is it does not check for integer overflow on the addition operation. If the sum of x and y is greater than the maximum possible value of an unsigned int, the addition operation will overflow and perhaps result in a value less than or equal to MAX, even though the sum of x and y is greater than MAX.
Below is a function which checks for overflow by confirming the sum is greater than or equal to both x and y. If the sum did overflow, the sum would be less than x or less than y.
<span id="mwASc"></span><span class="kt" id="mwASg">bool</span><span class="w" id="mwASk"> </span><span class="nf" id="mwASo">sumIsValid_secure</span><span class="p" id="mwASs">(</span><span class="kt" id="mwASw">unsigned</span><span class="w" id="mwAS0"> </span><span class="kt" id="mwAS4">int</span><span class="w" id="mwAS8"> </span><span class="n" id="mwATA">x</span><span class="p" id="mwATE">,</span><span class="w" id="mwATI"> </span><span class="kt" id="mwATM">unsigned</span><span class="w" id="mwATQ"> </span><span class="kt" id="mwATU">int</span><span class="w" id="mwATY"> </span><span class="n" id="mwATc">y</span><span class="p" id="mwATg">)</span><span class="w" id="mwATk"> </span><span class="p" id="mwATo">{</span> <span class="w" id="mwATs"> </span><span class="kt" id="mwATw">unsigned</span><span class="w" id="mwAT0"> </span><span class="kt" id="mwAT4">int</span><span class="w" id="mwAT8"> </span><span class="n" id="mwAUA">sum</span><span class="w" id="mwAUE"> </span><span class="o" id="mwAUI">=</span><span class="w" id="mwAUM"> </span><span class="n" id="mwAUQ">x</span><span class="w" id="mwAUU"> </span><span class="o" id="mwAUY">+</span><span class="w" id="mwAUc"> </span><span class="n" id="mwAUg">y</span><span class="p" id="mwAUk">;</span> <span class="w" id="mwAUo"> </span><span class="k" id="mwAUs">return</span><span class="w" id="mwAUw"> </span><span class="n" id="mwAU0">sum</span><span class="w" id="mwAU4"> </span><span class="o" id="mwAU8">>=</span><span class="w" id="mwAVA"> </span><span class="n" id="mwAVE">x</span><span class="w" id="mwAVI"> </span><span class="o" id="mwAVM">&&</span><span class="w" id="mwAVQ"> </span><span class="n" id="mwAVU">sum</span><span class="w" id="mwAVY"> </span><span class="o" id="mwAVc">>=</span><span class="w" id="mwAVg"> </span><span class="n" id="mwAVk">y</span><span class="w" id="mwAVo"> </span><span class="o" id="mwAVs">&&</span><span class="w" id="mwAVw"> </span><span class="n" id="mwAV0">sum</span><span class="w" id="mwAV4"> </span><span class="o" id="mwAV8"><=</span><span class="w" id="mwAWA"> </span><span class="n" id="mwAWE">MAX</span><span class="p" id="mwAWI">;</span> <span class="p" id="mwAWM">}</span>Path traversal prevention
Path traversal is a vulnerability whereby paths provided from an untrusted source are interpreted in such a way that unauthorised file access is possible.
For example, consider a script that fetches an article by taking a filename, which is then read by the script and parsed. Such a script might use the following hypothetical URL to retrieve an article about dog food:
<span typeof="mw:Nowiki" id="mwAWo">https://www.example.net/cgi-bin/article.sh?name=dogfood.html</span>
If the script has no input checking, instead trusting that the filename is always valid, a malicious user could forge a URL to retrieve configuration files from the web server:
<span typeof="mw:Nowiki" id="mwAW4">https://www.example.net/cgi-bin/article.sh?name=../../../../../etc/passwd</span>
Depending on the script, this may expose the /etc/passwd file, which on Unix-like systems contains (among others) user IDs, their login names, home directory paths and shells. (See SQL injection for a similar attack.)

