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
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]
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.