The other day I came across a program that allowed me to select from a prepackaged set of queries and then communicated with a server to retrieve the answer to the selected query. I began to wonder when I realized that the program never asked for a password for authentication with the server. It turns out that the password was embedded in the program. The author explained that it was OK because 1) it was a binary file so no one could read it and 2) if they could read it they wouldn’t be able to find the password string.
Neither of these reasons is valid and I would like to use this post to demonstrate that. My example program just writes the “password” on the terminal but the only difference between it and an actual production program is the number of strings that a malicious user would have to search through.
#include <stdio.h>
#include <string.h>
main ()
{
char password [9] = {"secret"};
printf ("This is the password: %sn", password);
}
|
Figure 1 – Basic program with embedded password |
When executed it displays
x1
This is the password: secret
ready 14:12:16
|
Figure 2 – Execution of basic program |
To display the strings in the program module our malicious user can use the strings command from the >system>gnu_library>bin directory. The -n5 limits the output to strings of 5 characters or longer. I’ve truncated the output (. . . .) to shorten the display but you can see that the password is one of the very first strings displayed. Having the password in close proximity to keywords like “login” or “password” or to an identifiable user ID like “admin”, “root”, or “sql” makes the search easier.
>system>gnu_library>bin>strings -n5 x1.pm
bind, Release 17.1.beta.be
phx_vos#
Noah_Davids.CAC
Pre-release
This is the password: %s
secret
s$start_c_program
_preemption_cleanup
_exit
. . . . .
|
Figure 3 – Using the GNU strings command to find all strings longer than 4 characters in program module |
If the strings command is not available our malicious user can just display the program module. I suspect that we have all done this by accident and while not pretty it will display the password. I’ve again truncated the output and again you can see the password.
d x1.pm
%phx_vos#m16_mas>SysAdmin>Noah_Davids>x1.pm 11-01-13 14:13:59 mst
`00`01`00`1Abind, Release 17.1.beta.be`00`00`00`00`00`00`00`04ctp
`00`00`00`00`0
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`0
0phx_vos
+#`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`
00`00Noa
. . . .
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`C
D'`8B`C0
+`00`00`00`00This is the password: %s
`00`00`00`00`00`00`00secret`00`00`00`00`00`00`00`04`B0`00`00`00`00`01`00
`00`00,`
+`00`00`04`00`00`00`03@`00`FF`F8`FF`FE`00`04main`00`00`83`EC`2C`C7D$$`00
. . . .
|
Figure 4 – Displaying the program module to find the password |
There are several alternatives to embedding the password in the program.
The password can be placed in a file and the program can read the file. Only those people with a “need to run” are given read access to the file and everyone else gets null access. Of course “need to run” may not equate with “need to know the password”. In addition there is always the danger of someone mistakenly changing the access.
An alternative is to keep the password string in the program and just limit access to the program. This solution also suffers from the “it’s easy to change an access list” problem. If the program is kept in the same directory as other programs that can be run by anyone the probability of an access list change goes up.
Finally, you can keep the password in the program module but obfuscate the string somehow. The following program shows a simple way of doing this.
#include <stdio.h>
#include <string.h>
main ()
{
char obfuscate [9] = {0x0c, 0x81, 0xe2, 0x94, 0xe6, 0x9c};
char key [9] = {127, 228, 129, 230, 131, 232, 133, 234, 135};
char password [9];
int i;
for (i = 0; i < strlen (obfuscate); i++)
password [i] = obfuscate [i] ^ key [i];
password [i] = 0x0;
printf ("This is the password: %sn", password);
}
|
Figure 5 – Program with obfuscated password string |
As you can see all it does is take the obfuscate characters and XOR them with another a set of key characters to create the password. Running the program produces the same output as the first program.
x2
This is the password: secret
ready 14:12:51
|
Figure 6 – Execution of obfuscated program |
But a search for strings does not show anything that looks like the password
>system>gnu_library>bin>strings -n5 x1.pm bind, Release 17.1.beta.be phx_vos# Noah_Davids.CAC Pre-release This is the password: %s s$start_c_program _preemption_cleanup _exit . . . . |
Figure 7 – strings command no longer shows password |
And while displaying the file will show the obfuscated password characters and the key characters you have to know exactly where to look to find them and also how they are combined to create the password.
d x2.pm
%phx_vos#m16_mas>SysAdmin>Noah_Davids>x2.pm 11-01-13 14:15:27 mst
. . . .
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`CD'`8B`
C0`00`0
+0`00`00This is the password: %s
`00`00`00`00`00`00`00`0C`81`E2`94`E6`9C`00`00`00`00`00`00`00`00`00`00`7F
`E4`81`
+E6`83`E8`85`EA`87`00`00`00`00`04`B0`00`00`00`00`01`00`00`00`00`00`00`0
4`01`B0
+`00`03@`00`FF`F0`00`08`FF`FE`00`04main`00`00`83`EC`89$X`89t$T`89|$P`C
7D$L`00
|
Figure 8 – Displaying program module no longer shows recognizable password |
This is still not a perfect solution since the program module can be disassembled to figure out how the password is generated. Still disassembling the program requires a great deal more sophistication then just displaying the program module.
I am of two minds about putting the obfuscated password string in a file and then protecting the file via an access list. On the one hand if the password will ever need to be changed this is a much better solution then embedding the obfuscated password string in the program. On the other hand I suspect that even if there are other configuration options in the file, putting the string in the file will give our malicious user fewer potential password strings to investigate. Of course he will still need to gain access to the file and then have to figure out the obfuscation technique and key.
One final point, how did I generate the obfuscated password characters? The nice thing about the XOR operation is that ((A XOR B) XOR B) equals A so I just wrote a short program to take the original password XOR the characters with my key and print the result.
#include <stdio.h>
#include <string.h>
main ()
{
char password [9];
char key [9] = {127, 228, 129, 230, 131, 232, 133, 234, 135};
char newPW [9];
int i;
strcpy (password, "secret");
for (i = 0; i < strlen (password); i++)
{
newPW [i] = password [i] ^ key [i];
printf ("%xn", newPW [i]);
}
}
|
Figure 9 – Program to generate obfuscated password |