Autorun UI elements now match command module elements.
This commit is contained in:
@@ -25,21 +25,20 @@ module BeEF
|
|||||||
get '/' do
|
get '/' do
|
||||||
mods = BeEF::Core::Models::CommandModule.all
|
mods = BeEF::Core::Models::CommandModule.all
|
||||||
|
|
||||||
mods_hash = {}
|
mods_array = []
|
||||||
i = 0
|
|
||||||
mods.each do |mod|
|
mods.each do |mod|
|
||||||
modk = BeEF::Module.get_key_by_database_id(mod.id)
|
modk = BeEF::Module.get_key_by_database_id(mod.id)
|
||||||
next unless BeEF::Module.is_enabled(modk)
|
next unless BeEF::Module.is_enabled(modk)
|
||||||
|
|
||||||
mods_hash[i] = {
|
mods_array << {
|
||||||
'id' => mod.id,
|
'id' => mod.id,
|
||||||
'class' => config.get("beef.module.#{modk}.class"),
|
'class' => config.get("beef.module.#{modk}.class"),
|
||||||
'name' => config.get("beef.module.#{modk}.name"),
|
'name' => config.get("beef.module.#{modk}.name"),
|
||||||
'category' => config.get("beef.module.#{modk}.category")
|
'category' => config.get("beef.module.#{modk}.category")
|
||||||
}
|
}
|
||||||
i += 1
|
|
||||||
end
|
end
|
||||||
mods_hash.to_json
|
mods_array.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/search/:mod_name' do
|
get '/search/:mod_name' do
|
||||||
|
|||||||
@@ -1,3 +1,38 @@
|
|||||||
|
|
||||||
|
loadModuleInfo = async function(token, moduleName) {
|
||||||
|
let moduleId = null;
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
console.log("Search data:");
|
||||||
|
console.log(searchData);
|
||||||
|
if (typeof searchData.id === 'number') {
|
||||||
|
moduleId = searchData.id;
|
||||||
|
} else {
|
||||||
|
throw new Error("Searching module name failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEBUG log
|
||||||
|
console.log(`Successfully retrieved module id for ${moduleName} = ${moduleId}`);
|
||||||
|
|
||||||
|
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.`);
|
||||||
|
}
|
||||||
|
return infoData;
|
||||||
|
|
||||||
|
} catch(error) {
|
||||||
|
console.error(error);
|
||||||
|
console.error("Failed to get module information.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form that displays fields for a module.
|
* Form that displays fields for a module.
|
||||||
*
|
*
|
||||||
@@ -9,22 +44,37 @@
|
|||||||
AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, index) {
|
AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, index) {
|
||||||
const moduleTextAreaId = `rule-${ruleId}-module-textarea-${index}`;
|
const moduleTextAreaId = `rule-${ruleId}-module-textarea-${index}`;
|
||||||
const chainModeComboId = `rule-${ruleId}-module-combo-${index}`;
|
const chainModeComboId = `rule-${ruleId}-module-combo-${index}`;
|
||||||
|
const token = BeefWUI.get_rest_token();
|
||||||
|
|
||||||
|
// TODO: Load in modules from ruby.
|
||||||
|
/*
|
||||||
|
const moduleSelect = new Ext.form.ComboBox({
|
||||||
|
fieldLabel: 'Command Module',
|
||||||
|
store: [{name: 'hi', id: 1}],
|
||||||
|
queryMode: 'local', // Set the queryMode to 'remote'
|
||||||
|
displayField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
editable: false, // Disable manual editing of the field
|
||||||
|
forceSelection: true, // Force selection from the list
|
||||||
|
//listeners: {
|
||||||
|
// render: function (combo) {
|
||||||
|
// combo.setValue(moduleData.name);
|
||||||
|
// },
|
||||||
|
// select: function(combo, newValue, oldValue) {
|
||||||
|
// if (newValue) {
|
||||||
|
// console.log("Combo value selected.");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
const moduleOptionsContainer = new Ext.Panel({
|
const moduleOptionsContainer = new Ext.Panel({
|
||||||
padding: '5 5 5 5',
|
title: `${moduleData.name}`,
|
||||||
border: false,
|
padding: '10 10 10 10',
|
||||||
layout: 'form',
|
layout: 'form',
|
||||||
items: [/*{
|
border: false,
|
||||||
xtype: 'combo',
|
items: [
|
||||||
id: chainModeComboId,
|
|
||||||
fieldLabel: 'Chain Mode',
|
|
||||||
store: ['moduleA', 'moduleB'], // TODO: Update this to the array of commands.
|
|
||||||
queryMode: 'local', // Use local data.
|
|
||||||
triggerAction: 'all', // Show both options instead of just the default.
|
|
||||||
editable: false, // Disable manual text input.
|
|
||||||
forceSelection: true,
|
|
||||||
value: moduleData.name,
|
|
||||||
},*/
|
|
||||||
{
|
{
|
||||||
xtype: 'displayfield',
|
xtype: 'displayfield',
|
||||||
fieldLabel: 'Module Name',
|
fieldLabel: 'Module Name',
|
||||||
@@ -35,23 +85,42 @@ AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, ind
|
|||||||
fieldLabel: 'Module Author',
|
fieldLabel: 'Module Author',
|
||||||
value: moduleData.author ? moduleData.author : 'anonymous',
|
value: moduleData.author ? moduleData.author : 'anonymous',
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
listeners: {
|
||||||
|
afterrender: loadModule
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadModule() {
|
|
||||||
|
async function loadModule() {
|
||||||
// TODO: Need to query module option types so that not everything is given a textfield.
|
// TODO: Need to query module option types so that not everything is given a textfield.
|
||||||
|
const moduleInfo = await loadModuleInfo(token, moduleData.name);
|
||||||
|
if (!moduleInfo) {
|
||||||
|
moduleOptionsContainer.update("<p>Failed to load module information.</p>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
console.log("Module data:");
|
console.log("Module data:");
|
||||||
console.log(moduleData);
|
console.log(moduleData);
|
||||||
for (key in moduleData.options) {
|
console.log("Module info:");
|
||||||
const value = moduleData.options[key];
|
console.log(JSON.stringify(moduleInfo, null, 2));
|
||||||
const inputField = new Ext.form.TextField({
|
console.log("Module options, should be an array:");
|
||||||
fieldLabel: key,
|
console.log(moduleInfo.options);
|
||||||
value: value ? value : '',
|
|
||||||
});
|
//genNewAutoRunModulePanel(moduleOptionsContainer, moduleInfo, ruleId);
|
||||||
moduleOptionsContainer.add(inputField);
|
|
||||||
|
for (let i = 0; i < moduleInfo.options.length; i++) {
|
||||||
|
console.log(JSON.stringify(moduleInfo.options[i], null, 2));
|
||||||
|
// TODO add real autorun module value by default.
|
||||||
|
generate_form_input_field(
|
||||||
|
moduleOptionsContainer,
|
||||||
|
moduleInfo.options[i],
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
{session: `${moduleInfo.name}-module-${index}-field-${i}`}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
moduleOptionsContainer.doLayout();
|
||||||
}
|
}
|
||||||
loadModule();
|
|
||||||
|
|
||||||
const buttonContainer = new Ext.Container({
|
const buttonContainer = new Ext.Container({
|
||||||
layout: {
|
layout: {
|
||||||
@@ -79,12 +148,12 @@ AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, ind
|
|||||||
|
|
||||||
|
|
||||||
AutoRunModuleForm.superclass.constructor.call(this, {
|
AutoRunModuleForm.superclass.constructor.call(this, {
|
||||||
padding: '10 10 10 10',
|
|
||||||
closable: false,
|
|
||||||
items: [
|
items: [
|
||||||
|
//moduleSelect,
|
||||||
moduleOptionsContainer,
|
moduleOptionsContainer,
|
||||||
buttonContainer
|
buttonContainer
|
||||||
]});
|
]
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Ext.extend(AutoRunModuleForm, Ext.Panel, {});
|
Ext.extend(AutoRunModuleForm, Ext.Container, {});
|
||||||
@@ -18,10 +18,11 @@ const areNotificationUpdateTest = {
|
|||||||
* Form for the user to read, update and delete a specific Auto Run rule.
|
* 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.
|
* 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.
|
* deleteFn: callback function to delete this rule.
|
||||||
* updateFn: callback function to update this rule.
|
* updateFn: callback function to update this rule.
|
||||||
*/
|
*/
|
||||||
AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
AutoRunRuleForm = function(rule, modules, deleteFn, updateFn) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const ruleTextFieldId = `rule-name-${rule.id}`;
|
const ruleTextFieldId = `rule-name-${rule.id}`;
|
||||||
const chainModeComboId = `rule-chain-mode-${rule.id}`;
|
const chainModeComboId = `rule-chain-mode-${rule.id}`;
|
||||||
@@ -31,6 +32,9 @@ AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
|||||||
const moduleContainer = new Ext.Container({
|
const moduleContainer = new Ext.Container({
|
||||||
style: {
|
style: {
|
||||||
padding: '10 10 10 10',
|
padding: '10 10 10 10',
|
||||||
|
},
|
||||||
|
listeners: {
|
||||||
|
afterrender: setupModuleForms
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,7 +76,7 @@ AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
|||||||
moduleContainer.removeAll(true);
|
moduleContainer.removeAll(true);
|
||||||
|
|
||||||
// I think execution order should always be sequential.
|
// I think execution order should always be sequential.
|
||||||
// The actual order comed from the modules array.
|
// The actual order comes from the modules array.
|
||||||
for (let i = 0; i < newRule.modules.length; ++i) {
|
for (let i = 0; i < newRule.modules.length; ++i) {
|
||||||
const isFirstModule = i === 0;
|
const isFirstModule = i === 0;
|
||||||
const isLastModule = i >= newRule.modules.length - 1;
|
const isLastModule = i >= newRule.modules.length - 1;
|
||||||
@@ -86,7 +90,6 @@ AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setupModuleForms();
|
|
||||||
|
|
||||||
function handleUpdateRule() {
|
function handleUpdateRule() {
|
||||||
// TODO: Check if inputs are valid.
|
// TODO: Check if inputs are valid.
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ getCurrentRules = async function(token) {
|
|||||||
throw new Error(`Getting auto run rules failed with status ${res.status}`);
|
throw new Error(`Getting auto run rules failed with status ${res.status}`);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
console.log("Successfully retrieved active rules.");
|
|
||||||
console.log(data);
|
|
||||||
const rules = JSON.parse(data.rules);
|
const rules = JSON.parse(data.rules);
|
||||||
|
|
||||||
if (data.success === true && Array.isArray(rules)) {
|
if (data.success === true && Array.isArray(rules)) {
|
||||||
@@ -49,6 +47,27 @@ getCurrentRules = async function(token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// DEBUG log
|
||||||
|
console.log("Successfully retrieved active modules:");
|
||||||
|
console.log(modules);
|
||||||
|
|
||||||
|
return modules;
|
||||||
|
|
||||||
|
} catch(error) {
|
||||||
|
console.error(error);
|
||||||
|
console.error("Failed to get auto run rules.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AutoRunTab = function() {
|
AutoRunTab = function() {
|
||||||
// RESTful API token.
|
// RESTful API token.
|
||||||
var token = BeefWUI.get_rest_token();
|
var token = BeefWUI.get_rest_token();
|
||||||
@@ -128,7 +147,18 @@ AutoRunTab = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadRules() {
|
async function loadRules() {
|
||||||
const rules = await getCurrentRules(token);
|
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) {
|
if (rules !== null) {
|
||||||
ruleLoadingState.update(`<p>Loaded ${rules.length} Auto Run rules.</p>`);
|
ruleLoadingState.update(`<p>Loaded ${rules.length} Auto Run rules.</p>`);
|
||||||
ruleContainer.removeAll();
|
ruleContainer.removeAll();
|
||||||
@@ -136,6 +166,7 @@ AutoRunTab = function() {
|
|||||||
for (let i = 0; i < rules.length; i++) {
|
for (let i = 0; i < rules.length; i++) {
|
||||||
ruleForm = new AutoRunRuleForm(
|
ruleForm = new AutoRunRuleForm(
|
||||||
rules[i],
|
rules[i],
|
||||||
|
modules,
|
||||||
function() {deleteRule(rules[i].id)},
|
function() {deleteRule(rules[i].id)},
|
||||||
function(newRuleData) {updateRule(rules[i].id, newRuleData)}
|
function(newRuleData) {updateRule(rules[i].id, newRuleData)}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ var re_execute_command_title = 'Re-execute command'
|
|||||||
function generate_form_input_field(form, input, value, disabled, zombie) {
|
function generate_form_input_field(form, input, value, disabled, zombie) {
|
||||||
var input_field = null;
|
var input_field = null;
|
||||||
var input_def = null;
|
var input_def = null;
|
||||||
|
console.log("Input type: ");
|
||||||
|
console.log(JSON.stringify(input, null, 2));
|
||||||
|
|
||||||
if (!input['ui_label']) input['ui_label'] = input['name'];
|
if (!input['ui_label']) input['ui_label'] = input['name'];
|
||||||
if (!input['type']) input['type'] = 'textfield';
|
if (!input['type']) input['type'] = 'textfield';
|
||||||
@@ -33,6 +35,8 @@ function generate_form_input_field(form, input, value, disabled, zombie) {
|
|||||||
allowBlank: false,
|
allowBlank: false,
|
||||||
value: input['value']
|
value: input['value']
|
||||||
};
|
};
|
||||||
|
console.log("Input Def:");
|
||||||
|
console.log(JSON.stringify(input_def, null, 2));
|
||||||
|
|
||||||
// create the input field object based upon the type supplied
|
// create the input field object based upon the type supplied
|
||||||
switch(input['type'].toLowerCase()) {
|
switch(input['type'].toLowerCase()) {
|
||||||
@@ -100,9 +104,11 @@ function generate_form_input_field(form, input, value, disabled, zombie) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Before setting values input field.");
|
||||||
if(value) input_field.setValue(value);
|
if(value) input_field.setValue(value);
|
||||||
if(disabled) input_field.setDisabled(true);
|
if(disabled) input_field.setDisabled(true);
|
||||||
|
|
||||||
|
console.log("Before adding input field to form values input field.");
|
||||||
form.add(input_field);
|
form.add(input_field);
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -424,64 +430,4 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function genNewAutoRunModulePanel(panel, module, ruleId) {
|
|
||||||
if(typeof panel != 'object') {
|
|
||||||
Ext.beef.msg('Bad!', 'Incorrect panel chosen.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.removeAll();
|
|
||||||
if(module.name == 'some special command module') {
|
|
||||||
//HERE we will develop specific panels for the command modules that require it.
|
|
||||||
} else {
|
|
||||||
var form = new Ext.form.FormPanel({
|
|
||||||
id: `form-are-module-${ruleId}`,
|
|
||||||
border: false,
|
|
||||||
labelWidth: 75,
|
|
||||||
defaultType: 'textfield',
|
|
||||||
title: module.name,
|
|
||||||
bodyStyle: 'padding: 5px;',
|
|
||||||
|
|
||||||
items: [
|
|
||||||
new Ext.form.DisplayField({
|
|
||||||
name: 'command_module_description',
|
|
||||||
fieldLabel: 'Description',
|
|
||||||
fieldClass: 'command-module-panel-description',
|
|
||||||
value: module.description
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
|
|
||||||
buttons:[{
|
|
||||||
text: "Save Module",
|
|
||||||
handler: function() {console.log("Saved module...")}
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
|
|
||||||
// create the panel and hide it
|
|
||||||
/*
|
|
||||||
var payload_panel = new Ext.Panel({
|
|
||||||
id: 'payload-panel', // used with Ext.GetCmp('payload-panel')
|
|
||||||
bodyStyle: 'padding:10px;', // we can assign styles to the main div
|
|
||||||
layout : 'form',
|
|
||||||
bodyBorder: false,
|
|
||||||
height: 200,
|
|
||||||
hidden: true,
|
|
||||||
border: false //we can remove the border of the panel
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
Ext.each(module.Data, function(input){
|
|
||||||
// Fake a zombie "session" property for the sake of getting it working.
|
|
||||||
generate_form_input_field(form, input, null, false, {session: module.name})}
|
|
||||||
);
|
|
||||||
|
|
||||||
//form.add(payload_panel);
|
|
||||||
panel.add(form);
|
|
||||||
panel.doLayout();
|
|
||||||
// hide the load mask after rendering of the config panel is done
|
|
||||||
//panel.configLoadMask.hide();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user