> For the complete documentation index, see [llms.txt](https://capcap-1.gitbook.io/capcap/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://capcap-1.gitbook.io/capcap/readme/ctf-modules/exploitation/password-attacks/linux-auth-process/linux-credential-hunting.md).

# Linux Credential Hunting

## Credential Hunting in Linux

### Overview

After gaining a foothold (e.g. reverse shell via web app exploit), credential hunting is the first step before attempting complex privilege escalation. Credentials found here can give elevated access within seconds.

Credentials are grouped into four categories:

| Category  | Sources                                                |
| --------- | ------------------------------------------------------ |
| Files     | Configs, databases, notes, scripts, cronjobs, SSH keys |
| History   | Command-line history, logs                             |
| Memory    | Cache, in-memory processing                            |
| Key-rings | Browser stored credentials                             |

***

### Files

#### Configuration Files

Services store credentials in config files so they can authenticate automatically without human input. Primary extensions to target: `.conf`, `.config`, `.cnf` — but files can be renamed, so don't rely on extensions alone.

**Find all config files (by extension):**

```bash
for l in $(echo ".conf .config .cnf"); do
    echo -e "\nFile extension: " $l
    find / -name *$l 2>/dev/null | grep -v "lib\|fonts\|share\|core"
done
```

**Search inside config files for credential keywords:**

```bash
for i in $(find / -name *.cnf 2>/dev/null | grep -v "doc\|lib"); do
    echo -e "\nFile: " $i
    grep "user\|password\|pass" $i 2>/dev/null | grep -v "\#"
done
```

> `grep -v "\#"` strips commented lines so you only see active config values.

***

#### Databases

SQLite and other file-based databases are often stored in user home directories or app directories and may contain plaintext or weakly hashed credentials.

**Find database files:**

```bash
for l in $(echo ".sql .db .*db .db*"); do
    echo -e "\nDB File extension: " $l
    find / -name *$l 2>/dev/null | grep -v "doc\|lib\|headers\|share\|man"
done
```

Notable targets from Firefox profile directories:

| File          | Contents                            |
| ------------- | ----------------------------------- |
| `cert9.db`    | Certificate store                   |
| `key4.db`     | Encryption keys for saved passwords |
| `logins.json` | Encrypted saved credentials         |

***

#### Notes

Admins frequently store credentials in plaintext notes. These have no standard extension and can be named anything, so search both `.txt` files and extension-less files.

```bash
find /home/* -type f -name "*.txt" -o ! -name "*.*"
```

***

#### Scripts

Automated scripts must authenticate without human input, so credentials get hardcoded directly into the script body.

**Find scripts by extension:**

```bash
for l in $(echo ".py .pyc .pl .go .jar .c .sh"); do
    echo -e "\nFile extension: " $l
    find / -name *$l 2>/dev/null | grep -v "doc\|lib\|headers\|share"
done
```

***

#### Cronjobs

Cron runs scripts automatically — same problem as scripts above. Credentials are often embedded in the cron scripts themselves or passed as arguments.

**Cron locations to check:**

| Path                 | Description                           |
| -------------------- | ------------------------------------- |
| `/etc/crontab`       | System-wide crontab                   |
| `/etc/cron.d/`       | Per-application cron configs (Debian) |
| `/etc/cron.daily/`   | Daily jobs                            |
| `/etc/cron.hourly/`  | Hourly jobs                           |
| `/etc/cron.weekly/`  | Weekly jobs                           |
| `/etc/cron.monthly/` | Monthly jobs                          |

```bash
cat /etc/crontab
ls -la /etc/cron.*/
```

***

#### SSH Keys

Private keys in `~/.ssh/` allow passwordless authentication to other systems. Finding a private key = potential pivot to other machines in the network.

```bash
find / -name id_rsa 2>/dev/null
find / -name id_ed25519 2>/dev/null
find / -name authorized_keys 2>/dev/null
```

***

### History

#### Bash History

People frequently make the mistake of typing passwords directly into the terminal — as command arguments, inline with scripts, or via `su`. Everything gets captured in `.bash_history`.

```bash
tail -n 50 /home/*/.bash_history
```

**Real example of what you find:**

```bash
/tmp/api.py cry0l1t3 6mX4UP1eWH3HXK
# Username and password passed as CLI arguments — sitting in plaintext
```

**Also check:**

```bash
cat /home/*/.bashrc
cat /home/*/.bash_profile
# May contain exported credentials as environment variables
```

***

#### Log Files

Logs capture authentication events, sudo usage, and service activity. Useful for reconstructing what credentials exist on the system.

**Key log files:**

| File                  | Contents                        |
| --------------------- | ------------------------------- |
| `/var/log/auth.log`   | All auth events (Debian)        |
| `/var/log/secure`     | All auth events (RedHat/CentOS) |
| `/var/log/faillog`    | Failed login attempts           |
| `/var/log/cron`       | Cron job execution              |
| `/var/log/messages`   | Generic system activity         |
| `/var/log/syslog`     | Generic system activity         |
| `/var/log/mysqld.log` | MySQL activity                  |
| `/var/log/httpd`      | Apache activity                 |

**Grep all logs for credential-related keywords at once:**

```bash
for i in $(ls /var/log/* 2>/dev/null); do
    GREP=$(grep "accepted\|session opened\|session closed\|failure\|failed\|ssh\|password changed\|new user\|delete user\|sudo\|COMMAND\=\|logs" $i 2>/dev/null)
    if [[ $GREP ]]; then
        echo -e "\n#### Log file: " $i
        grep "accepted\|session opened\|session closed\|failure\|failed\|ssh\|password changed\|new user\|delete user\|sudo\|COMMAND\=\|logs" $i 2>/dev/null
    fi
done
```

***

### Memory and Cache

Credentials for logged-in users and active services are held in memory. These never touch disk in plaintext but can be extracted while the process is running.

#### mimipenguin

Dumps credentials from memory of running processes (GNOME keyring, etc.). Requires root.

```bash
sudo python3 mimipenguin.py
# [SYSTEM - GNOME]    cry0l1t3:WLpAEXFa0SbqOHY
```

***

#### LaZagne

Broader credential extraction tool. Pulls from memory and from all stored credential locations across the system.

**Sources LaZagne targets:**

Wifi, Wpa\_supplicant, Libsecret, Kwallet, Chromium, Firefox, Thunderbird, Git, ENV variables, Grub, Fstab, AWS, Filezilla, SSH, Apache, Shadow, Docker, Keepass, Keyrings, Sessions

**Run all modules:**

```bash
sudo python2.7 laZagne.py all
```

**Run only browser module:**

```bash
python3 laZagne.py browsers
```

***

### Browser Credentials

Firefox stores saved passwords encrypted in the user's profile directory. The encryption key is also stored locally, so decryption is straightforward.

**Profile location:**

```bash
ls -l ~/.mozilla/firefox/ | grep default
```

**Encrypted credentials file:**

```bash
cat ~/.mozilla/firefox/<profile>/logins.json | jq .
```

The `logins.json` file contains encrypted username, encrypted password, the target URL, and field names.

**Decrypt with firefox\_decrypt:**

```bash
python3.9 firefox_decrypt.py
# Select profile → outputs plaintext username:password per site
```

> Requires Python 3.9 for the latest version. Use firefox\_decrypt 0.7.0 with Python 2 on older systems.

LaZagne handles this automatically via the browsers module.

***

### Tool Summary

| Tool              | Target                                 | Requires Root    |
| ----------------- | -------------------------------------- | ---------------- |
| `mimipenguin`     | Memory (GNOME, running processes)      | Yes              |
| `laZagne`         | Memory + all stored credential sources | Recommended      |
| `firefox_decrypt` | Firefox saved passwords                | No (run as user) |

***

### Credential Hunting Checklist

```
[ ] Config files     → for loop over .conf/.config/.cnf, grep for user/pass
[ ] Database files   → for loop over .sql/.db, check Firefox profile DBs
[ ] Notes/txt files  → find /home/* txt and extension-less files
[ ] Scripts          → for loop over .sh/.py/.pl/.go/.jar/.c
[ ] Cronjobs         → /etc/crontab, /etc/cron.d/, /etc/cron.*/
[ ] SSH keys         → find id_rsa, id_ed25519, authorized_keys
[ ] Bash history     → /home/*/.bash_history, .bashrc, .bash_profile
[ ] Log files        → grep auth/sudo/session keywords across /var/log/*
[ ] Memory           → mimipenguin, laZagne all
[ ] Browser creds    → firefox_decrypt, laZagne browsers
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://capcap-1.gitbook.io/capcap/readme/ctf-modules/exploitation/password-attacks/linux-auth-process/linux-credential-hunting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
