An Auditor’s Checklist for Securing Shopify Backends on OVH
OVH Infrastructure Hardening for Shopify Backends
Securing a Shopify backend hosted on OVH infrastructure requires a multi-layered approach, focusing on network segmentation, access control, and continuous monitoring. This checklist assumes a typical setup involving dedicated servers or VPS instances running web servers (e.g., Nginx), database servers (e.g., MySQL), and potentially caching layers.
Network Security & Firewall Configuration
The primary defense is a robust firewall. OVH’s Advanced Firewall (formerly known as “Firewall as a Service”) offers granular control. We’ll focus on essential rules for a Shopify backend.
Ingress Rules (Allowing Traffic In)
Only essential ports should be open. For a typical Shopify setup, this includes HTTP/HTTPS for the web server and SSH for administration.
Web Server Access
Allow inbound traffic on ports 80 (HTTP) and 443 (HTTPS) from all sources. If your Shopify store has specific IP restrictions for certain operations (e.g., API integrations), these should be added as source IP whitelists.
SSH Access
Crucially, SSH access should be restricted to known administrative IP addresses. Avoid opening SSH to the entire internet (0.0.0.0/0).
Database Access
Database ports (e.g., 3306 for MySQL) should NEVER be exposed to the public internet. Access should be strictly limited to the web server(s) on the internal network or via a secure VPN/bastion host.
Egress Rules (Allowing Traffic Out)
Egress rules are often overlooked but are vital for preventing compromised systems from initiating malicious outbound connections. Allow outbound traffic only to necessary destinations:
- Outbound connections to Shopify’s API endpoints.
- DNS resolution (UDP/TCP port 53) to trusted DNS servers.
- NTP for time synchronization (UDP port 123).
- Package repository access (e.g., apt.ovh.net, deb.debian.org) for updates.
- Any other specific third-party services your backend integrates with.
OVH Firewall Configuration Example (Conceptual)
While the OVH control panel provides a GUI, the underlying rules can be conceptualized as follows. This is not direct OVH syntax but illustrates the logic.
Ingress Rules (Conceptual)
# Allow HTTP ALLOW TCP FROM ANY TO [SERVER_IP] PORT 80 # Allow HTTPS ALLOW TCP FROM ANY TO [SERVER_IP] PORT 443 # Allow SSH from specific admin IPs ALLOW TCP FROM [ADMIN_IP_1] TO [SERVER_IP] PORT 22 ALLOW TCP FROM [ADMIN_IP_2] TO [SERVER_IP] PORT 22 # Deny all other inbound traffic by default DENY ALL
Egress Rules (Conceptual)
# Allow DNS ALLOW UDP FROM ANY TO ANY PORT 53 ALLOW TCP FROM ANY TO ANY PORT 53 # Allow NTP ALLOW UDP FROM ANY TO ANY PORT 123 # Allow outbound to Shopify API IPs (requires IP lookup) ALLOW TCP FROM [SERVER_IP] TO [SHOPIFY_API_IP_RANGE] PORT 443 # Allow package updates ALLOW TCP FROM [SERVER_IP] TO [PACKAGE_REPO_IP_RANGE] PORT 80 ALLOW TCP FROM [SERVER_IP] TO [PACKAGE_REPO_IP_RANGE] PORT 443 # Deny all other outbound traffic by default DENY ALL
Server-Level Security Hardening
Beyond network firewalls, the operating system and services running on the servers must be secured.
SSH Security
Disable root login and password authentication. Use key-based authentication exclusively. Change the default SSH port (though this is security through obscurity, it reduces automated scans).
SSH Configuration (`/etc/ssh/sshd_config`)
[sshd] Port 2222 # Example: Changed from 22 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes AllowUsers your_admin_user MaxAuthTries 3 LoginGraceTime 30
After modifying, restart the SSH service: sudo systemctl restart sshd. Ensure you have tested key-based login before disconnecting your current session.
Web Server (Nginx) Configuration
Nginx should be configured to serve Shopify traffic securely and efficiently. Key security aspects include disabling unnecessary modules, enforcing HTTPS, and mitigating common web vulnerabilities.
Enforcing HTTPS and TLS Configuration
Use strong TLS protocols and cipher suites. Regularly update certificates and use tools like SSL Labs’ Server Test for an objective score.
server {
listen 80;
server_name your-shopify-domain.com;
return 301 https://$host$request_uri; # Redirect HTTP to HTTPS
}
server {
listen 443 ssl http2;
server_name your-shopify-domain.com;
ssl_certificate /etc/letsencrypt/live/your-shopify-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-shopify-domain.com/privkey.pem;
# Strong TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS (HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Other security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none';"; # CSP requires careful tuning for Shopify
# ... rest of your Shopify proxy/backend configuration ...
location / {
proxy_pass http://127.0.0.1:8080; # Example: proxy to a backend app
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Database Security (MySQL)
Secure your MySQL instance by restricting access, using strong passwords, and disabling unnecessary features.
Access Control
Ensure the MySQL server is not accessible from the public internet. If your application runs on the same server as MySQL, use `localhost` or `127.0.0.1` for the connection string. If on separate servers, use internal OVH network IPs and firewall rules.
User Privileges
Grant the minimum necessary privileges to database users. Avoid using the `root` user for application connections.
-- Example: Create a user for the Shopify app with limited privileges CREATE USER 'shopify_app'@'localhost' IDENTIFIED BY 'very_strong_password_here'; GRANT SELECT, INSERT, UPDATE, DELETE ON shopify_database.* TO 'shopify_app'@'localhost'; FLUSH PRIVILEGES;
MySQL Configuration (`my.cnf`)
Consider disabling features not required for your Shopify backend.
[mysqld] # General settings datadir=/var/lib/mysql socket=/var/run/mysqld/mysqld.sock pid-file=/var/run/mysqld/mysqld.pid # Network binding - crucial for security bind-address = 127.0.0.1 # Or internal IP if on a separate server # Disable features not needed skip-networking # If app is on the same server, this is the most secure # local-infile = 0 # Disable loading local files into the database # Logging (essential for auditing) log_error = /var/log/mysql/error.log general_log_file = /var/log/mysql/mysql.log general_log = 1 # Enable for auditing, disable in production if performance is critical and logs are managed elsewhere slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 2
Restart MySQL after changes: sudo systemctl restart mysql.
Application-Level Security
While Shopify handles much of the frontend security, your backend application logic and integrations are critical.
API Key Management
Shopify API keys (private and public) and any other sensitive credentials (e.g., for payment gateways, shipping providers) must be stored securely. Avoid hardcoding them directly in application code. Use environment variables or a dedicated secrets management system.
Example: Using Environment Variables (PHP)
<?php // Load environment variables from .env file (using a library like vlucas/phpdotenv) $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv->load(); $shopifyApiKey = $_ENV['SHOPIFY_API_KEY']; $shopifyApiSecret = $_ENV['SHOPIFY_API_SECRET']; $shopifyAccessToken = $_ENV['SHOPIFY_ACCESS_TOKEN']; // Use these variables to authenticate with Shopify API // ... ?>
Ensure the `.env` file is NOT committed to version control and has restrictive file permissions (e.g., chmod 600 .env).
Input Validation and Sanitization
All data received from Shopify webhooks, API requests, or user input must be rigorously validated and sanitized to prevent injection attacks (SQLi, XSS, etc.).
Rate Limiting and Throttling
Implement rate limiting on your backend API endpoints to protect against brute-force attacks and denial-of-service attempts, especially for authentication endpoints or webhook receivers.
Logging and Monitoring
Comprehensive logging and proactive monitoring are essential for detecting and responding to security incidents.
System Logs
Ensure that system logs (syslog, auth.log, Nginx access/error logs, MySQL error logs) are enabled, rotated, and stored securely. Consider forwarding critical logs to a centralized, immutable log management system.
Application Logs
Your application should log security-relevant events: authentication attempts (success/failure), API calls, data modifications, and any errors.
Example: Logging in PHP
<?php
// Using Monolog for structured logging
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('security');
$log->pushHandler(new StreamHandler('/var/log/your_app/security.log', Logger::INFO));
// Example: Log a failed login attempt
$userId = '[email protected]';
$ipAddress = $_SERVER['REMOTE_ADDR'];
$log->warning('Failed login attempt', [
'user' => $userId,
'ip' => $ipAddress,
'timestamp' => date('Y-m-d H:i:s')
]);
// Example: Log a successful API call
$shopDomain = 'your-store.myshopify.com';
$endpoint = '/admin/api/2023-10/orders.json';
$log->info('Shopify API call successful', [
'shop' => $shopDomain,
'endpoint' => $endpoint,
'timestamp' => date('Y-m-d H:i:s')
]);
?>
Intrusion Detection/Prevention Systems (IDS/IPS)
Consider deploying host-based IDS/IPS solutions like Fail2ban to monitor logs for suspicious activity (e.g., repeated failed SSH logins, web server attack patterns) and automatically block offending IP addresses.
Fail2ban Configuration Example
Create custom jails for your specific application logs.
[DEFAULT] bantime = 1h findtime = 10m maxretry = 5 banaction = iptables-multiport [sshd] enabled = true port = 2222 # Your custom SSH port filter = sshd logpath = /var/log/auth.log [nginx-badbots] enabled = true port = http,https filter = nginx-badbots logpath = /var/log/nginx/access.log maxretry = 100 # Adjust based on traffic volume bantime = 1d
You’ll need to create corresponding filter files (e.g., `/etc/fail2ban/filter.d/nginx-badbots.conf`) to define patterns for malicious requests.
Regular Auditing and Updates
Security is an ongoing process. Regular audits and timely updates are non-negotiable.
Vulnerability Scanning
Periodically scan your OVH infrastructure and applications for known vulnerabilities using tools like Nessus, OpenVAS, or OWASP ZAP.
Patch Management
Maintain a strict patch management policy for the operating system, web server, database, and any application dependencies. Automate updates where feasible, but always test in a staging environment first.
Configuration Audits
Regularly review firewall rules, SSH configurations, web server settings, and database user privileges to ensure they align with security best practices and your organization’s policies.
Access Reviews
Periodically review who has access to your OVH control panel, servers (SSH keys, user accounts), and sensitive credentials. Revoke access for former employees or unnecessary accounts immediately.