command_wget: fix artifacts (#693)

* command_wget: fix artifacts
This commit is contained in:
fe7ch
2018-03-15 07:54:03 +03:00
committed by Michel Oosterhof
parent f549510c14
commit 49be876532
2 changed files with 53 additions and 57 deletions

View File

@ -19,6 +19,7 @@ from twisted.python import log, compat
from cowrie.shell.honeypot import HoneyPotCommand
from cowrie.shell.fs import *
from cowrie.core.artifact import Artifact
from cowrie.core.config import CONFIG
"""
@ -120,6 +121,7 @@ class command_wget(HoneyPotCommand):
if not path or not self.fs.exists(path) or not self.fs.isdir(path):
self.errorWrite('wget: %s: Cannot open: No such file or directory\n' % outfile)
self.exit()
return
self.url = url
@ -128,9 +130,8 @@ class command_wget(HoneyPotCommand):
self.limit_size = CONFIG.getint('honeypot', 'download_limit_size')
self.downloadPath = CONFIG.get('honeypot', 'download_path')
self.artifactFile = tempfile.NamedTemporaryFile(dir=self.downloadPath, delete=False)
self.artifactFile = Artifact(outfile)
# HTTPDownloader will close() the file object so need to preserve the name
self.artifactName = self.artifactFile.name
d = self.download(url, outfile, self.artifactFile)
if d:
@ -139,7 +140,6 @@ class command_wget(HoneyPotCommand):
else:
self.exit()
def download(self, url, fakeoutfile, outputfile, *args, **kwargs):
"""
url - URL to download
@ -182,49 +182,42 @@ class command_wget(HoneyPotCommand):
return factory.deferred
def handle_CTRL_C(self):
"""
"""
self.errorWrite('^C\n')
self.connection.transport.loseConnection()
def success(self, data, outfile):
"""
"""
if not os.path.isfile(self.artifactName):
log.msg("there's no file " + self.artifactName)
if not os.path.isfile(self.artifactFile.shasumFilename):
log.msg("there's no file " + self.artifactFile.shasumFilename)
self.exit()
with open(self.artifactName, 'rb') as f:
filedata = f.read()
shasum = hashlib.sha256(filedata).hexdigest()
hash_path = os.path.join(self.downloadPath, shasum)
# Rename temp file to the hash
if not os.path.exists(hash_path):
os.rename(self.artifactName, hash_path)
unique = True
else:
os.remove(self.artifactName)
log.msg("Not storing duplicate content " + shasum)
unique = False
# log to cowrie.log
log.msg(format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s',
url=self.url,
outfile=self.artifactFile.shasumFilename,
shasum=self.artifactFile.shasum)
# log to output modules
self.protocol.logDispatch(eventid='cowrie.session.file_download',
format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s',
url=self.url, outfile=hash_path, shasum=shasum, unique=unique)
format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s',
url=self.url,
outfile=self.artifactFile.shasumFilename,
shasum=self.artifactFile.shasum)
# Update honeyfs to point to downloaded file or write to screen
if outfile != '-':
self.fs.update_realfile(self.fs.getfile(outfile), hash_path)
self.fs.update_realfile(self.fs.getfile(outfile), self.artifactFile.shasumFilename)
self.fs.chown(outfile, self.protocol.user.uid, self.protocol.user.gid)
else:
self.write(filedata)
with open(self.artifactFile.shasumFilename, 'rb') as f:
self.write(f.read())
self.exit()
def error(self, error, url):
"""
"""
@ -233,14 +226,22 @@ class command_wget(HoneyPotCommand):
self.errorWrite(errorMessage + '\n')
# Real wget also adds this:
if hasattr(error, 'webStatus') and hasattr(error, 'webMessage'): # exceptions
self.errorWrite('{} ERROR {}: {}\n'.format(time.strftime('%Y-%m-%d %T'), error.webStatus.decode(), error.webMessage.decode()))
self.errorWrite('{} ERROR {}: {}\n'.format(time.strftime('%Y-%m-%d %T'), error.webStatus.decode(),
error.webMessage.decode()))
else:
self.errorWrite('{} ERROR 404: Not Found.\n'.format(time.strftime('%Y-%m-%d %T')))
self.protocol.logDispatch(eventid='cowrie.session.file_download.failed',
format='Attempt to download file(s) from URL (%(url)s) failed',
url=self.url)
# prevent cowrie from crashing if the terminal have been already destroyed
try:
self.protocol.logDispatch(eventid='cowrie.session.file_download.failed',
format='Attempt to download file(s) from URL (%(url)s) failed',
url=self.url)
except:
pass
self.exit()
commands['/usr/bin/wget'] = command_wget
commands['/usr/bin/dget'] = command_wget
@ -258,7 +259,6 @@ class HTTPProgressDownloader(client.HTTPDownloader):
self.nomore = False
self.quiet = self.wget.quiet
def noPage(self, reason): # Called for non-200 responses
"""
"""
@ -272,7 +272,6 @@ class HTTPProgressDownloader(client.HTTPDownloader):
client.HTTPDownloader.noPage(self, reason)
def gotHeaders(self, headers):
"""
"""
@ -292,9 +291,9 @@ class HTTPProgressDownloader(client.HTTPDownloader):
if self.totallength > 0:
if not self.quiet:
self.wget.errorWrite('Length: %d (%s) [%s]\n' % \
(self.totallength,
sizeof_fmt(self.totallength),
self.contenttype))
(self.totallength,
sizeof_fmt(self.totallength),
self.contenttype))
else:
if not self.quiet:
self.wget.errorWrite('Length: unspecified [{}]\n'.format(self.contenttype))
@ -309,7 +308,6 @@ class HTTPProgressDownloader(client.HTTPDownloader):
return client.HTTPDownloader.gotHeaders(self, headers)
def pagePart(self, data):
"""
"""
@ -348,17 +346,17 @@ class HTTPProgressDownloader(client.HTTPDownloader):
if self.totallength != 0 and self.currentlength != self.totallength:
return client.HTTPDownloader.pageEnd(self)
if not self.quiet:
self.wget.errorWrite('\r100%%[%s] %s %dK/s' % \
('%s>' % (38 * '='),
splitthousands(str(int(self.totallength))).ljust(12),
self.speed / 1000))
self.wget.errorWrite('\r100%%[%s] %s %dK/s' %
('%s>' % (38 * '='),
splitthousands(str(int(self.totallength))).ljust(12),
self.speed / 1000))
self.wget.errorWrite('\n\n')
self.wget.errorWrite(
'%s (%d KB/s) - `%s\' saved [%d/%d]\n\n' % \
'%s (%d KB/s) - `%s\' saved [%d/%d]\n\n' %
(time.strftime('%Y-%m-%d %H:%M:%S'),
self.speed / 1000,
self.fakeoutfile, self.currentlength, self.totallength))
self.wget.fs.mkfile(self.fakeoutfile, 0, 0, self.totallength, 33188)
if self.fakeoutfile != '-':
self.wget.fs.mkfile(self.fakeoutfile, 0, 0, self.totallength, 33188)
return client.HTTPDownloader.pageEnd(self)

