2 minute read

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 :

  1. fdbcli : Command Line Interface
  2. 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.