Pentesting FoundationDB
During a recent Pentesting engagement, I came across a service using FoundationDB to store application layer configurations and state. This lead me to dive into understanding this very rare, but interesting type of distributed database and document tools and methods to access the data stored in it.
The official documentation for FoundationDB can be found here. A brief description from the docs is :
FoundationDB is a distributed database designed to handle large volumes of structured data across clusters of commodity servers. It organizes data as an ordered key-value store and employs ACID transactions for all operations.
Utilities to access a local or remote database require the presence of a local Cluster File. The high level format of this file is :
$ cat /etc/foundationdb/fdb.cluster
description:ID@IP:PORT,IP:PORT,...
Additional details on this can be found here.
A local or remote FoundationDB can be conveniently be accessed using 2 utilities :
- fdbcli : Command Line Interface
- Python API
fdbcli : Command Line Interface
[Official Documentation][https://apple.github.io/foundationdb/command-line-interface.html]
Commands available to obtain database metadata :
fdbcli --exec "status minimal"
fdbcli --exec "status details"
An example of the output of these commands would look like :
# fdbcli --exec "status details"
Using cluster file `/etc/foundationdb/fdb.cluster'.
Configuration:
Redundancy mode - single
Storage engine - ssd-2
Coordinators - 1
Cluster:
FoundationDB processes - 2
Machines - 1
Memory availability - 3.5 GB per process on machine with least available
>>>>> (WARNING: 4.0 GB recommended) <<<<<
Fault Tolerance - 0 machines
Server time - 05/30/23 16:10:29
Data:
Replication health - Healthy
Moving data - 0.000 GB
Sum of key-value sizes - 138.222 GB
Disk space used - 202.369 GB
Operating space:
Storage server - 523.2 GB free on most full server
Log server - 523.2 GB free on most full server
Workload:
Read rate - 188 Hz
Write rate - 51 Hz
Transactions started - 54 Hz
Transactions committed - 17 Hz
Conflict rate - 0 Hz
Backup and DR:
Running backups - 0
Running DRs - 0
Process performance details:
127.0.0.1:4500 ( 4% cpu; 6% machine; 0.004 Gbps; 1% disk IO; 5.5 GB / 3.5 GB RAM )
127.0.0.1:4501 ( 4% cpu; 6% machine; 0.004 Gbps; 1% disk IO; 0.2 GB / 3.5 GB RAM )
Coordination servers:
127.0.0.1:4500 (reachable)
Client time: 05/30/23 16:10:29
Key-Value pairs stored can be read using getrange
. This method yields packed data in the response which may require some processing.
root@ubuntu:/home/support# fdbcli
Using cluster file `/etc/foundationdb/fdb.cluster'.
The database is available.
Welcome to the fdbcli. For help, type `help'.
fdb> getrange \x00 \xff 100
Range limited to 100 keys
`\x15\x08...\x80' is `\x14\x16G?\x16..\xda=\xef'
`\x15\x08...\xa7@' is `\x14\x16G?...\xda=\xf1'
[Trimmed]
Python API
(Official Documentation)[https://apple.github.io/foundationdb/api-python.html]
Here would be a simple Python (in Python2.7) script to enumerate sequential keys. It would be a good idea to be cognizant of the limit
of the number of pairs you want to fetch back, as it may impact the performance of the database.
import fdb
from fdb.tuple import pack, unpack
fdb.api_version(510)
db = fdb.open()
for k, v in db.get_range('\x00', '\xFF' ,limit=10, reverse=False):
try:
unpack(k)
except:
print()
try:
unpack(v)
except:
print()
This method takes care of unpacking the data (as compared to that from fdbcli), providing a readable dump of key-value pairs.
Warning Notice: This article is intended for Educational purposes only. Please be mind when using these tools on production or sensitive systems.