View File

@ -24,14 +24,13 @@ from __future__ import division, absolute_import
import hashlib
import os
import re
import time
import tempfile
from twisted.python import log
from cowrie.core.config import CONFIG
class Artifact:
"""
"""
@ -45,6 +44,8 @@ class Artifact:
self.fp = tempfile.NamedTemporaryFile(dir=self.artifactDir, delete=False)
self.tempFilename = self.fp.name
self.shasum = ''
self.shasumFilename = ''
def __enter__(self):
"""
@ -75,26 +76,23 @@ class Artifact:
"""
size = self.fp.tell()
self.fp.seek(0)
shasum = hashlib.sha256(self.fp.read()).hexdigest()
data = self.fp.read()
self.fp.close()
shasumFilename = self.artifactDir + "/" + shasum
self.shasum = hashlib.sha256(data).hexdigest()
self.shasumFilename = os.path.join(self.artifactDir, self.shasum)
if size == 0 and keepEmpty == False:
if size == 0 and not keepEmpty:
log.msg("Not storing empty file")
os.remove(self.fp.name)
elif os.path.exists(shasumFilename):
elif os.path.exists(self.shasumFilename):
log.msg("Not storing duplicate content " + self.shasum)
os.remove(self.fp.name)
else:
os.rename(self.fp.name, shasumFilename)
os.rename(self.fp.name, self.shasumFilename)
umask = os.umask(0)
os.umask(umask)
os.chmod(shasumFilename, 0o666 & ~umask)
os.chmod(self.shasumFilename, 0o666 & ~umask)
# if size>0:
# linkName = self.artifactDir + "/" \
# + time.strftime('%Y%m%dT%H%M%S') \
# + "_" + re.sub('[^-A-Za-z0-9]', '_', self.label)
# os.symlink(shasum, linkName)
return shasum, shasumFilename
return self.shasum, self.shasumFilename