Merge branch 'pr/LauchieHarvey/3031' into port-tests
This commit is contained in:
@@ -105,6 +105,99 @@ module BeEF
|
||||
{ 'success' => false, 'error' => e.message }
|
||||
end
|
||||
|
||||
# Update an ARE rule set.
|
||||
# @param [Hash] ARE rule ID.
|
||||
# @param [Hash] ARE ruleset as JSON
|
||||
# @return [Hash] {"success": Boolean, "rule_id": Integer, "error": String}
|
||||
def update_rule_json(id, data)
|
||||
# Quite similar in implementation to load_rule_json. Might benefit from a refactor.
|
||||
name = data['name'] || ''
|
||||
author = data['author'] || ''
|
||||
browser = data['browser'] || 'ALL'
|
||||
browser_version = data['browser_version'] || 'ALL'
|
||||
os = data['os'] || 'ALL'
|
||||
os_version = data['os_version'] || 'ALL'
|
||||
modules = data['modules']
|
||||
execution_order = data['execution_order']
|
||||
execution_delay = data['execution_delay']
|
||||
chain_mode = data['chain_mode'] || 'sequential'
|
||||
|
||||
begin
|
||||
BeEF::Core::AutorunEngine::Parser.instance.parse(
|
||||
name,
|
||||
author,
|
||||
browser,
|
||||
browser_version,
|
||||
os,
|
||||
os_version,
|
||||
modules,
|
||||
execution_order,
|
||||
execution_delay,
|
||||
chain_mode
|
||||
)
|
||||
rescue => e
|
||||
print_error("[ARE] Error updating ruleset (#{name}): #{e.message}")
|
||||
return { 'success' => false, 'error' => e.message }
|
||||
end
|
||||
|
||||
existing_rule = BeEF::Core::Models::Rule.where(
|
||||
name: name,
|
||||
author: author,
|
||||
browser: browser,
|
||||
browser_version: browser_version,
|
||||
os: os,
|
||||
os_version: os_version,
|
||||
modules: modules.to_json,
|
||||
execution_order: execution_order.to_s,
|
||||
execution_delay: execution_delay.to_s,
|
||||
chain_mode: chain_mode
|
||||
).first
|
||||
|
||||
unless existing_rule.nil?
|
||||
msg = "Duplicate rule already exists in the database (ID: #{existing_rule.id})"
|
||||
print_info("[ARE] Skipping ruleset (#{name}): #{msg}")
|
||||
return { 'success' => false, 'error' => msg }
|
||||
end
|
||||
old_are_rule = BeEF::Core::Models::Rule.find_by(id: id)
|
||||
|
||||
old_are_rule.update(
|
||||
name: name,
|
||||
author: author,
|
||||
browser: browser,
|
||||
browser_version: browser_version,
|
||||
os: os,
|
||||
os_version: os_version,
|
||||
modules: modules.to_json,
|
||||
execution_order: execution_order.to_s,
|
||||
execution_delay: execution_delay.to_s,
|
||||
chain_mode: chain_mode
|
||||
)
|
||||
|
||||
print_info("[ARE] Ruleset (#{name}) updated successfully.")
|
||||
|
||||
if @debug_on
|
||||
print_more "Target Browser: #{browser} (#{browser_version})"
|
||||
print_more "Target OS: #{os} (#{os_version})"
|
||||
print_more 'Modules to run:'
|
||||
modules.each do |mod|
|
||||
print_more "(*) Name: #{mod['name']}"
|
||||
print_more "(*) Condition: #{mod['condition']}"
|
||||
print_more "(*) Code: #{mod['code']}"
|
||||
print_more '(*) Options:'
|
||||
mod['options'].each do |key, value|
|
||||
print_more "\t#{key}: (#{value})"
|
||||
end
|
||||
end
|
||||
print_more "Exec order: #{execution_order}"
|
||||
print_more "Exec delay: #{exec_delay}"
|
||||
end
|
||||
|
||||
{ 'success' => true }
|
||||
rescue TypeError, ArgumentError => e
|
||||
print_error("[ARE] Failed to update ruleset (#{name}): #{e.message}")
|
||||
{ 'success' => false, 'error' => e.message }
|
||||
end
|
||||
|
||||
# Load an ARE ruleset from file
|
||||
# @param [String] JSON ARE ruleset file path
|
||||
def load_rule_file(json_rule_path)
|
||||
|
||||
@@ -84,6 +84,26 @@ module BeEF
|
||||
{ 'success' => false, 'error' => e.message }.to_json
|
||||
end
|
||||
|
||||
#
|
||||
# Update a ruleset
|
||||
#
|
||||
patch '/rule/:rule_id' do
|
||||
rule_id = params[:rule_id]
|
||||
rule = BeEF::Core::Models::Rule.find(rule_id)
|
||||
raise InvalidParameterError, 'id' if rule.nil?
|
||||
data = JSON.parse request.body.read
|
||||
rloader = BeEF::Core::AutorunEngine::RuleLoader.instance
|
||||
rloader.update_rule_json(rule_id, data)
|
||||
|
||||
{ 'success' => true }.to_json
|
||||
rescue InvalidParameterError => e
|
||||
print_error e.message
|
||||
halt 400
|
||||
rescue StandardError => e
|
||||
print_error "Internal error while updating Autorun rule: #{e.message}"
|
||||
{ 'success' => false, 'error' => e.message }.to_json
|
||||
end
|
||||
|
||||
#
|
||||
# Run a specified rule on all online hooked browsers (if the zombie matches the rule).
|
||||
# Offline hooked browsers are ignored
|
||||
|
||||
@@ -25,21 +25,20 @@ module BeEF
|
||||
get '/' do
|
||||
mods = BeEF::Core::Models::CommandModule.all
|
||||
|
||||
mods_hash = {}
|
||||
i = 0
|
||||
mods_array = []
|
||||
|
||||
mods.each do |mod|
|
||||
modk = BeEF::Module.get_key_by_database_id(mod.id)
|
||||
next unless BeEF::Module.is_enabled(modk)
|
||||
|
||||
mods_hash[i] = {
|
||||
mods_array << {
|
||||
'id' => mod.id,
|
||||
'class' => config.get("beef.module.#{modk}.class"),
|
||||
'name' => config.get("beef.module.#{modk}.name"),
|
||||
'category' => config.get("beef.module.#{modk}.category")
|
||||
}
|
||||
i += 1
|
||||
end
|
||||
mods_hash.to_json
|
||||
mods_array.to_json
|
||||
end
|
||||
|
||||
get '/search/:mod_name' do
|
||||
|
||||
@@ -90,6 +90,9 @@ module BeEF
|
||||
ui/panel/tabs/ZombieTabRTC.js
|
||||
ui/panel/Logout.js
|
||||
ui/panel/WelcomeTab.js
|
||||
ui/panel/AutoRunTab.js
|
||||
ui/panel/AutoRunRuleForm.js
|
||||
ui/panel/AutoRunModuleForm.js
|
||||
ui/panel/ModuleSearching.js
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
|
||||
loadModuleInfo = async function(token, moduleId, moduleName) {
|
||||
try {
|
||||
// If all we have is the name then we need to get the ID first.
|
||||
if (moduleId === undefined) {
|
||||
const searchResponse = await fetch(`/api/modules/search/${moduleName}?token=${token}`);
|
||||
if (!searchResponse.ok) {
|
||||
throw new Error(`Getting auto run rules failed with status ${searchResponse.status}`);
|
||||
}
|
||||
const searchData = await searchResponse.json();
|
||||
if (typeof searchData.id === 'number') {
|
||||
moduleId = searchData.id;
|
||||
} else {
|
||||
throw new Error("Searching module name failed.");
|
||||
}
|
||||
}
|
||||
|
||||
const infoResponse = await fetch(`/api/modules/${moduleId}?token=${token}`);
|
||||
const infoData = await infoResponse.json();
|
||||
if (!infoData) {
|
||||
throw new Error(`Module with name ${moduleName} and ID ${moduleId} couldn't be retrived.`);
|
||||
}
|
||||
// Set the module Id incase we need it later.
|
||||
infoData.id = moduleId;
|
||||
return infoData;
|
||||
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
console.error("Failed to get module information.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Form that displays fields for a module.
|
||||
*
|
||||
* moduleData: The object definition of this moduleData from the Auto Run Engine.
|
||||
* deleteFn: callback function to delete this moduleData.
|
||||
* moveUp: moves the module up one spot in the Auto Run execution order.
|
||||
* moveDown: moves the module down one spot in the Auto Run exection order.
|
||||
*/
|
||||
AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, index, moduleList) {
|
||||
const moduleTextAreaId = `rule-${ruleId}-module-textarea-${index}`;
|
||||
const chainModeComboId = `rule-${ruleId}-module-combo-${index}`;
|
||||
const token = BeefWUI.get_rest_token();
|
||||
|
||||
const comboStore = new Ext.data.Store({
|
||||
data: moduleList,
|
||||
reader: new Ext.data.JsonReader({
|
||||
fields: ['id', 'name'],
|
||||
}),
|
||||
proxy: new Ext.data.MemoryProxy(moduleList)
|
||||
});
|
||||
|
||||
const moduleSelect = new Ext.form.ComboBox({
|
||||
fieldLabel: 'Change Module',
|
||||
store: comboStore,
|
||||
queryMode: 'local',
|
||||
displayField: 'name',
|
||||
valueField: 'id',
|
||||
editable: false, // Disable manual editing of the field
|
||||
forceSelection: true, // Force selection from the list
|
||||
triggerAction: 'all',
|
||||
typeAhead: true,
|
||||
listeners: {
|
||||
select: async function(combo) {
|
||||
const selectedModuleId = combo.getValue()
|
||||
const moduleInfo = await loadModuleInfo(token, selectedModuleId, undefined);
|
||||
if (!moduleInfo) {
|
||||
console.error("Failed to load new module.");
|
||||
return;
|
||||
}
|
||||
// Update the module data to reflect the new module.
|
||||
moduleData.name = moduleInfo.name;
|
||||
moduleData.condition = moduleInfo.condition ? moduleInfo.condition : null;
|
||||
moduleData.options = {};
|
||||
for (let i = 0; i < moduleInfo.options.length; i++) {
|
||||
const newOption = moduleInfo.options[i];
|
||||
moduleData.options[newOption.name] = newOption.value ? newOption.value : '';
|
||||
}
|
||||
loadModule(moduleInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const moduleOptionsContainer = new Ext.Panel({
|
||||
title: `Module ${index + 1}`,
|
||||
tbar: [moduleSelect],
|
||||
layout: 'form',
|
||||
border: false,
|
||||
listeners: {
|
||||
afterrender: function() {loadModule(undefined)}
|
||||
}
|
||||
});
|
||||
|
||||
async function loadModule(moduleInfo) {
|
||||
if (!moduleInfo)
|
||||
moduleInfo = await loadModuleInfo(token, undefined, moduleData.name);
|
||||
if (!moduleInfo) {
|
||||
moduleOptionsContainer.update("<p>Failed to load module information.</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the combobox default value to be this module.
|
||||
// Can't use the moduleData name since it doesn't match the ID.
|
||||
moduleSelect.setValue(moduleInfo.id);
|
||||
|
||||
// Setup module form elements. Remove all incase we're switching from a different module.
|
||||
moduleOptionsContainer.removeAll();
|
||||
moduleOptionsContainer.add(new Ext.form.DisplayField({
|
||||
fieldLabel: 'Module Name',
|
||||
value: moduleInfo.name
|
||||
}))
|
||||
moduleOptionsContainer.add(new Ext.form.DisplayField({
|
||||
fieldLabel: 'Module Author',
|
||||
value: moduleInfo.author ? moduleInfo.author : 'anonymous'
|
||||
}))
|
||||
|
||||
for (let i = 0; i < moduleInfo.options.length; i++) {
|
||||
const inputField = generate_form_input_field(
|
||||
moduleOptionsContainer,
|
||||
moduleInfo.options[i],
|
||||
moduleData.options[moduleInfo.options[i].name],
|
||||
false,
|
||||
{session: `${moduleInfo.name}-module-${index}-field-${i}`}
|
||||
);
|
||||
// Ensure any changes to the element are reflected in the newRule object.
|
||||
// When the user saves the rule the whole newRule object will be saved,
|
||||
// including any changes made to these input fields.
|
||||
inputField.on('change', function(_inputF, newValue, oldValue) {
|
||||
moduleData.options[moduleInfo.options[i].name] = newValue;
|
||||
});
|
||||
|
||||
};
|
||||
moduleOptionsContainer.doLayout();
|
||||
}
|
||||
|
||||
const buttonContainer = new Ext.Container({
|
||||
layout: {
|
||||
type: 'hbox',
|
||||
pack: 'end',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
xtype: 'button',
|
||||
text: 'Delete',
|
||||
handler: deleteFn,
|
||||
},{
|
||||
xtype: 'button',
|
||||
text: 'Move Forward',
|
||||
handler: moveUp,
|
||||
disabled: moveUp == undefined,
|
||||
},{
|
||||
xtype: 'button',
|
||||
text: 'Move Back',
|
||||
handler: moveDown,
|
||||
disabled: moveDown == undefined,
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
AutoRunModuleForm.superclass.constructor.call(this, {
|
||||
items: [
|
||||
moduleOptionsContainer,
|
||||
buttonContainer
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
Ext.extend(AutoRunModuleForm, Ext.Container, {});
|
||||
181
extensions/admin_ui/media/javascript/ui/panel/AutoRunRuleForm.js
Normal file
181
extensions/admin_ui/media/javascript/ui/panel/AutoRunRuleForm.js
Normal file
@@ -0,0 +1,181 @@
|
||||
const areNotificationUpdateTest = {
|
||||
"name": "Display an alert-----",
|
||||
"author": "mgeeky",
|
||||
"modules": [
|
||||
{
|
||||
"name": "alert_dialog",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"text":"You've been BeEFed ;>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"execution_order": [0],
|
||||
"execution_delay": [0],
|
||||
"chain_mode": "nested-forward"
|
||||
};
|
||||
/**
|
||||
* Form for the user to read, update and delete a specific Auto Run rule.
|
||||
*
|
||||
* rule: The object definition of this rule from the Auto Run Engine.
|
||||
* modules: The list of all commands/modules that the user can choose from.
|
||||
* deleteFn: callback function to delete this rule.
|
||||
* updateFn: callback function to update this rule.
|
||||
*/
|
||||
AutoRunRuleForm = function(rule, modules, deleteFn, updateFn) {
|
||||
const self = this;
|
||||
const ruleTextFieldId = `rule-name-${rule.id}`;
|
||||
const chainModeComboId = `rule-chain-mode-${rule.id}`;
|
||||
const newRule = JSON.parse(JSON.stringify(rule));
|
||||
newRule.modules = JSON.parse(newRule['modules']);
|
||||
newRule.execution_delay = JSON.parse(newRule['execution_delay']);
|
||||
newRule.execution_order = JSON.parse(newRule['execution_order']);
|
||||
const moduleContainer = new Ext.Container({
|
||||
style: {
|
||||
padding: '10 10 10 10',
|
||||
},
|
||||
listeners: {
|
||||
afterrender: setupModuleForms
|
||||
}
|
||||
});
|
||||
|
||||
function reorderModule(index, direction) {
|
||||
// Rearrange modules into new order.
|
||||
const currentModule = newRule.modules[index];
|
||||
const newIndex = direction === 'back' ? index + 1 : index - 1;
|
||||
newRule.modules.splice(index, 1);
|
||||
newRule.modules.splice(newIndex, 0, currentModule);
|
||||
|
||||
// Update DOM.
|
||||
setupModuleForms();
|
||||
moduleContainer.doLayout();
|
||||
}
|
||||
|
||||
function removeModule(index) {
|
||||
// Remove element from execution_order and execution_delay arrays.
|
||||
newRule.modules.splice(index, 1);
|
||||
newRule.execution_delay.splice(index, 1);
|
||||
|
||||
// Update DOM.
|
||||
setupModuleForms();
|
||||
moduleContainer.doLayout();
|
||||
}
|
||||
|
||||
function addModule() {
|
||||
// New module is a copy of the last module.
|
||||
newRule.modules.push(newRule.modules[newRule.modules.length - 1]);
|
||||
newRule.execution_delay.push(newRule.execution_delay[newRule.execution_delay.length - 1]);
|
||||
|
||||
// Update DOM.
|
||||
setupModuleForms();
|
||||
moduleContainer.doLayout();
|
||||
}
|
||||
|
||||
function setupModuleForms() {
|
||||
|
||||
moduleContainer.removeAll(true);
|
||||
|
||||
// I think execution order should always be sequential.
|
||||
// The actual order comes from the modules array.
|
||||
for (let i = 0; i < newRule.modules.length; ++i) {
|
||||
const isFirstModule = i === 0;
|
||||
const isLastModule = i >= newRule.modules.length - 1;
|
||||
moduleContainer.add(new AutoRunModuleForm(
|
||||
newRule.modules[i],
|
||||
function() {removeModule(i)},
|
||||
isFirstModule ? undefined : function() {reorderModule(i, 'forward')},
|
||||
isLastModule ? undefined : function() {reorderModule(i, 'back')},
|
||||
rule.id,
|
||||
i,
|
||||
modules
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function handleUpdateRule() {
|
||||
// TODO: Need to overwrite module order.
|
||||
const form = self.getForm();
|
||||
const formValues = form.getValues();
|
||||
const updatedRule = {
|
||||
...newRule,
|
||||
name: formValues[ruleTextFieldId],
|
||||
chain_mode: formValues[chainModeComboId],
|
||||
execution_order: [...Array(newRule.modules.length).keys()],
|
||||
};
|
||||
updateFn(updatedRule);
|
||||
}
|
||||
|
||||
|
||||
AutoRunRuleForm.superclass.constructor.call(this, {
|
||||
padding:'10 10 10 10',
|
||||
title: `Rule ${rule.id}`,
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
id: ruleTextFieldId,
|
||||
value: rule.name ? rule.name : '',
|
||||
fieldLabel: 'Name',
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'Author',
|
||||
value: rule.author ? rule.author : 'anonymous',
|
||||
},{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'Browser(s)',
|
||||
value: rule.browser ? rule.browser : 'All',
|
||||
},{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'Browser version(s)',
|
||||
value: rule.browser_version ? rule.browser_version : 'All',
|
||||
},{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'OS(s)',
|
||||
value: rule.os ? rule.os : 'All',
|
||||
},{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'OS version(s)',
|
||||
value: rule.os_version ? rule.os_version : 'All',
|
||||
},
|
||||
moduleContainer,
|
||||
{
|
||||
xtype: 'button',
|
||||
text: 'Add Module',
|
||||
handler: addModule
|
||||
},
|
||||
{
|
||||
xtype: 'combo',
|
||||
id: chainModeComboId,
|
||||
fieldLabel: 'Chain Mode',
|
||||
store: ['sequential', 'nested-forward'],
|
||||
queryMode: 'local', // Use local data.
|
||||
triggerAction: 'all', // Show both options instead of just the default.
|
||||
editable: false, // Disable manual text input.
|
||||
forceSelection: true,
|
||||
value: rule.chain_mode ? rule.chain_mode : 'sequential'
|
||||
},{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'Execution Order',
|
||||
value: newRule.execution_order ?
|
||||
JSON.stringify(newRule.execution_order)
|
||||
: 'undefined',
|
||||
},{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'Execution Delay',
|
||||
value: newRule.execution_delay ?
|
||||
JSON.stringify(newRule.execution_delay)
|
||||
: 'undefined',
|
||||
}
|
||||
],
|
||||
buttons: [{
|
||||
text: 'Delete',
|
||||
handler: deleteFn
|
||||
}, {
|
||||
text: 'Save',
|
||||
handler: handleUpdateRule
|
||||
}],
|
||||
border: false,
|
||||
closable: false
|
||||
});
|
||||
};
|
||||
|
||||
Ext.extend(AutoRunRuleForm, Ext.FormPanel, {});
|
||||
185
extensions/admin_ui/media/javascript/ui/panel/AutoRunTab.js
Normal file
185
extensions/admin_ui/media/javascript/ui/panel/AutoRunTab.js
Normal file
@@ -0,0 +1,185 @@
|
||||
const defaultRule = {
|
||||
"name": "Display an alert",
|
||||
"author": "mgeeky",
|
||||
"modules": [
|
||||
{
|
||||
"name": "alert_dialog",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"text":"You've been BeEFed ;>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"execution_order": [0],
|
||||
"execution_delay": [0],
|
||||
"chain_mode": "nested-forward"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously returns the currently active rules in an array.
|
||||
* Empty array means no rules are active.
|
||||
* null if there was an error.
|
||||
*/
|
||||
getCurrentRules = async function(token) {
|
||||
|
||||
try {
|
||||
var res = await fetch(`/api/autorun/rules?token=${token}`);
|
||||
if (!res.ok) {
|
||||
throw new Error(`Getting auto run rules failed with status ${res.status}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
const rules = JSON.parse(data.rules);
|
||||
|
||||
if (data.success === true && Array.isArray(rules)) {
|
||||
return rules;
|
||||
}
|
||||
|
||||
console.log("No active auto run rules.");
|
||||
return [];
|
||||
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
console.error("Failed to get auto run rules.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
getModules = async function(token) {
|
||||
try {
|
||||
var res = await fetch(`/api/modules?token=${token}`);
|
||||
if (!res.ok) {
|
||||
throw new Error(`Getting auto run rules failed with status ${res.status}`);
|
||||
}
|
||||
const modules = await res.json();
|
||||
|
||||
return modules;
|
||||
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
console.error("Failed to get auto run rules.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
AutoRunTab = function() {
|
||||
// RESTful API token.
|
||||
var token = BeefWUI.get_rest_token();
|
||||
|
||||
// Heading container to describe general Auto Run state.
|
||||
var ruleLoadingState = new Ext.Container({
|
||||
html: "<p>Loading Auto Run rules...</p>",
|
||||
})
|
||||
var headingContainer = new Ext.Panel({
|
||||
style: {
|
||||
font: '11px tahoma,arial,helvetica,sans-serif'
|
||||
},
|
||||
padding:'10 10 10 10',
|
||||
border: false,
|
||||
items: [{
|
||||
xtype: 'container',
|
||||
html: '\
|
||||
<div>\
|
||||
<h4>Auto Run Rules</h4>\
|
||||
<p>These determine what commands run automatically when a browser is hooked.</p>\
|
||||
</div>'
|
||||
},
|
||||
ruleLoadingState,
|
||||
{
|
||||
xtype: 'button',
|
||||
text: 'Add New Rule',
|
||||
handler: addRule
|
||||
}],
|
||||
listeners: {
|
||||
afterrender: loadRules
|
||||
}
|
||||
});
|
||||
// Contains all of the rules and inputs to change each rule.
|
||||
var ruleContainer = new Ext.Panel({
|
||||
border: false,
|
||||
listeners: {
|
||||
afterrender: loadRules
|
||||
}
|
||||
});
|
||||
|
||||
async function deleteRule(id) {
|
||||
const res = await fetch(`/api/autorun/rule/${id}?token=${token}`, {method: 'DELETE'});
|
||||
if (!res.ok) {
|
||||
console.error(`Failed when deleting rule with id ${id}. Failed with status ${res.status}.`);
|
||||
return;
|
||||
}
|
||||
// Update the entire rules panel. Not very efficient.
|
||||
loadRules();
|
||||
}
|
||||
|
||||
async function addRule() {
|
||||
const res = await fetch(`/api/autorun/rule/add?token=${token}`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(defaultRule)
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.error(`Failed when adding a new rule with status ${res.status}.`);
|
||||
return;
|
||||
}
|
||||
// Update the entire rules panel. Not very efficient.
|
||||
loadRules();
|
||||
}
|
||||
|
||||
async function updateRule(id, newRuleData) {
|
||||
const res = await fetch(`/api/autorun/rule/${id}?token=${token}`, {
|
||||
method: 'PATCH',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(newRuleData)
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.error(`Failed when adding a new rule with status ${res.status}.`);
|
||||
return;
|
||||
}
|
||||
// Update the entire rules panel. Not very efficient.
|
||||
loadRules();
|
||||
}
|
||||
|
||||
async function loadRules() {
|
||||
let modules = [];
|
||||
let rules = [];
|
||||
try {
|
||||
modules = await getModules(token);
|
||||
rules = await getCurrentRules(token);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error("Failed to load command modules and/or rules for Auto Run.");
|
||||
ruleLoadingState.update("<p>Failed to load Auto Run rules.</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rules !== null) {
|
||||
ruleLoadingState.update(`<p>Loaded ${rules.length} Auto Run rules.</p>`);
|
||||
ruleContainer.removeAll();
|
||||
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
ruleForm = new AutoRunRuleForm(
|
||||
rules[i],
|
||||
modules,
|
||||
function() {deleteRule(rules[i].id)},
|
||||
function(newRuleData) {updateRule(rules[i].id, newRuleData)}
|
||||
);
|
||||
ruleContainer.add(ruleForm);
|
||||
}
|
||||
ruleContainer.doLayout();
|
||||
} else {
|
||||
ruleLoadingState.update("<p>Failed to load Auto Run rules.</p>");
|
||||
}
|
||||
}
|
||||
|
||||
AutoRunTab.superclass.constructor.call(this, {
|
||||
region: 'center',
|
||||
items: [headingContainer, ruleContainer],
|
||||
autoScroll: true,
|
||||
border: false,
|
||||
closable: false
|
||||
});
|
||||
};
|
||||
|
||||
Ext.extend(AutoRunTab, Ext.Panel, {});
|
||||
@@ -38,6 +38,8 @@ MainPanel = function(){
|
||||
|
||||
this.welcome_tab = new WelcomeTab;
|
||||
|
||||
this.auto_run_tab = new AutoRunTab;
|
||||
|
||||
MainPanel.superclass.constructor.call(this, {
|
||||
id:'main-tabs',
|
||||
activeTab:0,
|
||||
@@ -76,6 +78,15 @@ MainPanel = function(){
|
||||
items:[
|
||||
this.zombies_grid
|
||||
]
|
||||
},
|
||||
{
|
||||
id:'autorun-view',
|
||||
title:'Auto Run',
|
||||
layout:'border',
|
||||
hideMode:'offsets',
|
||||
items:[
|
||||
this.auto_run_tab
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
|
||||
@@ -102,9 +102,9 @@ function generate_form_input_field(form, input, value, disabled, zombie) {
|
||||
|
||||
if(value) input_field.setValue(value);
|
||||
if(disabled) input_field.setDisabled(true);
|
||||
|
||||
|
||||
form.add(input_field);
|
||||
|
||||
return input_field;
|
||||
};
|
||||
|
||||
function get_dynamic_payload_details(payload, zombie) {
|
||||
@@ -357,13 +357,13 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
fieldLabel: 'Description',
|
||||
fieldClass: 'command-module-panel-description',
|
||||
value: module.Description
|
||||
}),
|
||||
new Ext.form.DisplayField({
|
||||
name: 'command_module_id_visible',
|
||||
fieldLabel: 'Id',
|
||||
fieldClass: 'command-module-panel-description',
|
||||
value: command_module_id
|
||||
})
|
||||
}),
|
||||
new Ext.form.DisplayField({
|
||||
name: 'command_module_id_visible',
|
||||
fieldLabel: 'Id',
|
||||
fieldClass: 'command-module-panel-description',
|
||||
value: command_module_id
|
||||
})
|
||||
],
|
||||
|
||||
buttons:[{
|
||||
@@ -424,4 +424,4 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user