Skip to content

Commit

Permalink
Rework functions/contexts additional fields
Browse files Browse the repository at this point in the history
  • Loading branch information
cyrus-and committed Aug 13, 2024
1 parent 1deebf4 commit 7d6c122
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 44 deletions.
50 changes: 40 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ permalink: /contributing/

Feel free to use any file in the [`_gtfobins/`] folder as an example.

Each entry is defined in a [YAML][] file placed in the [`_gtfobins/`][] folder and named like the executable (binary or script) it refers, without any extension. The file contains a single document enclosed in delimiters: `---` and `...`. The general structure is the following:
Each entry is defined in a [YAML][] file placed in the [`_gtfobins/`][] folder and named like the executable (binary or script) it refers, without any extension. The file contains a single YAML document enclosed in delimiters: `---` and `...`. The general structure is the following:

```yaml
---
Expand All @@ -36,27 +36,57 @@ The optional `version` field must outline any particular OS or executable requir

The `contexts` object can be omitted altogether, in that case `code` is assumed to be about the `unprivileged` context. When a context specifies a specialized `code` field, it is used in place of the global value, which can be omitted if all the context specifies a specialization. `description` instances can always be omitted, while ultimately there must be one `code` example for each context, either specialized or inherited.

### Functions

Some functions support additional fields:

- `reverse-shell` allows a `listener` field that describes how to receive the shell on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);
| Function | Fields |
|-----------------|---------------------------|
| `shell` | `blind` |
| `command` | `blind` |
| `reverse-shell` | `blind` `tty` `listener` |
| `bind-shell` | `blind` `tty` `connector` |
| `file-write` | `binary` |
| `file-read` | `binary` |
| `upload` | `binary` `receiver` |
| `download` | `binary` `sender` |
| `library-load` | n/a |
| `inherit` | `from` |

Where:

- the optional `blind` field determines whether the example is able to somehow return the output of the execution of commands or not (defaults to `false`);

- the optional `tty` field determines whether the example is able to spawn a full TTY shell or not (defaults to `true`);

- `bind-shell` allows a `connector` field that describes how to initiate the shell on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);
- the optional `binary` field determines whether the example is able to handle arbitrary binary data or not (defaults to `true`);

- `upload` allows a `receiver` field that describes how to receive data on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);
- the optional `listener` field describes how to receive the shell on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);

- `download` allows a `sender` field that describes how to send data on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);
- the optional `connector` field describes how to initiate the shell on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);

- `reverse-shell` and `bind-shell` allows a `limited` flag that is `true` when the example is not able to spawn a full TTY shell.
- the optional `receiver` field describes how to receive data on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);

- `file-write`, `file-read`, `upload`, and `download` allows a `limited` flag that is `true` when the example is not able handle arbitrary binary data;
- the optional `sender` field describes how to send data on the other side, it can be either a string (that must match the corresponding key in [`_data/functions.yml`][], e.g., `TCP`), or an object with two optional fields (`description` and `code`);

- `inherit` requires a `from` field that is the name of another executable that the example enables.
- the mandayory `from` field that is the name of another executable that the example enables.

### Contexts

Some contexts support additional fields:

- `suid` allows a `limited` flag that is `true` when the example only works with distributions whose default shell does not drop SUID privileges;
| Context | Fields |
|----------------|----------|
| `unprivileged` | n/a |
| `sudo` | n/a |
| `suid` | `system` |
| `capabilities` | `list` |

Where:

- the optional `system` field determines whether the executable uses functions like [`system`](https://man7.org/linux/man-pages/man3/system.3.html) that passes commands to the default system shell, which, according to the version used, might or might not drop the privileges (defaults to `false`);

- `capabilities` requires a `list` of Linux [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) in the format `CAP_*` that are needed in order to execute this function with bypassed permissions.
- the mandayory `list` field is the list of Linux [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) in the format `CAP_*` that are needed in order to execute this function with bypassed permissions.

### Aliases

Expand Down
7 changes: 5 additions & 2 deletions _data/contexts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ suid:
label: SUID
description: This function is performed by the privileged user if the executable has the SUID bit set and the right ownership because the *effective* privileges are not dropped.
extra:
limited: This executable runs external commands via functions like `system`, so it only works for distributions where the default shell does not drop SUID privileges.
regular: Remember to omit the `-p` argument of every `sh` invocation for distributions where the default shell does not drop SUID privileges.
system:
true: This executable runs external commands via functions like `system`, so it only works for distributions where the default shell does not drop SUID privileges.
false: Remember to omit the `-p` argument of every `/bin/sh` invocation for distributions where the default shell does not drop SUID privileges.

capabilities:
label: Capabilities
description: This function is performed bypassing the usual kernel permission checks if the executable has certain capabilities set.
extra:
list: 'The following capabilities are needed:'
35 changes: 25 additions & 10 deletions _data/functions.yml
Original file line number Diff line number Diff line change
@@ -1,44 +1,59 @@
shell:
label: Shell
description: This executable can spawn an interactive system shell.
extra:
blind: &blind
true: The commands are executed but their output is hidden from the attacker.

command:
label: Command
description: This executable can run non-interactive system commands.
extra:
blind: *blind

reverse-shell:
label: Reverse shell
description: This executable can send back a reverse system shell to a listening attacker.
extra: &network-shell-extra
limited: The spawned shell is just a dummy REPL that can only run simple terminal commands.
regular: The spawned shell is a full TTY shell that can run complex terminal programs like `sudo` password prompts.
extra:
tty: &tty
false: The spawned shell is just a dummy REPL that can only run simple terminal commands.
blind: *blind
listener:

bind-shell:
label: Bind shell
description: This executable can bind a system shell to a local port waiting for an attacker to connect.
extra: *network-shell-extra
extra:
tty: *tty
blind: *blind
connector:

file-write:
label: File write
description: This executable can write data to local files.
extra: &data-operations-extra
limited: The content is corrupted or otherwise altered by the process, thus it might not be suitable for handling arbitrary binary data.
regular: The content is handled perfectly, including binary data.
extra:
binary: &binary
false: The content is corrupted or otherwise altered by the process, thus it might not be suitable for handling arbitrary binary data.

file-read:
label: File read
description: This executable can read data from local files.
extra: *data-operations-extra
extra:
binary: *binary

upload:
label: Upload
description: This executable can upload local data.
extra: *data-operations-extra
extra:
binary: *binary
receiver:

download:
label: Download
description: This executable can download remote data.
extra: *data-operations-extra
extra:
binary: *binary
sender:

library-load:
label: Library load
Expand Down
30 changes: 17 additions & 13 deletions _layouts/gtfobin.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,20 @@ <h2 id="{{ function_name }}" class="function-name">{{- function.label -}}</h2>

{% comment %} additional per-function content {% endcomment %}
{% case function_name %}
{% when "shell", "command", "reverse-shell", "bind-shell" %}
{% if example.blind %}
<fieldset>
<legend>Output</legend>
{{ function.extra.blind[true] | markdownify }}
</fieldset>
{% endif %}
{% when "reverse-shell", "bind-shell" %}
{% when "reverse-shell", "bind-shell", "file-write", "file-read", "download", "upload" %}
<fieldset>
<legend>Remarks</legend>
{% if example.limited %}
{{ function.extra.limited | markdownify }}
{% else %}
{{ function.extra.regular | markdownify }}
{% endif %}
</fieldset>
{% unless example.tty %}
<fieldset>
<legend>TTY</legend>
{{ function.extra.tty[false] | markdownify }}
</fieldset>
{% endunless %}
{% when "reverse-shell" %}
{% if example.listener %}
{% assign known = function.extra[example.listener] %}
Expand Down Expand Up @@ -173,15 +177,15 @@ <h2 id="{{ function_name }}" class="function-name">{{- function.label -}}</h2>
{% when "suid" %}
<fieldset>
<legend>Remarks</legend>
{% if per_context_info.limited %}
{{ context.extra.limited | markdownify }}
{% if context.extra.system %}
{{ context.extra.system[true] | markdownify }}
{% else %}
{{ context.extra.regular | markdownify }}
{{ context.extra.system[false] | markdownify }}
{% endif %}
</fieldset>
{% when "capabilities" %}
<p>
The following capabilities are needed:
{{ context.extra.list }}
{% for capability in per_context_info.list %}
<code>{{ capability | escape }}</code>
{%- if forloop.last -%}.{%- else -%}, {%- endif -%}
Expand Down
2 changes: 1 addition & 1 deletion index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description: GTFOBins is a curated list of Unix-like executables that can be use

{{ page.description }}

The project [collects]({{ '/scope/' | relative_url }}) legitimate functions of Unix-like executables that can be abused to ~~get the f**k~~ break out restricted shells, escalate or maintain elevated privileges, transfer files, spawn bind and reverse shells, and facilitate other post-exploitation tasks.
The project collects legitimate [functions]({{ '/scope/' | relative_url }}) of Unix-like executables that can be abused to ~~get the f**k~~ break out restricted shells, escalate or maintain elevated privileges, transfer files, spawn bind and reverse shells, and facilitate other post-exploitation tasks.

GTFOBins is a joint effort by [Emilio Pinna][norbemi] and [Andrea Cardaci][cyrus_and], and many other [contributors][]. Everyone can [get involved]({{ '/contributing/' | relative_url }}) by providing additional entries and techniques!

Expand Down
21 changes: 13 additions & 8 deletions linter/linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def contexts(names, context_schema):
schema.Optional('contexts'): {
**contexts(['unprivileged', 'sudo'], {}),
**contexts(['suid'], {
schema.Optional('limited'): bool,
schema.Optional('system'): bool,
}),
**contexts(['capabilities'], {
schema.Optional('list'): schema.And(len, [
Expand Down Expand Up @@ -100,29 +100,34 @@ def check_code_coherence(example):

functions = {
'functions': schema.And(len, {
**functions(['shell', 'command', 'library-load'], {}),
**functions(['shell', 'command'], {
schema.Optional('blind'): bool,
}),
**functions(['reverse-shell'], {
schema.Optional('limited'): bool,
schema.Optional('tty'): bool,
schema.Optional('blind'): bool,
schema.Optional('listener'): network_shell_counterpart,
}),
**functions(['bind-shell'], {
schema.Optional('limited'): bool,
schema.Optional('tty'): bool,
schema.Optional('blind'): bool,
schema.Optional('connector'): network_shell_counterpart,
}),
**functions(['file-write'], {
schema.Optional('limited'): bool,
schema.Optional('binary'): bool,
}),
**functions(['file-read'], {
schema.Optional('limited'): bool,
schema.Optional('binary'): bool,
}),
**functions(['upload'], {
schema.Optional('limited'): bool,
schema.Optional('binary'): bool,
schema.Optional('receiver'): network_file_counterpart,
}),
**functions(['download'], {
schema.Optional('limited'): bool,
schema.Optional('binary'): bool,
schema.Optional('sender'): network_file_counterpart,
}),
**functions(['library-load'], {}),
**functions(['inherit'], {
'from': non_empty_string,
}),
Expand Down

0 comments on commit 7d6c122

Please sign in to comment.