Added jwt requirements to PBA endpoints, fixed bugs, added different

display if PBA succeeded than if failed.
This commit is contained in:
VakarisZ 2019-03-14 17:53:05 +02:00
parent 92615b848d
commit be598d0953
14 changed files with 81 additions and 52 deletions

View File

@ -271,10 +271,10 @@ class Configuration(object):
extract_azure_creds = True
post_breach_actions = []
custom_pba_linux_cmd = ""
custom_pba_windows_cmd = ""
custom_pba_linux_file_info = None
custom_pba_windows_file_info = None
custom_PBA_linux_cmd = ""
custom_PBA_windows_cmd = ""
PBA_linux_filename = None
PBA_windows_filename = None
WormConfiguration = Configuration()

View File

@ -97,12 +97,5 @@
"use_file_logging": true,
"victims_max_exploit": 7,
"victims_max_find": 30,
"post_breach_actions" : [],
"custom_post_breach" : { "linux": "",
"windows": "",
"linux_file": None,
"windows_file": None,
"windows_file_info": None,
"linux_file_info": None
}
"post_breach_actions" : []
}

View File

@ -24,15 +24,15 @@ class FileExecution(PBA):
self.windows_filename = WormConfiguration.PBA_windows_filename
super(FileExecution, self).__init__("File execution", linux_command, windows_command)
def execute_linux(self):
def _execute_linux(self):
FileExecution.download_PBA_file(FileExecution.get_dest_dir(WormConfiguration, True),
self.linux_filename)
return super(FileExecution, self).execute_linux()
return super(FileExecution, self)._execute_linux()
def execute_win(self):
def _execute_win(self):
FileExecution.download_PBA_file(FileExecution.get_dest_dir(WormConfiguration, True),
self.windows_filename)
return super(FileExecution, self).execute_win()
return super(FileExecution, self)._execute_win()
def add_default_command(self, is_linux):
"""

View File

@ -36,7 +36,7 @@ class PBA(object):
if command:
hostname = socket.gethostname()
ControlClient.send_telemetry('post_breach', {'command': command,
'output': exec_funct(),
'result': exec_funct(),
'name': self.name,
'hostname': hostname,
'ip': socket.gethostbyname(hostname)
@ -46,18 +46,23 @@ class PBA(object):
"""
Default linux PBA execution function. Override it if additional functionality is needed
"""
self._execute_default(self.linux_command)
return self._execute_default(self.linux_command)
def _execute_win(self):
"""
Default linux PBA execution function. Override it if additional functionality is needed
"""
self._execute_default(self.windows_command)
return self._execute_default(self.windows_command)
@staticmethod
def _execute_default(command):
"""
Default post breach command execution routine
:param command: What command to execute
:return: Tuple of command's output string and boolean, indicating if it succeeded
"""
try:
return subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
return subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True), True
except subprocess.CalledProcessError as e:
# Return error output of the command
return e.output
return e.output, False

View File

@ -51,22 +51,22 @@ class PostBreach(object):
command_pba = PBA(name="Custom")
# Add linux commands to PBA's
if config['PBA_linux_filename']:
if config['custom_PBA_linux_cmd']:
file_pba.linux_command = config['custom_PBA_linux_cmd']
if config.PBA_linux_filename:
if config.custom_PBA_linux_cmd:
file_pba.linux_command = config.custom_PBA_linux_cmd
else:
file_pba.add_default_command(is_linux=True)
elif config['custom_PBA_linux_cmd']:
command_pba.linux_command = config['custom_PBA_linux_cmd']
elif config.custom_PBA_linux_cmd:
command_pba.linux_command = config.custom_PBA_linux_cmd
# Add windows commands to PBA's
if config['PBA_windows_filename']:
if config['custom_PBA_windows_cmd']:
file_pba.windows_command = config['custom_PBA_windows_cmd']
if config.PBA_windows_filename:
if config.custom_PBA_windows_cmd:
file_pba.windows_command = config.custom_PBA_windows_cmd
else:
file_pba.add_default_command(is_linux=False)
elif config['custom_PBA_windows_cmd']:
command_pba.windows_command = config['custom_PBA_windows_cmd']
elif config.custom_PBA_windows_cmd:
command_pba.windows_command = config.custom_PBA_windows_cmd
# Add PBA's to list
if file_pba.linux_command or file_pba.windows_command:

View File

@ -55,13 +55,13 @@ class FileUpload(flask_restful.Resource):
:param file_type: Type indicates which file was deleted, linux of windows
:return: Empty response
"""
file_conf_path = PBA_LINUX_FILENAME_PATH if file_type == 'PBAlinux' else PBA_WINDOWS_FILENAME_PATH
filename = ConfigService.get_config_value(file_conf_path)
filename_path = PBA_LINUX_FILENAME_PATH if file_type == 'PBAlinux' else PBA_WINDOWS_FILENAME_PATH
filename = ConfigService.get_config_value(filename_path)
file_path = os.path.join(UPLOADS_DIR, filename)
try:
if os.path.exists(file_path):
os.remove(file_path)
ConfigService.set_config_value(file_conf_path, {'size': '0', 'name': ''})
ConfigService.set_config_value(filename_path, '')
except OSError as e:
LOG.error("Can't remove previously uploaded post breach files: %s" % e)

View File

