mirror of
https://github.com/gchq/CyberChef.git
synced 2025-05-10 00:05:11 -04:00
chef.bake can parse chef format recipe
This commit is contained in:
parent
616b38c6fb
commit
a289eda7fc
2 changed files with 108 additions and 12 deletions
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
import {operations} from "./index.mjs";
|
import {operations} from "./index.mjs";
|
||||||
import { sanitise } from "./apiUtils.mjs";
|
import { sanitise } from "./apiUtils.mjs";
|
||||||
|
import Utils from "../core/Utils";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to core/Recipe, Recipe controls a list of operations and
|
* Similar to core/Recipe, Recipe controls a list of operations and
|
||||||
|
@ -34,9 +36,10 @@ class NodeRecipe {
|
||||||
});
|
});
|
||||||
if (op) {
|
if (op) {
|
||||||
return op;
|
return op;
|
||||||
} else {
|
|
||||||
throw new TypeError(`Couldn't find an operation with name '${ing}'.`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new TypeError(`Couldn't find an operation with name '${ing}'.`);
|
||||||
|
|
||||||
} else if (typeof ing === "function") {
|
} else if (typeof ing === "function") {
|
||||||
if (operations.includes(ing)) {
|
if (operations.includes(ing)) {
|
||||||
return ing;
|
return ing;
|
||||||
|
@ -47,7 +50,15 @@ class NodeRecipe {
|
||||||
} else if (ing.op) {
|
} else if (ing.op) {
|
||||||
const sanitisedOp = this._validateIngredient(ing.op);
|
const sanitisedOp = this._validateIngredient(ing.op);
|
||||||
if (ing.args) {
|
if (ing.args) {
|
||||||
return {op: sanitisedOp, args: ing.args};
|
|
||||||
|
// disabled, breakpoint options sometimes come from parsed
|
||||||
|
// recipes pasted from UI
|
||||||
|
return {
|
||||||
|
op: sanitisedOp,
|
||||||
|
args: ing.args,
|
||||||
|
disabled: ing.disabled,
|
||||||
|
breakpoint: ing.breakpoint
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return sanitisedOp;
|
return sanitisedOp;
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,7 +66,6 @@ class NodeRecipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse config for recipe.
|
* Parse config for recipe.
|
||||||
* @param {String | Function | String[] | Function[] | [String | Function]} recipeConfig
|
* @param {String | Function | String[] | Function[] | [String | Function]} recipeConfig
|
||||||
|
@ -66,6 +76,14 @@ class NodeRecipe {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Case for when recipeConfig is a chef format recipe string
|
||||||
|
if (typeof recipeConfig == "string" || recipeConfig instanceof String) {
|
||||||
|
const attemptedParseResult = Utils.parseRecipeConfig(recipeConfig);
|
||||||
|
if (attemptedParseResult.length > 0) {
|
||||||
|
recipeConfig = attemptedParseResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Array.isArray(recipeConfig)) {
|
if (!Array.isArray(recipeConfig)) {
|
||||||
recipeConfig = [recipeConfig];
|
recipeConfig = [recipeConfig];
|
||||||
}
|
}
|
||||||
|
@ -79,15 +97,27 @@ class NodeRecipe {
|
||||||
* @returns {NodeDish}
|
* @returns {NodeDish}
|
||||||
*/
|
*/
|
||||||
execute(dish) {
|
execute(dish) {
|
||||||
return this.opList.reduce((prev, curr) => {
|
for (const op of this.opList) {
|
||||||
// CASE where opList item is op and args
|
if (
|
||||||
if (Object.prototype.hasOwnProperty.call(curr, "op") &&
|
Object.prototype.hasOwnProperty.call(op, "op") &&
|
||||||
Object.prototype.hasOwnProperty.call(curr, "args")) {
|
Object.prototype.hasOwnProperty.call(op, "args")
|
||||||
return curr.op(prev, curr.args);
|
) {
|
||||||
|
|
||||||
|
if (op.breakpoint) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// CASE opList item is just op.
|
|
||||||
return curr(prev);
|
if (op.disabled) {
|
||||||
}, dish);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dish = op.op(dish, op.args);
|
||||||
|
} else {
|
||||||
|
dish = op(dish);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dish;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,6 +357,58 @@ TestRegister.addApiTests([
|
||||||
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
|
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept single operation Chef format recipe as second argument", () => {
|
||||||
|
const result = chef.bake("throw throw burrito", "To_Hex_Content('All chars',false)");
|
||||||
|
assert.strictEqual(result.toString(), "|7468726f77207468726f77206275727269746f|");
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept single operation Chef format recipe as second argument with non-default arguments", () => {
|
||||||
|
const result = chef.bake("Throw Throw Burrito", "ROT13(true,false,14)");
|
||||||
|
assert.strictEqual(result.toString(), "Tvfck Tvfck Biffwhc");
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept multiple operation Chef format recipe as second argument", () => {
|
||||||
|
const result = chef.bake("throw throw burrito", "To_Hex('Space',2)Hex_to_Object_Identifier()Extract_IP_addresses(true,false,false,true)");
|
||||||
|
assert.strictEqual(result.toString(), `Total found: 5
|
||||||
|
|
||||||
|
2.36.104.114
|
||||||
|
111.119.32.116
|
||||||
|
104.114.111.119
|
||||||
|
32.98.117.114
|
||||||
|
114.105.116.111
|
||||||
|
`);
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept multiple operation Chef format recipe as pasted from UI as second argument", () => {
|
||||||
|
const result = chef.bake("throw throw burrito", `To_Hex('Space',2)
|
||||||
|
Hex_to_Object_Identifier()
|
||||||
|
Extract_IP_addresses(true,false,false,true)
|
||||||
|
`);
|
||||||
|
assert.strictEqual(result.toString(), `Total found: 5
|
||||||
|
|
||||||
|
2.36.104.114
|
||||||
|
111.119.32.116
|
||||||
|
104.114.111.119
|
||||||
|
32.98.117.114
|
||||||
|
114.105.116.111
|
||||||
|
`);
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept multiple operation Chef format recipe with a disabled operation", async () => {
|
||||||
|
const result = await chef.bake("throw throw burrito", `ROT13(true,true,13)
|
||||||
|
Atbash_Cipher(/disabled)
|
||||||
|
MD5()
|
||||||
|
`);
|
||||||
|
assert.strictEqual(result.toString(), "f859e9e196c4452d2d25f12dffc67355");
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept multiple operation Chef format recipe with a breakpoint operation", async () => {
|
||||||
|
const result = await chef.bake("throw throw burrito", `ROT13(true,true,13)
|
||||||
|
Atbash_Cipher()
|
||||||
|
MD5(/breakpoint)`);
|
||||||
|
assert.strictEqual(result.toString(), "tfvyq tfvyq lsvvety");
|
||||||
|
}),
|
||||||
|
|
||||||
it("Excluded operations: throw a sensible error when you try and call one", () => {
|
it("Excluded operations: throw a sensible error when you try and call one", () => {
|
||||||
try {
|
try {
|
||||||
chef.fork();
|
chef.fork();
|
||||||
|
@ -375,6 +427,20 @@ TestRegister.addApiTests([
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
it("Excluded operations: throw a sensible error when you try and call one as part of a recipe", () => {
|
||||||
|
try {
|
||||||
|
chef.bake(`978346800
|
||||||
|
1012651200
|
||||||
|
1046696400
|
||||||
|
1081087200
|
||||||
|
1115305200
|
||||||
|
1149609600`, "Fork('\\n','\\n',false)From_UNIX_Timestamp('Seconds (s)')");
|
||||||
|
} catch (e) {
|
||||||
|
assert.strictEqual(e.type, "ExcludedOperationError");
|
||||||
|
assert.strictEqual(e.message, "Sorry, the Fork operation is not available in the Node.js version of CyberChef.");
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
it("Operation arguments: should be accessible from operation object if op has array arg", () => {
|
it("Operation arguments: should be accessible from operation object if op has array arg", () => {
|
||||||
assert.ok(chef.toCharcode.args);
|
assert.ok(chef.toCharcode.args);
|
||||||
assert.deepEqual(chef.unzip.args, {
|
assert.deepEqual(chef.unzip.args, {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue