Password on code - what's the best way to obfuscate it?

R

Rodrigo Bermejo

Dear fellows /.

I've been in the need to crate applications which require to make use of
another program which requires authentication. As everyone who has
tried to solve this problem with a script lang (no compiled, what would
be the best term /?), a security concern comes in play.

Where in hell should I put the password /?

Last day I got caught in a philosophical journey thinking about it.
..A password needs a password to be "decrypted"..you can create as many
layers of passwords to obfuscate the previous one , but you will ever
need a password to decrypt all the underlying passwords.

I did not take this subject in the school :)

Some one could share its experiences with ruby to attack this security
issue?
Would be wonderful too if some of you could share your philosophical
thoughts about.

!!!! Enjoy its Friday !!!!

-r.
rm -rf /usr/bin/rm
 
D

David Masover

I've been in the need to crate applications which require to make use of
another program which requires authentication. As everyone who has
tried to solve this problem with a script lang (no compiled, what would
be the best term /?), a security concern comes in play.

Where in hell should I put the password /?

Probably the same place you'd put it in a complied language. Consider:

int main() {
char * a = "one two three";
a = "four five six";
return 0;
}

Compile that, even strip the result, then run strings on it. I get this:

/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
__libc_start_main
GLIBC_2.2.5
fff.
fffff.
-#
l$ L
t$(L
|$0H
one two three
four five six

If you were "hiding" passwords in C/C++ source, I hope that makes the point
clearly that they aren't "hidden" at all. Indeed, it's the same problem of any
DRM scheme -- if you're giving your program to a user, and the program has a
password or key embedded in it, the user can get that key.

To answer your question properly, I have to ask: Who are you trying to hide
this password from?

If you're actually going to distribute it to end-users who you _don't_ want to
have the key, read the above until it sinks in -- you're _not_ going to be
able to obfuscate it to where a user can't figure it out. If this is a problem,
you'll have to get more specific -- it's possible there's a way to make it more
secure, but it's not going to involve obfuscation.

If it's something else, it really depends what you're doing. For example, if
your users have that password, but you just don't want it stored in plain
text, you might look at interfacing with whatever their local "keychain" might
be -- in OS X, this is Keychain. On Linux, this could be KWallet, or it could
be gnome-keyring. On Windows, there's something built in that encrypts things
using, I believe, the user's login password.

If this is a web service, and you just don't want that password in the
repository -- understandable, as you might share that code with others at some
point -- separate it out, put it in a config file, make sure that config file
isn't in version control and isn't world-readable, but is somewhere the app
can get at. For example, if it's your MySQL password, you could just put it in
~/.my.cnf and parse that -- or, what I used to do, parse that in a deploy
script, and use it to generate database.yml for Rails.



Oh, and completely unrelated, but your sig:
rm -rf /usr/bin/rm

That's better written as:

rm -f `which rm`

And it works just fine. Indeed, if you run "rm -rf /", it has no problems
deleting every file on the system, including rm itself and the shell. This is
because in Unix, a file isn't removed until its last reference is gone -- that
means all filenames (each file can have multiple names, they're called
hardlinks), and all open handles (any program that has the file actually open
for reading/writing).

The 'rm' command just removes a link (name) -- this usually results in a file
being deleted, but if a program has it open, the file will still exist until
the program closes it.

So, rm can rm itself (removing the link), so it looks like rm has been
deleted. Then, when rm exits, the last link to rm is gone, and the kernel
cleans up the file.

And yes, I did play with this -- installed a minimal Linux in a vm, and did
"rm -rf /" as root, just to see if it would work. It did -- I think the only
things left were mountpoints.
 
7

7stud --

David said:
Probably the same place you'd put it in a complied language. Consider:

int main() {
char * a = "one two three";
a = "four five six";
return 0;
}

Compile that, even strip the result, then run strings on it. I get this:

1) What does "even strip the result" mean?

2) What does "run strings on it" mean?
 
B

Ben Giddings