@ -4,9 +4,7 @@ import functools
import logging
from jsonschema import Draft4Validator, validators
from six import string_types
from werkzeug.utils import secure_filename
import os
import base64
from cc.database import mongo
from cc.encryptor import encryptor
@ -36,7 +34,7 @@ ENCRYPTED_CONFIG_STRINGS = \
['cnc', 'aws_config', 'aws_secret_access_key']
]
UPLOADS_DIR = '/cc/userUploads'
UPLOADS_DIR = 'monkey_island/cc/userUploads'
# Where to find file names in config
PBA_WINDOWS_FILENAME_PATH = ['monkey', 'behaviour', 'PBA_windows_filename']
@ -315,14 +313,12 @@ class ConfigService:
@staticmethod
def remove_PBA_files():
if ConfigService.get_config():
linux_file_name = ConfigService.get_config_value(
['monkey', 'behaviour', 'custom_post_breach', 'linux_file_info', 'name'])
windows_file_name = ConfigService.get_config_value(
['monkey', 'behaviour', 'custom_post_breach', 'windows_file_info', 'name'])
if linux_file_name:
ConfigService.remove_file(linux_file_name)
if windows_file_name:
ConfigService.remove_file(windows_file_name)
linux_filename = ConfigService.get_config_value(PBA_WINDOWS_FILENAME_PATH)
windows_filename = ConfigService.get_config_value(PBA_LINUX_FILENAME_PATH)
if linux_filename:
ConfigService.remove_file(linux_filename)
if windows_filename:
ConfigService.remove_file(windows_filename)
@staticmethod
def remove_file(file_name):

View File

@ -329,13 +329,13 @@ SCHEMA = {
"Reference your file by filename."
},
"custom_PBA_windows_cmd": {
"title": "Windows command",
"title": "Windows post breach command",
"type": "string",
"default": "",
"description": "Windows command to be executed after breaching."
},
"PBA_windows_file": {
"title": "Windows file",
"title": "Windows post breach file",
"type": "string",
"format": "data-url",
"description": "File to be executed after breaching. "

View File

@ -6,6 +6,7 @@ class AuthComponent extends React.Component {
super(props);
this.auth = new AuthService();
this.authFetch = this.auth.authFetch;
this.jwtHeader = this.auth.jwtHeader();
}
}

View File

@ -198,7 +198,13 @@ class ConfigurePageComponent extends AuthComponent {
PBAwindows = () => {
return (<FilePond
server='/api/fileUpload/PBAwindows'
server={{ url:'/api/fileUpload/PBAwindows',
process: {headers: {'Authorization': this.jwtHeader}},
revert: {headers: {'Authorization': this.jwtHeader}},
restore: {headers: {'Authorization': this.jwtHeader}},
load: {headers: {'Authorization': this.jwtHeader}},
fetch: {headers: {'Authorization': this.jwtHeader}}
}}
files={this.getWinPBAfile()}
onupdatefiles={fileItems => {
this.setState({
@ -211,7 +217,13 @@ class ConfigurePageComponent extends AuthComponent {
PBAlinux = () => {
return (<FilePond
server='/api/fileUpload/PBAlinux'
server={{ url:'/api/fileUpload/PBAlinux',
process: {headers: {'Authorization': this.jwtHeader}},
revert: {headers: {'Authorization': this.jwtHeader}},
restore: {headers: {'Authorization': this.jwtHeader}},
load: {headers: {'Authorization': this.jwtHeader}},
fetch: {headers: {'Authorization': this.jwtHeader}}
}}
files={this.getLinuxPBAfile()}
onupdatefiles={fileItems => {
this.setState({

View File

@ -13,9 +13,19 @@ let renderMachine = function (data) {
return <div>{data.label} ( {renderIpAddresses(data)} )</div>
};
let renderPbaResults = function (results) {
let pbaClass = "";
if (results[1]){
pbaClass="pba-success"
} else {
pbaClass="pba-danger"
}
return <div className={pbaClass}> {results[0]} </div>
};
const subColumns = [
{id: 'pba_name', Header: "Name", accessor: x => x.name, style: { 'white-space': 'unset' }},
{id: 'pba_output', Header: "Output", accessor: x => x.output, style: { 'white-space': 'unset' }}
{id: 'pba_output', Header: "Output", accessor: x => renderPbaResults(x.result), style: { 'white-space': 'unset' }}
];
let renderDetails = function (data) {

View File

@ -4,8 +4,6 @@ import ReactDOM from 'react-dom';
import 'babel-polyfill';
import App from './components/Main';
import Bootstrap from 'bootstrap/dist/css/bootstrap.css'; // eslint-disable-line no-unused-vars
import { FilePond, registerPlugin } from 'react-filepond';
import 'filepond/dist/filepond.min.css';
// Render the main component into the dom
ReactDOM.render(<App />, document.getElementById('app'));

View File

@ -15,6 +15,12 @@ export default class AuthService {
return this._authFetch(url, options);
};
jwtHeader = () => {
if (this._loggedIn()) {
return 'JWT ' + this._getToken();
}
};
hashSha3(text) {
let hash = new SHA3(512);
hash.update(text);

View File

@ -424,6 +424,14 @@ body {
top: 30%;
}
.pba-danger {
background-color: #ffc7af;
}
.pba-success {
background-color: #afd2a2;
}
/* Print report styling */
@media print {