Having machines in a network that is only reachable through an intermediate machine (e.g. a firewall) can make using ssh less comfortable. When using VPN or changing the network layout is not an option - the ssh ProxyCommand option can help. The result is being able to connect to hosts with one command through the intermediate machine. This also enables using rsync or versioning systems over ssh which otherwise wouldn’t work directly.
The intermediate machine is named “intermediate” and the target machine (which is in the not directly reachable network) “target”. The ~/.ssh/config entries should look like this:
So when you execute:
An ssh connection to “intermediate” is opened. netcat is started on “intermediate” to forward the ssh session to “target”. nc -w sets a connection timeout, this should make sure that “intermediate” doesn’t run abandoned nc processes. ssh -e none disables escape chars, they are not useful in this case and can only cause problems.
One of my iCTF challenges was a simple JavaScript obfuscation, a backup of the code is available here. What happens is obvious, window.alert is triggered with the message “why?”. “Why” is less obvious since the code was encoded with jjencode. There are no other visible hints.
To further look into window.alert, we can overwrite the function:
After re-running the code we see that window.alert is not being called with a String as argument, but with an object which contains the attribute:
Although it is generally discouraged to share a shell account with multiple users, sometimes its necessary. When I recently had to share a login I wanted to recreate my personalized environment, but then again not mess with other peoples environment. Also I wanted to preferably create something they could use for themselves without messing in turn my environment up (for example by configuring emacs as the default text editor). I wanted to have my own .bash_history file, load my own .vimrc etc. I used Debian 6.0 with current ssh/sshd versions.
Overview
What I did was exporting an LC_* environment variable on the client machine; those get forwarded by the ssh client to the server. On the server I would check in the .bashrc file whether the variable was set, if it was set I would load the custom configuration files. Any of the users who share the account are then able to configure the server environment for themselves.
Implementation
I added this line to ~/.bashrc
.....
export LC_USER=michael
.....
Don't forget to source the .bashrc file after it was edited, otherwise it will have no effect in the active session, this can be done with
$ source ~/.bashrc
You should have SendEnv set to forward the LC_* variables (this is usually enabled). This can be done in either the global ssh config /etc/ssh/ssh_config or the user ssh config: ~/.ssh/config
....
SendEnv LANG LC_*
....
On the server where you want to connect to, the file /etc/ssh/sshd_config should have the following option enabled (this is often enabled by default)
....
AcceptEnv LANG LC_*
....
To verify, ssh into the target machine and try this, the result should be similar. If you get no response check whether the variable was even exported locally (use the same command).
$ env | grep LC_
LC_USER=michael
Once this is done, upload your personalized .bashrc file to the remote server into ~/.yourusername/.bashrc .
Finally edit the ~/.bashrc file on the server so it sources the new custom file:
if [ `expr match "$LC_USER" '^[a-zA-Z0-9]\+$'` -gt 0 ] ;
then
echo "Welcome ${LC_USER}"
source ~/.${LC_USER}/.bashrc
fi
To keep a personal .bash_history and .vimrc file, put the following into the personal .bashrc file (don't forget to upload your .vimrc file into ~/.${LC_USER}).
HISTFILE=./.bash_history
alias vim='vim -u ~/.${LC_USER}/.vimrc'
Conclusion
This proved to be a noninvasive and reliable way to share accounts with custom configurations. Other ways to solve this problem might have been the usage of IP addresses. I looked into this first, but then decided that its not very good since connecting through intermediate machines would render discrimination of users impossible.
This is a writeup of the PlaidCTF 500 pts challenge “Fun with Firewire”.
Introduction
Given is a memory dump (128 MB) of a running Windows XP SP3 machine as well as a 32 MB file containing random data (a TrueCrypt volume image, according to the problem description). The memory dump was supposedly extracted via the Firewire port: The Firewire specification allows devices to have full DMA access. This allows forensic analysts (or a malicious hacker) to plug into any running computer that has a Firewire port and gain full access to the machine within seconds. Papers describing the attack and tools can be found at http://www.hermann-uwe.de/blog/physical-memory-attacks-via-firewire-dma-part-1-overview-and-mitigation. A different way to get a dump of the memory would be to conduct a “cold boot attack” as described in this paper.
Overview
To get an overview of the memory dump we inspect it with volatility. We see that TrueCrypt was running at the moment the dump was taken … good.
Further inspection of the memory dump reveals that the Operating System is Windows XP SP3, and the latest version of TrueCrypt (7.0a) is used. We reconstruct the setup by launching a VirtualBox installation, and we extract the memory using Mantech Memory Dumper mdd http://sourceforge.net/projects/mdd/. TrueCrypt offers the possibility to cache the passwords for mounting encrypted volumes. Comparing different memory dumps let us conclude that password caching was not enabled in the TrueCrypt software.
We briefly summarize the relevant technical details of TrueCrypt. More information can be found at http://www.truecrypt.org/docs/. In order to mount an encrypted volume, TrueCrypt uses the password and/or one or more key-files in order to decrypt the header (first 512 bytes of the volume). If the header gets correctly decrypted (a magic cookie is found), TrueCrypt reads the configuration (encryption algorithm and mode, etc.) as well as the master and secondary key into memory, and safely overwrites the memory regions where the password / key-file location was stored. The extracted master and secondary key is used for any further encryption and decryption of data. Since the data is encrypted and decrypted on the fly, these keys remain in memory. (Note that recent papers suggest storing the keys in CPU registers, more specifically in SSE registers http://portal.acm.org/citation.cfm?id=1752053 or in MSR registers http://arxiv.org/abs/1104.4843 instead of in the RAM in order to mitigate against these attacks.).
The default cipher used by TrueCrypt is AES in XTS mode which uses two 256 Bit AES-keys. We have to locate these keys in the memory dump. One option would be to analyze the data-structures and locate the memory region where TrueCrypt stores the keys.
But it is easier to use a generic approach to locate AES keys since a tool for that task was already written for the “cold boot attack” research: AESKeyFinder.
Once we have the right keys, we replace the header of the encrypted volume with the header of an identical volume which we created and where we set the password (so that TrueCrypt starts the mounting process correctly), but have TrueCrypt patched so that it uses the extracted keys from the memory dump instead of the ones from the newly generated header.
Finding the keys
AESKeyFinder inspects memory dumps (or actually any kind of files) and performs a simple heuristic to estimate entropy. The tool targets the expanded AES keys and tests whether a contiguous region in memory satisfies the constraints of a valid AES key schedule https://secure.wikimedia.org/wikipedia/en/wiki/Rijndael_key_schedule.
So we run the tool in verbose mode:
The “constraint on rows”-output tells us that the expanded keys are valid according to the AES key schedule. If we had bit errors in the respective memory regions (likely in cold boot attacks), not all constraints would have been met and AESKeyFinder would have calculated a guess for the original valid key.
So we have three keys after only a few of seconds of runtime - so far so good.
The entropy of (3) is really low, and we can definitely exclude it if we assume TrueCrypt is not totaly broken. This is good news since we have exactly two remaining 256-bit AES keys, as used by TrueCrypt in default configuration (AES in XTR mode).
Patching TrueCrypt
Next we read the source of TrueCrypt. Remember that TrueCrypt first decrypts the header with the password, and then reads the AES-key from the decrypted header. Reading in the header is done in Volume/VolumeHeader.cpp:VolumeHeader::Deserialize(.,.,.). We patch the code there, right after the master and secondary key was read from the decrypted header, and replace it with the hard-coded key value we found in the previous step. Our quick and dirty patch looks as follows:
Mounting the Volume
In order for TrueCrypt to reach the patched code it must first correctly decrypt a valid header. So we copy the header from an identically sized TrueCrypt volume configured with the default parameters:
and open ppp.challenge.vol with the patched TrueCrypt software and find the file KEY.TXT in the correctly decrypted volume.
Summary
This was a really nice challenge letting us explore TrueCrypt internals. If you think this is too complicated - you are right. You can also solve the challenge with available tools.
People involved in solving this challenge: Clemens Hlauschek, Michael Weissbacher