1) What does "even strip the result" mean?

'strip' is a tool for removing all symbols from an object file or
executable. It means that if you try to debug the code you get no
meaningful breakpoints, function names, variable names, etc. On the
other hand, it doesn't remove any string constants that are used.
2) What does "run strings on it" mean?

'strings' is another tool used to see "strings" in a binary file. It
basically looks through the entire file and when it encounters 4 bytes
in a row that are ASCII characters, it assumes it's a string and
prints it out. This means it finds a lot of junk that isn't really a
true string, but it also finds any actual string in the file that's at
least 4 chars long.

http://unixhelp.ed.ac.uk/CGI/man-cgi?strings
http://unixhelp.ed.ac.uk/CGI/man-cgi?strip

Ben
 
S

s.ross

2) What does "run strings on it" mean?

Dump anything that seems like strings in otherwise binary data.

$ which strings
/usr/bin/strings
$ strings /usr/bin/strings|head
Usage: %s [-] [-a] [-o] [-t format] [-number] [-n number] [[-arch
<arch_flag>] ...] [--] [file ...]
%.*s
__text
__TEXT
-arch
missing argument(s) to %s option
unknown architecture specification flag: %s %s
missing argument to %s option
invalid decimal number in option: %s %s
invalid argument to option: %s %s
[...]
 
D

David Masover

Thanks for clearing that up, I should've been more specific...

'strip' is a tool for removing all symbols from an object file or
executable. It means that if you try to debug the code you get no
meaningful breakpoints, function names, variable names, etc. On the
other hand, it doesn't remove any string constants that are used.

Right. Basically, it removes so-called "debugging symbols", returning a binary
that is smaller, more optimized in theory, but harder to debug. Ubuntu, at
least, seems to ship stripped binaries, with the debugging symbols elsewhere.

But the resultant binary is functionally identical. In order for the program
to run, it needs to have a string somewhere.
'strings' is another tool used to see "strings" in a binary file. It
basically looks through the entire file and when it encounters 4 bytes
in a row that are ASCII characters, it assumes it's a string and
prints it out. This means it finds a lot of junk that isn't really a
true string, but it also finds any actual string in the file that's at
least 4 chars long.

Interesting. I assumed it actually analyzed the binary, somehow...

Of course, you can easily see how one might fool 'strings' -- something as
simple as xor'ing the string constant would probably make it seem to be
unprintable characters. But the same thing is going to apply to a scripted
language -- the only difference is that it's harder for most people to
disassemble a binary and reverse engineer what's going on, than simply read
through source code.

I should point out, again, that if the intent is to store a password inside
your program, such that people with a copy of the program can't get the
password, this presents roughly the same reverse-engineering difficulty as DRM,
which is known to be ineffective.

The reason I asked for more details was, maybe we could help rethink the
design, to provide real security, not just obfuscation.

To take a really simple example, suppose I wanted to distribute a program
which tied into some Amazon S3 storage that I control. I could try to stick my
Amazon credentials into the program, but then anyone could find them and delete
everyone's stuff.

The right solution isn't to hide them better, it's to never send those
credentials in the first place. Instead, I can set up a server which holds my
AWS credentials. The client then pings that server with an S3 request, the
server signs the request, then S3 knows it's approved -- and the server can be
smart enough not to let the client delete anything it's not supposed to.

But to know how to do this right, I'd still have to know what he's actually
trying to do.
 
B

Brian Candler

Rodrigo said:
I've been in the need to crate applications which require to make use of
another program which requires authentication. As everyone who has
tried to solve this problem with a script lang (no compiled, what would
be the best term /?), a security concern comes in play.

Where in hell should I put the password /?

Option 1: put the password in a config file, and use filesystem
permissions to ensure it is readable to the application but not to
anyone else.

Of course, don't put the config file with the live password in your
source repository. You can keep a file with dummy passwords in source,
say
config/database.yml.sample

Then when the software is deployed, you do
cp config/database.yml.sample config/database.yml
chmod 400 config/database.yml
vi config/database.yml

