Logging Monitoring Failures in Fiber
How Logging Monitoring Failures Manifests in Fiber
Logging monitoring failures in Fiber applications typically occur when sensitive data is inadvertently logged to console, files, or external monitoring services without proper sanitization. This manifests through several attack patterns:
- Credential Leakage: Database passwords, API keys, and authentication tokens appearing in log files when Fiber handles authentication or database connections
- Personal Data Exposure: User PII (email addresses, phone numbers, SSNs) logged during request processing, especially in error handling
- Debug Information Disclosure: Stack traces, configuration details, and internal system information exposed in production logs
- Audit Trail Manipulation: Failed attempts to log security events or modify audit logs to cover tracks
In Fiber applications, this commonly appears in middleware, error handlers, and database connection logging. For example, a Fiber application might log entire request bodies without filtering sensitive fields, or include database connection strings in error messages when connections fail.
// Vulnerable pattern - logging entire request without filtering
app.Post("/login", func(c *fiber.Ctx) error {
user := new(User)
if err := c.BodyParser(user); err != nil {
log.Printf("Login attempt: %v", c.Body()) // Logs password in plaintext
return c.Status(400).SendString("Invalid request")
}
// ... authentication logic
return c.SendStatus(200)
})
Another manifestation occurs in database logging where connection details are exposed:
// Vulnerable - exposing database credentials in logs
dsn := "user:password@tcp(localhost:5432)/dbname?sslmode=disable"
log.Printf("Connecting to database: %s", dsn) // Logs credentials
Middleware that logs request details without proper filtering is particularly problematic:
// Vulnerable middleware - logs sensitive headers
app.Use(func(c *fiber.Ctx) error {
log.Printf("Request: %s %s Headers: %v", c.Method(), c.Path(), c.Headers())
return c.Next()
})
Fiber-Specific Detection
Detecting logging monitoring failures in Fiber applications requires both static code analysis and runtime scanning. middleBrick's black-box scanning approach can identify these issues without requiring access to source code:
Static Analysis Patterns
- Search for
log.Printf,log.Println, and other logging calls that include request bodies or headers - Identify database connection strings and credentials in configuration files
- Look for error handlers that include stack traces or internal system details
Runtime Detection with middleBrick
middleBrick scans Fiber endpoints by sending test requests and analyzing responses for sensitive data exposure. The scanner checks for:
- Response headers that might leak internal information
- Error messages that include stack traces or database details
- Logging endpoints that echo back sensitive request data
# Scan a Fiber API endpoint with middleBrick
middlebrick scan https://api.example.com --output json
# Example output showing logging monitoring failure
{
"category": "Logging Monitoring Failures",
"severity": "high",
"finding": "Sensitive data exposure in error responses",
"remediation": "Implement proper error handling and remove stack traces from production responses"
}
Manual Testing Approach
For Fiber applications, manual testing should include:
// Test for logging vulnerabilities
func testLoggingVulnerabilities(app *fiber.App) {
// Test with invalid credentials
req := httptest.NewRequest("POST", "/login", strings.NewReader(`{"email":"test@example.com","password":"wrong"}`))
w := httptest.NewRecorder()
app.Handler().ServeHTTP(w, req)
// Check if sensitive data appears in logs
// ... implementation would verify log outputs
}
middleBrick's Advantage
Unlike traditional scanners that only check for known vulnerabilities, middleBrick's approach tests the actual runtime behavior of your Fiber API, identifying logging monitoring failures that only appear with specific input patterns or error conditions.
Fiber-Specific Remediation
Remediating logging monitoring failures in Fiber requires a multi-layered approach using Fiber's native features and Go best practices:
1. Implement Structured Logging with Sanitization
Use Fiber's context to safely log request information without exposing sensitive data:
import (
"github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus"
)
// Custom middleware for safe logging
func safeLoggingMiddleware() fiber.Handler {
return func(c *fiber.Ctx) error {
// Log basic request info without sensitive data
logrus.Infof("Request: %s %s from %s",
c.Method(), c.Path(), c.IP())
return c.Next()
}
}
// Sanitize function for sensitive data
func sanitizeData(data interface{}) interface{} {
switch v := data.(type) {
case map[string]interface{}:
sanitized := make(map[string]interface{})
for key, value := range v {
if strings.Contains(key, "password") || strings.Contains(key, "secret") {
sanitized[key] = "[FILTERED]"
} else {
sanitized[key] = sanitizeData(value)
}
}
return sanitized
case []interface{}:
sanitized := make([]interface{}, len(v))
for i, item := range v {
sanitized[i] = sanitizeData(item)
}
return sanitized
default:
return v
}
}
2. Secure Error Handling
Implement proper error handling that doesn't expose internal details:
import "github.com/gofiber/fiber/v3"
// Custom error handler middleware
func secureErrorHandler() fiber.Handler {
return func(c *fiber.Ctx) error {
err := c.Next()
if err != nil {
// Log the error internally with details
logrus.Errorf("Error processing request: %v", err)
// Return generic error to client
return c.Status(500).JSON(fiber.Map{
"error": "Internal server error",
"requestId": c.Get("X-Request-ID"),
})
}
return nil
}
}
// Example endpoint with secure error handling
app.Post("/sensitive", func(c *fiber.Ctx) error {
defer func() {
if r := recover(); r != nil {
logrus.Errorf("Panic recovered: %v", r)
return c.Status(500).JSON(fiber.Map{"error": "Internal error"})
}
}()
// Your business logic here
return c.SendStatus(200)
})
3. Database Connection Security
Never log database credentials or connection details:
import "github.com/gofiber/fiber/v3"
func setupDatabase() {
// Use environment variables, never log them
dbUser := os.Getenv("DB_USER")
dbPass := os.Getenv("DB_PASSWORD")
dbHost := os.Getenv("DB_HOST")
// Log only non-sensitive connection info
logrus.Infof("Connecting to database at %s", dbHost)
// Establish connection without logging credentials
dsn := fmt.Sprintf("%s:%s@tcp(%s)/mydb", dbUser, dbPass, dbHost)
// ... connection logic
}
4. Request Body Filtering
Filter sensitive fields from request logging:
func filterSensitiveFields(body []byte) ([]byte, error) {
var data map[string]interface{}
if err := json.Unmarshal(body, &data); err != nil {
return body, nil // Return original if not JSON
}
sensitiveFields := []string{"password", "secret", "token", "key", "ssn"}
for _, field := range sensitiveFields {
if _, exists := data[field]; exists {
data[field] = "[FILTERED]"
}
}
return json.Marshal(data)
}
// Use in middleware
app.Use(func(c *fiber.Ctx) error {
body, _ := c.Body()
filteredBody, _ := filterSensitiveFields(body)
logrus.Debugf("Request body: %s", filteredBody)
return c.Next()
})
5. Audit Trail Implementation
Implement secure audit logging for security events:
type AuditLog struct {
Event string `json:"event"`
UserID string `json:"user_id"`
IP string `json:"ip"`
Timestamp time.Time `json:"timestamp"`
Details string `json:"details"`
}
func logAuditEvent(event, userID, ip, details string) {
audit := AuditLog{
Event: event,
UserID: userID,
IP: ip,
Timestamp: time.Now(),
Details: details,
}
// Write to secure audit log (append-only, tamper-evident)
auditJSON, _ := json.Marshal(audit)
file, _ := os.OpenFile("audit.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
defer file.Close()
file.WriteString(string(auditJSON) + "\n")
}