Surely after part 1 and part 2 , everyone has understood the importance of ensuring product safety right from the design and programming. In this part 3, we will learn about a more dangerous vulnerability, which also appears quite a lot in the challenges of the secure coding ctf.
It is an OS Command Injection vulnerability.
7. OS Command Injection
OS Command Injection is a vulnerability in the functions, lines of code that will execute system commands. When these functions receive input from outside (entered by the user, received from another service, …) without checking carefully, it is possible that the input contains more system commands connected together. When the function is executed, the server will accidentally execute more commands that are “injected” .
Suppose your product has a function that lists images as follows:
- B1: When you press the button, it will send to the server the data is:
ls
. - B2: Server, after receiving data from the client, will pass the input into the function to execute the system command to get the list of files.
- B3: Server returns data to the client.
- B4: The client displays a list of images for the user to view.
In step 1, the attacker can insert system commands for the server to execute. If the inserted command is a fairly familiar command rm -rf then why =))
Often times when the OS Command Injection vulnerability is successfully exploited, an attacker will use a number of techniques to maintain a connection to the server, thereby repeatedly asking the server to execute the commands he wants. Then when he successfully escalated his privilege … like this sticker here =))
I think that brief is enough to see the cause of the OS Command Injection vulnerability and its danger level. With this vulnerability, secure coding ctf also provides up to 3 challlenges with increasing difficulty.
7.1. Example 1: Ping me
Information:
- Week: 3
- Post: Ping me
- Programming language: PHP
- Source code:
- index.php: https://ideone.com/JwzHDu
- code.php: https://ideone.com/Dse9dC
In the index.php file we see that when entering a valid IP address, the server will ping that address and return us the result. Here to test if there is an OS Command Injection vulnerability, we just need to add 1 system command character like |
, ||
, &
, &&
, … followed by a system command.
Saying that, reading the code is knowing that it has holes already, not handling user input.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token keyword">isset</span> <span class="token punctuation">(</span> <span class="token variable">$_GET</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'address'</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$address</span> <span class="token operator">=</span> <span class="token variable">$_GET</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'address'</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">require</span> <span class="token double-quoted-string string">"code.php"</span> <span class="token punctuation">;</span> <span class="token variable">$command</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"ping -c 1 "</span> <span class="token punctuation">;</span> <span class="token variable">$command</span> <span class="token operator">=</span> <span class="token variable">$command</span> <span class="token punctuation">.</span> <span class="token variable">$address</span> <span class="token punctuation">.</span> <span class="token double-quoted-string string">" 2>&1"</span> <span class="token punctuation">;</span> <span class="token variable">$answer</span> <span class="token operator">=</span> <span class="token function">shell_exec</span> <span class="token punctuation">(</span> <span class="token variable">$command</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">echo</span> <span class="token double-quoted-string string">"<h3>"</span> <span class="token punctuation">.</span> <span class="token function">preg_replace</span> <span class="token punctuation">(</span> <span class="token double-quoted-string string">"/r|n/"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"<br/>"</span> <span class="token punctuation">,</span> <span class="token variable">$answer</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token double-quoted-string string">"</h3>"</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter important">?></span></span> |
- $ address is the value we entered.
- $ command is the command that the system will execute. This $ command variable is then appended directly to the input we entered.
- “2> & 1” simply put both the error messages (stderr) into the output (stdout) that will return us (reference read link:2> & 1 is what? ).
- shell_exec ($ command) will execute the system command stored in the $ command variable, and the result is written to the variable $ answer .
With input is 8.8.8.8 | ls
then the server will execute ping -c 1 8.8.8.8 | ls
and returns the result, including flag1 _ +. txt file (the server is off so I can’t take the picture anymore). Now we have to read this file to get the flag.
Although not carefully checking the input, but in the code.php file there is filtered cat
string. Since the cat command cannot be used to read the contents of the file, at this point it will take a little “know-how” to know about Linux. In addition to the cat
command, there are some other commands that also help us read the file’s content, for example:
nl
: reads the file like the cat command, but has an extra line number.head
: reads some lines at the beginning of the filetail
: read some lines at the end of the file
Here I have used the nl
command to read the flag content.
7.2. Example 2: Pong
Information:
- Week: 3
- Lesson: Pong
- Programming language: PHP
- Source code: https://ideone.com/9gO7R3
This time the code was checked more carefully to avoid being exploited by OS Command Injection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">require</span> <span class="token double-quoted-string string">"dir_listing.php"</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token keyword">isset</span> <span class="token punctuation">(</span> <span class="token variable">$_GET</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'address'</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$address</span> <span class="token operator">=</span> <span class="token variable">$_GET</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'address'</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token variable">$address</span> <span class="token operator">=</span> <span class="token function">preg_replace</span> <span class="token punctuation">(</span> <span class="token double-quoted-string string">"/||&|;|`|n/"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">" "</span> <span class="token punctuation">,</span> <span class="token variable">$address</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$command</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"ping -c 1 "</span> <span class="token punctuation">;</span> <span class="token variable">$command</span> <span class="token operator">=</span> <span class="token variable">$command</span> <span class="token punctuation">.</span> <span class="token variable">$address</span> <span class="token punctuation">.</span> <span class="token double-quoted-string string">" 2>&1"</span> <span class="token punctuation">;</span> <span class="token comment">// echo $command;</span> <span class="token variable">$answer</span> <span class="token operator">=</span> <span class="token function">shell_exec</span> <span class="token punctuation">(</span> <span class="token variable">$command</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">echo</span> <span class="token double-quoted-string string">"<h3>"</span> <span class="token punctuation">.</span> <span class="token function">preg_replace</span> <span class="token punctuation">(</span> <span class="token double-quoted-string string">"/r|n/"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"<br/>"</span> <span class="token punctuation">,</span> <span class="token variable">$answer</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token double-quoted-string string">"</h3>"</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter important">?></span></span> |
The code is similar to the above example, but this time the characters commonly used to exploit the OS Command Injection vulnerability have been filtered and replaced entirely with a space character.
However, it has not been fully filtered yet, there are still some characters that can be used to nest statements, that is 3 characters $ ( )
. With these 3 characters can help execute the command: $(command)
will cause the server to execute the command.
Because I don’t know where the flag is, I just search the entire server for files with the name “flag”.
So right in my current directory there is a file flag2.txt
This time, I didn’t see anything blocked, so I cated the file’s contents.
7.3. Example 3: Overwatch
Information:
- Week: 3
- Post: Overwatch
- Programming language: Python
- Source code: https://ideone.com/tDy2XI
The sign that a website has a command injection vulnerability is in the code from lines 40 – 42:
1 2 3 4 | cmd <span class="token operator">=</span> <span class="token string">'echo {} > ./languages/{}.txt'</span> <span class="token punctuation">.</span> <span class="token builtin">format</span> <span class="token punctuation">(</span> language <span class="token punctuation">,</span> username <span class="token punctuation">)</span> subprocess <span class="token punctuation">.</span> Popen <span class="token punctuation">(</span> cmd <span class="token punctuation">,</span> shell <span class="token operator">=</span> <span class="token boolean">True</span> <span class="token punctuation">,</span> stdout <span class="token operator">=</span> subprocess <span class="token punctuation">.</span> PIPE <span class="token punctuation">,</span> stderr <span class="token operator">=</span> subprocess <span class="token punctuation">.</span> STDOUT <span class="token punctuation">)</span> |
In this example, we also connect the input directly to the command to execute, no input filtering at all. However, the results are not displayed on the interface, so it is difficult to determine the command execution result.
With this type of exploitation blind OS Command Injection, it is necessary to have own techniques to test. This challenge also provides a simple way for us already. At line 45, we know there is a file /LICENSE.md that we can view the contents of. And on line 52 we know that there is permission to write to this file as well: license_file = open('LICENSE.md', 'w')
So the exploitation direction is as follows: we can execute a command and write the results to the file LICENSE.md
, then read this file from the client side. Here I have tried with the ls
command, recording the execution result of this command in LICENSE.md
So was successful in exploiting Blind OS Command Injection. Similarly, just replace the command ls
with the command cat flag20.txt
to write the content of the flag20.txt
file to the LICENSE.md
file.
So what should we do to prevent OS Command Injection vulnerability?
- Option 1: minimize the user input used in the commands will be executed.
- Method 2: filter the input carefully, remove the characters that can “chain” command like
|
,||
,&
,&&
,;
,$
, …