Finding differences in JavaScript programs with the help of parse trees

I’d like to present a quick and dirty solution to comparing two JavaScript programs that can’t be compared with a simple diff. This can be useful to check whether programs are mostly equal and can help in figuring out where these differences are. The result will be achieved by performing a makeshift parse tree comparison.

Tools that will be used:

  • Google Closure Compiler
  • a small Perl script
  • vimdiff

First, Google’s Closure Compiler will be used to generate the parse trees.

$ java -jar compiler.jar --print_tree --js original.js > original.tree.txt
$ java -jar compiler.jar --print_tree --js modified.js > modified.tree.txt

The sourcename attribute should be stripped from the resulting file. Actually for most comparisons I did it was sufficient to keep only the first word of each line. This script can be used to print only the first word, but preserve heading whitespace (whitespace should be kept to keep a better overview later):

# treestrip.pl
while (<>) {
    m/(^\W*\w+)\W*/;
    print $1."\n";
}

Next:

$ perl treestrip.pl < original.tree.txt > original.stripped.tree.txt
$ perl treestrip.pl < modified.tree.txt > modified.stripped.tree.txt

Finally the stripped down parse trees can be compared with vimdiff. The iwhite option makes vimdiff ignore differences in whitespace:

$ vimdiff -c 'set diffopt+=iwhite' original.stripped.tree.txt modified.stripped.tree.txt

Suspicious blocks can be traced back to the parse tree before it was stripped (same line number). From there the surrounding function or variable names will lead back to the code in the JavaScript file.

Connecting seamlessly with ssh through intermediate hosts

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:

Host intermediate
   Hostname 192.168.1.1
....
Host target
    ProxyCommand ssh -e none intermediate exec nc -w 1000 %h %p
....

So when you execute:

$ ssh target

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.

iCTF 2011 challenge 15 writeup (150 points)

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:

window.alert = function(e) { console.log(JSON.stringify(e)); };

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:

{"secret":"Angelina Jolie's only good movie, in leet speak, reverse is the key"}

The solution is obviously: Hackers.

FYI: Before the obfuscation the code looked like this:

var obj = { };
obj.secret = "Angelina Jolie's only good movie, in leet speak, reverse is the key";
obj.toString = function(e) { return "why?"; };
obj.toSource = function(e) { return "function toSource() {\n" +
"    [native code]\n" +
"}\n"
};
window.alert(obj);

Personalizing shell accounts that are used by multiple users

Problem description

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.

iCTF challenge animation

Now that the iCTF is over I wanted to get a better overview over how the challenges got solved. I made a little animation that can be found here.

ictf animation