![]() |
Can malware steal a password held in ram by a running process?
Let's say a script prompts for a password and then uses the password to open an encrypted container or login to somewhere remotely or whatever.
If the script keeps the password in ram while it's looping doing whatever its purpose is, can NON-root malware steal the password? |
It depends on where the malware is, and how the password is being used.
1. passwords in shell scripts depend on how you use them. If they are put on the commandline, (like "mysql --user=user_name --password=your_password db_name" then they are public to anyone using the ps command for the duration of the command. Now there have been tricks to try and hide it (things like changing the parameter with the password), but they don't work reliably, and the password is STILL exposed for a short time. 2. if the malware is running as the same user (or root), then it is possible to use the debugger to extract it. There are some tricks available to block that (ssh uses one), and if your system supports SELinux, I think there is one there (it disables the capability for a ptrace connection to the process). 3. If the password is embedded in the script (rather than being prompted for) you also have to prevent the script from being read - as just reading the script will expose the password. The problem is that if a different user is going to use the script, then it must be readable by that user as well... In general, passwords and scripts don't mix very well. |
Quote:
|
i'm running this test but i am not able to find out how to read the password in another terminal instance:
Code:
[schneidz@hyper public_html]$ cat ulysses.ksh Code:
[schneidz@hyper ~]$ echo un = $un -- pw = $pw |
You can read the reads /writes of a process using strace if you are same user of process or the root user can read it all.
|
The plan being considered here is to only type the password before any malware is covertly loaded, and ensure this by using a live CD and blocking all internet access until the password is typed.
|
A login password does not need to be recorded anywhere, so unless some program along the way is retaining a copy in its memory the password could not be later recovered. Encryption keys are another matter. The key (not the passphrase, but the key generated from or unlocked by the passphrase) must be kept in kernel memory so that data can be encrypted/decrypted when required. For Linux whole disk encryption, root can easily recover such a key:
Code:
dmsetup table --showkeys {device_name} |
I need the passphrase in ram at all times, any key stolen is not much of an issue (because it only decrypts one container).
How can one prevent the passphrase from being stolen using something like ssh's tricks mentioned above? |
Quote:
What makes it tricky as far as scripting goes, is that it would have to be done within the interpreter program itself, and not by the script. Doing it outside the interpreter becomes a race condition - though if you lose the race, you can detect it as the ptrace system call will fail. It happens to work because the kernel only allows one process to control another process through the ptrace system call. You can test this by using gdb to attach to a shell process, and then attempt to do it again while gdb is active. The second should fail. As an added note: this would also block strace - which uses the ptrace system call to get the information from the traced process. |
Probably wiser to build ssh with my modifications then.
Also disabling the swap space is another thought. Or is ssh's code protected against this too? Truecrypt's keys can be recovered from the swap space sometimes. |
Quote:
Quote:
But malware running on the system would tend to not have access unless it is running as root. |
If root dumps memory, does obfuscating the passphrase's storage in ram and the source code have any chance? The attacker does not have the source code of my modifed ssh that is source modified to also manage 100 encrypted containers.
|
No.
Most likely your "modifications" will break ssh protocol standards, or violate security. |
Of course, step one is to make sure that the ssh connection is secured by digital certificates, each one of which might be password-protected.
After all, when you walk into the upper floors of any office-building, there's no one standing there asking each person, "say the magic word!" No, that person must present a unique badge, and if necessary, enter a PIN-number that's associated with it. The PIN unlocks the badge but is useless with regard to any other badge and is equally useless without the badge to which it belongs. If the badge is reported lost or stolen, within minutes it is useless ... PIN or not. Furthermore, in a true security system, this should serve only for authentication. The access authorizations that are granted to a particular certificate (security-token ... badge ...) are not in any way encoded in the certificate itself and cannot be affected in any way by the certificate-holder. |
Just a nit, but that PIN is the password. The "unique badge" is the login name.
|
Ssh is only taken as a sample of code that prevents password theft from ram, not for actual ssh connections.
The modifications would be just additional code that uses the password as a passphrase to mount selected truecrypt-clone containers, probably by calling the CLI of the truecrypt clone using the C system() call. Or modify the truecrypt clone sources instead. They'd have protection against ptrace would they not? Could use a separate original instance of ssh for ssh connections if wanted. |
You just broke your security.
The system() is not a secure library function. It permits side effects as it has to use bash to interpret the actual command - and that, at a minimum, exposes your password on the command line, or to debugging attached to the shell. Also see side effects - bash also interprets any special characters that may be in the command string. ssh already supports multiple connections (see port forwarding). |
Surely attaching to a shell that lives for a few milliseconds must be a challenge. What do you mean by special characters in the command string?
|
The simple things - ()*`';|$ And there are more. As for "that lives for a few milliseconds"?
Security is not a state - it is a process of doing things and paying attention to the details. ANY thing that can expose a secret is exposing that secret. And just how long does it take when something hangs for a while? Or what happens if an error occurs? Or what happens if something simple like a file name with rm -rf * occurs? Or one with a file name like "printenv >/tmp/public_file", or files with blanks embedded (ran across one using authors names - wasn't a problem for years, until there was a chinese name like fāng'àn... Handling special characters is NOT a simple process, and isn't static.) And since system() is using a shell, WHICH shell? Solaris/AIX/Linux don't all use the same one, and then there is Windows. http://xkcd.com/327/ There is also the issue of systems that track process (pacct records, audit records,...) some will record every parameter.... and thus record any passwords that happen to be on the command line. The system() function (along with popen, printf, sprintf, ...) are not secure library functions. |
Are you talking about invalid arguments in the ssh command line?
Invalid arguments in system() cannot appear because they are hardcoded in the C source code in my usage, except the password/passphrase. Any special characters in the passphrase are trivial to check and say "Sorry, passphrase must only contain letters a-z, A-Z or digits 0-9." For absolute security, it could be a direct call to the truecrypt-like software's main() function if the sources are build into one. |
You should also consider what happens to the password when the script stops running. It is still in RAM and can be found by scanning RAM for it.
|
Here's an idea. Have a password file inside an encrypted container. All you need to do is mount this container and use the password file inside for opening any further containers. That way you put the password only once and it isn't stored in RAM.
|
Quote:
Quote:
And limiting the passphrase in that manner makes it easier to hack. Passwords SHOULD have a character set as large as possible. It makes for much stronger passwords. Quote:
Note, you are now expanding the scope of ssh - and making it harder to validate. It is already hard enough as it is. Besides, you could use fork/exec yourself and set the parameters how you like - and completely bypass the shell entirely. Though that doesn't prevent the exposure of a password in the applications parameter list, or possibly through the application environment. It is still possible to also substitute a different program. Consider what might happen within a chroot jail - what it puts as the program name can be anything. And yes - this is stretching. But you do have to consider all the places and things that ssh is being used now. |
Looks like preventing theft of a password from ram is hopeless against malware with root privileges. Only normal user malware can be prevented from stealing a password. And even that with a lot of precaution.
Would a truecrypt clone use the same tricks as ssh against ptrace? Is this trick a common practise in security software? |
Should, but normally isn't done. It makes debugging very difficult. One reference for disabling ptrace outside of programming tricks is at http://fedoraproject.org/wiki/Featur...inuxDenyPtrace.
Though this is about cross security domain blocks, the capability to disable ptrace is in the system. |
There is some software in the windows world that allows you to automatically enter passwords to forms and other places.
How would the linux equivalent protect against theft of passwords from ram? When firefox stores passwords, how does it ensure they cannot be stolen from ram? |
Quote:
Quote:
1. only the owner (and root) may access the memory. 2. all other processes are blocked. As I have said earlier, it is possible for SELinux security labels to define a compartment that even root cannot access. But it is a bit tricky to setup, but once setup is very easy to use. |
Quote:
I think it's worth pointing out that any malware capable of doing that would have to have been written specifically to target a single specific version of Firefox. Also: I did a quick Amazon search for related material, and this one certainly looks relevant: http://www.amazon.ca/dp/1118825098 Finally, I'd recommend approaching this from the reverse angle. In order to answer "how would I prevent malware from stealing passwords from RAM" (and evaluate the risk of that actually happening), you first need to answer: "how would I write malware that steals passwords from RAM?" |
Quote:
|
Quote:
|
I was hoping any keylogger is loaded AFTER you type the password/passphrase, in other words you would boot a live CD on a diskless pc, then enter the passphrase to mount one container out of a 100, then browse the internet, then get infected, then the malware can only see the one container but not the other 99 containers.
Unless it steals the passphrase from ram from my little binary executable. Containers would have different keys but the same passphrase so it is only typed once, so keyloggers cannot steal it. If an SElinux setup makes it impossible to steal the passphrase from ram, that's what I need. But SElinux seems way too hard to set up. |
Does an SElinux live CD exist, with instructions for editing the live CD to add a browser, truecrypt-like software and ssh?
|
The best instructions I know are at: http://selinuxproject.org/page/Main_Page
and http://billauer.co.il/selinux-policy-module-howto.html No it isn't easy yet, but it is the most complete. |
Quote:
I can only guess that cryptsetup-luks or truecrypt do it in the right way, more research is required to be sure. I recommend not working with the passphrase in own scripts - you only add more copies of the passphrase, which are neither swap-protected nor sanitized after usage. You can call the crypto backend in your script and display it's password prompt, though. That way, your script process never keeps the passphrase in own memory. The key is another beast: It has to remain in memory the whole time the container is open, because encryption and decryption of blocks occur all the time. If your 100 containers are created independently (and not copied from each other), all of them have a different key and one compromised container does not compromise the others. That is, if it is compromised by getting the key. Some cues: Hardened Kernel grsecurity.net - Trusted Path execution, sanitize freed memory, AppArmor/SELinux Firefox with noscript addon, and webgl disabled in about:config ^That way it should be very, very difficult for code from the web to be even executed in the first place. Always keep the software up to date, best in a still supported long-term version. Especially browser and kernel. |
Thanks, and please have another look at my last edited post, the passphrase is held in ram in order to avoid typing it more than once which would expose it to a keylogger. It is needed because the keys generated from it are deliberately different for each container.
|
Ah sorry I did not notice this detail. But I think a keyfile instead of a passphrase would be a better option in that case. Maybe put the key file in a new container protected with an own passphrase. Once opened, the keyfile is accessible for the work with the 100 containers. Neither passphrase nor keyfile remain in application memory.
|
That's what you need to do: access is controlled by a unique, cryptographically-generated key. Use of the key, then, is controlled by a passphrase which must be used to decrypt the key. (Or, perhaps this latter step is optional.)
The host, perhaps using LDAP on its end for key-management, identifies each unique key and individually grants (or denies) access to each one. The host might know other things, such as the IP-address that the client will be coming from. In any case, you must possess both the key and the means to use it. If the client machine is compromised, the specific key that it is known to have held is promptly revoked by the host. (When "Eve" tries to use the now no-good key thereafter, you'll also know where she's coming from, and that it must be Eve.) |
Thing is, we do not trust any remote host. This is why client-side encryption is preferred.
We do not trust our client either, once it has been infected. Hopefully part of the client can be protected, ie most of the 100 containers and the passphrase that opens them all. |
Quote:
|
Malware cannot log keystrokes because you never type passphrase with malware loaded, only when you boot the live CD, and the live CD has been edited to never allow internet access before the passphrase has been typed.
|
Quote:
|
Maybe the live CD can be made in a live CD session.
|
Quote:
I'm mostly concerned about keeping the password in a bash variable, then they could use strace to find it because bash isn't designed to be particularly secure with its variables. |
Quote:
Also, if I'm understanding you right, then all you need to do is use memset to zero out the variables in your little binary executable that contain the password, right after your executable opens the container. |
They won't steal the passphrase but they will steal all the data, if it's only one container.
If it's more than one container, with different keys each container, then the passphrase has to stay in ram or you type it over and over every time you open yet another container. You want to work with 3 containers, say, in a live CD session, out of 100, so only these 3 are exposed to spying malware. |
Quote:
|
But that is exposing the passphrase to keyloggers we said.
|
Quote:
Code:
gksudo -u browseruser Both cryptsetup-luks and truecrypt can use keyfiles instead of passphrases or in addition to passphrases. |
Good idea, running the browser with another user account so as to hide the keyfile from malware coming from the browser.
We can do even better than that it seems with SELinux, otherwise it would not have been invented. |
Yes, SELINUX is probably even better if configured right. Though it needs more research to configure it right.
|
All times are GMT -5. The time now is 05:30 PM. |