(or the equivalent from your automated deployment process) to insert the
real password(s).

Option 2: GPG-encrypt your config file. When the application starts up,
make it prompt the user for the passphrase to decrypt the config. This
is most easily done by piping the config in on stdin, because gpg itself
will prompt for the necessary passphrase.

# startup script
gpg --homedir /path/to/config --decrypt /path/to/config.yml.asc | ruby
myapp.rb

# application
secret_data = YAML.load($stdin.read)

This is very secure if your passphrase is random enough, but has the
downside that if your machine reboots, it will have to wait for a
passphrase before the application can start.
 
B

Brian Candler

BTW, I was assuming that your application user doesn't have
administrative access to the system where the application is hosted.

If they do, all bets are off. For example:

* They can take a copy of your script, and modify it to add "STDERR.puts
password" at the appropriate point

* They can load their own version of Net::HTTP which prints out the
passwords it is using

* Unless you're using HTTPS or digest authentication, they can use
tcpdump/wireshark to look at the HTTP transaction on the wire, and
easily see the Authorization: header which contains the cleartext
username and password

But if you don't care about those possibilities (*), then you may as
well use any sort of trivial password hiding, such as setting the top
bit in each byte.

[ruby 1.8 example]
passwd => "\364\357\360\256\363\345\343\362\345\364"
passwd.size.times { |i| passwd = passwd ^ 0x80 } => 10
passwd

=> "top.secret"

[ruby 1.9 example]
passwd = "\364\357\360\256\363\345\343\362\345\364" => "\xF4\xEF\xF0\xAE\xF3\xE5\xE3\xF2\xE5\xF4"
passwd.size.times { |i| passwd = (passwd.ord ^ 0x80).chr }

ArgumentError: invalid byte sequence in UTF-8
from (irb):2:in `ord'
from (irb):2:in `block in irb_binding'
from (irb):2:in `times'
from (irb):2
from /usr/local/bin/irb19:12:in ` said:
passwd.force_encoding("BINARY") => "\xF4\xEF\xF0\xAE\xF3\xE5\xE3\xF2\xE5\xF4"
passwd.size.times { |i| passwd = (passwd.ord ^ 0x80).chr("BINARY") } => 10
passwd

=> "top.secret"

You can both hide and unhide passwords with the same code.

Regards,

Brian.

(*) This is making the (IMO risky) assessment that your users are too
dumb to use these techniques to recover the password, and yet not so
dumb that you'd be happy leaving the password in clear text.

There are lots of similar approaches, for example embedding a client SSL
certificate in your application, and using certificate authentication at
the server. This assumes your adversary is so dumb that they don't know
how to take the private key and certificate from the app and use it
themselves.
 
A

Axel Etzold

-------- Original-Nachricht --------
Datum: Mon, 14 Sep 2009 17:44:31 +0900
Von: Brian Candler <[email protected]>
An: (e-mail address removed)
Betreff: Re: Password on code - what\'s the best way to obfuscate it?

Dear Rodrigo,

you can use a variant of a secret sharing scheme. In such a scheme, a secret (password) is split up in n parts, and there is a number k<=n of partial secrets needed to retrieve it.
The fact that a secret is split enables you to distribute less than
the k information bits to any user and keep the remaining secret parts and the application to recombine it at a safe place (somewhere the user cannot read from - I assume this is possible for you as you say that you want to interface another program - which I assume you'll run on a web server or the like).

In the safe place, you'd have to write some code to combine the password from the k bits necessary to retrieve it.
Thus, when the user enters his info, the information transferred is not
sufficient to intercept or rebuild the correct password and the combined
one is wrong.

There's a descriptions of Shamir's secret sharing scheme with a simplified
example and links to some (non-Ruby) code (the web interface didn't work for me) here:

http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing

If you'd have to give away the entire application on a user's computer,
I second the previous respondents' pessimism - just like everything else
they wrote.

Best regards,

Axel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top