Sec Code
SECURE CODING
A Comprehensive Guide to Writing Secure Frontend, Backend, and API Code
Introduction
In today’s interconnected world, where applications operate on both the client and server sides and communicate through APIs, securing your code is crucial. Cybercriminals are always finding new ways to exploit vulnerabilities, so developers need to stay ahead by writing secure code. This blog explores common vulnerabilities listed in the OWASP Top 10, discusses API security concerns, and offers clear examples of both insecure and secure coding practices. By following the tips in this blog, you can better protect your applications from being compromised.
- Frontend Security
A. Cross-Site Scripting (XSS)
Insecure Code Example:
const userInput = document.getElementById("comment").value;
document.getElementById("commentDisplay").innerHTML = userInput;
Secure Code Example:
const userInput = document.getElementById("comment").value;
document.getElementById("commentDisplay").textContent = userInput;
Explanation: Replace innerHTML with textContent to prevent script injection. Implementing a Content Security Policy (CSP) adds an additional layer of defense.
B. Cross-Site Request Forgery (CSRF)
Insecure Code Example:
fetch('/updatePassword', {
method: 'POST',
body: JSON.stringify({ password: newPassword }),
});
Secure Code Example:
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
fetch('/updatePassword', {
method: 'POST',
headers: { 'CSRF-Token': csrfToken },
body: JSON.stringify({ password: newPassword }),
});
Explanation: Use CSRF tokens to verify the legitimacy of requests and prevent unauthorized actions.
C. Insecure Data Storage
Insecure Code Example:
localStorage.setItem('authToken', userAuthToken);
Secure Code Example:
const encryptedToken = encrypt(userAuthToken);
localStorage.setItem('authToken', encryptedToken);
Explanation: Encrypt sensitive data before storing it, and consider alternatives like HttpOnly cookies for session tokens.
D. Clickjacking
Insecure Code Example:
<iframe src="https://example.com"></iframe>
Secure Code Example:
<meta http-equiv="X-Frame-Options" content="DENY">
Explanation: Prevent your site from being embedded in iframes to protect against clickjacking.
- Backend Security
A. SQL Injection
Insecure Code Example:
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);
Secure Code Example:
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
Explanation: Use prepared statements to prevent attackers from injecting malicious SQL code.
B. Insecure Deserialization
Insecure Code Example:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.data"));
User user = (User) ois.readObject();
Secure Code Example:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.data"));
if (ois.readObject() instanceof User) {
User user = (User) ois.readObject();
} else {
throw new SecurityException("Invalid object deserialization");
}
Explanation: Implement strict type checks during deserialization to avoid executing malicious objects.
C. Command Injection
Insecure Code Example:
os.system(f"rm {user_input}")
Secure Code Example:
import shlex
subprocess.run(["rm", shlex.quote(user_input)])
Explanation: Use subprocess with shlex.quote() to sanitize inputs and prevent command injection.
D. Broken Authentication
Insecure Code Example:
session['user'] = user_id
Secure Code Example:
session['user'] = generate_secure_session_id(user_id)
Explanation: Ensure session IDs are securely generated and stored using secure cookies.
E. Security Misconfiguration
Insecure Configuration Example:
ini_set('display_errors', 1);
Secure Configuration Example:
ini_set('display_errors', 0);
error_log("Error message logged securely.");
Explanation: Disable error display in production environments and log errors securely.
- API Security
APIs are a critical component of modern applications, serving as the glue between different systems and services. However, they are also a common target for attackers. Ensuring API security is crucial to maintaining the overall security of your application. A. Broken Object-Level Authorization (BOLA)
Insecure Code Example:
# Fetching resource without authorization check
user_data = get_user_data(user_id)
Secure Code Example:
if current_user.id == user_id or current_user.is_admin:
user_data = get_user_data(user_id)
else:
raise UnauthorizedAccessError()
Explanation: Ensure that users can only access resources they are authorized to view. Implement checks based on user roles and permissions.
B. Excessive Data Exposure
Insecure Code Example:
return jsonify(user_data)
Secure Code Example:
return jsonify({ "name": user_data["name"], "email": user_data["email"] })
Explanation: Avoid returning unnecessary data in API responses. Limit the exposure of sensitive information.
C. Lack of Rate Limiting
Insecure Code Example:
# No rate limiting applied
@app.route('/login', methods=['POST'])
def login():
# authentication logic
Secure Code Example:
@app.route('/login', methods=['POST'])
@limiter.limit("5 per minute")
def login():
# authentication logic
Explanation: Implement rate limiting to protect against brute force attacks and denial of service (DoS) attacks.
D. Mass Assignment
Insecure Code Example:
user.update(params)
Secure Code Example:
user.update(params.permit(:name, :email))
Explanation: Prevent attackers from updating unintended model attributes by whitelisting allowed parameters.
A. Input Validation and Sanitization
Insecure Practice:
const userInput = req.body.input;
Secure Practice:
const userInput = sanitize(req.body.input);
if (!validate(userInput)) {
throw new Error("Invalid input");
}
Explanation: Always validate and sanitize user inputs to prevent injections and other attacks.
B. Authentication & Authorization
Insecure Practice:
if user.is_admin():
# Perform action
Secure Practice:
if user.is_authenticated() and user.has_permission("perform_action"):
# Perform action
Explanation: Implement robust authentication mechanisms and enforce strict access control with role-based access controls (RBAC).
C. Secure Configuration
Insecure Configuration:
server {
listen 80;
server_name example.com;
}
Secure Configuration:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
}
Explanation: Always serve your application over HTTPS and use
- Server-Side Security
Server-side vulnerabilities can have a devastating impact if left unaddressed. Here are some common server-side misconfigurations and vulnerabilities, along with examples and mitigation strategies. A. Security Misconfiguration
Insecure Configuration Example:
server {
listen 80;
server_name example.com;
root /var/www/html;
autoindex on;
}
Why It’s Vulnerable:
Default Settings: Leaving default settings unchanged can expose your server to unnecessary risks. Autoindexing Enabled: This setting allows anyone to browse the directory structure, potentially exposing sensitive files.
Secure Configuration Example:
server {
listen 443 ssl;
server_name example.com;
root /var/www/html;
autoindex off;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
}
Explanation: Secure your server by: Disabling directory autoindexing to prevent unauthorized access to files. Enforcing HTTPS and using security headers to protect against common attacks.
B. Unpatched Software and Components
Insecure Example: Running an outdated version of a web server (e.g., Apache or Nginx) or using libraries with known vulnerabilities.
Why It’s Vulnerable: Attackers can exploit known vulnerabilities in outdated software to gain unauthorized access or execute malicious code.
Secure Example: Regularly update and patch all software components, including the operating system, web servers, and application dependencies.
Explanation: Keeping your software up-to-date with the latest security patches is one of the most effective ways to protect against server-side attacks.
C. Insecure File Uploads
Insecure Code Example:
if (isset($_FILES['file'])) {
move_uploaded_file($_FILES['file']['tmp_name'], '/uploads/' . $_FILES['file']['name']);
}
Why It’s Vulnerable: If file types are not validated, attackers can upload malicious files (e.g., PHP scripts) that can be executed on the server.
Secure Code Example:
$allowed_types = array('image/jpeg', 'image/png', 'application/pdf');
if (isset($_FILES['file']) && in_array($_FILES['file']['type'], $allowed_types)) {
$filename = basename($_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], '/uploads/' . $filename);
}
Explanation: Validate file types and use secure file handling practices to prevent attackers from uploading and executing malicious files.
D. Server-Side Request Forgery (SSRF)
Insecure Code Example:
import requests
url = request.GET.get('url')
response = requests.get(url)
Why It’s Vulnerable: SSRF occurs when an attacker can manipulate URLs to make the server send requests to internal systems or other unintended locations, potentially exposing sensitive data.
Secure Code Example:
import requests
allowed_domains = ['example.com']
url = request.GET.get('url')
domain = urlparse(url).netloc
if domain in allowed_domains:
response = requests.get(url)
else:
raise Exception("Unauthorized domain")
Explanation: Restrict external requests to whitelisted domains, and validate URLs before making server-side requests.
E. Insecure Server-Side Logging
Insecure Example:
$error = "Error processing request for user: " . $_GET['user'];
file_put_contents('error_log.txt', $error, FILE_APPEND);
Why It’s Vulnerable: Logging user inputs directly without sanitization can result in log injection attacks, where attackers insert malicious data into logs.
Secure Example:
$user = htmlspecialchars($_GET['user'], ENT_QUOTES, 'UTF-8');
$error = "Error processing request for user: " . $user;
file_put_contents('error_log.txt', $error, FILE_APPEND);
Explanation: Sanitize all inputs before logging to prevent attackers from injecting malicious code or manipulating log files.
F. Insecure Default Configurations
Insecure Example:
Using default credentials for administrative interfaces (e.g., admin:admin).
Why It's Vulnerable:
Attackers often target default configurations to gain unauthorized access.
Secure Example:
Always change default credentials and secure administrative interfaces with strong, unique passwords.
Explanation: Default configurations are a common entry point for attackers. Securing them is critical to maintaining the overall security of your server.
- Service-Side Vulnerabilities
Services running on your server, such as databases, web servers, and other third-party services, can also introduce vulnerabilities if not properly configured and secured. A. Open Ports and Services
Insecure Example:
Leaving unnecessary ports and services open and exposed to the internet.
Why It's Vulnerable:
Open ports and services can be targeted by attackers for exploitation, leading to unauthorized access or denial of service.
Secure Example:
Use a firewall to block unnecessary ports and disable services that are not in use.
Explanation: Minimizing the attack surface by only allowing essential services to run and blocking unused ports reduces the risk of exploitation.
B. Weak Network Segmentation
Insecure Example:
Placing sensitive services (e.g., databases) on the same network segment as public-facing services.
Why It's Vulnerable:
If attackers compromise a public-facing service, they could gain access to more sensitive internal services.
Secure Example:
Implement strong network segmentation by isolating sensitive services in separate network zones with strict access controls.
Explanation: Network segmentation limits the lateral movement of attackers and protects sensitive data by separating it from public-facing services.
C. Misconfigured Security Services
Insecure Example:
Misconfigured Web Application Firewalls (WAFs) or Intrusion Detection Systems (IDS) that generate excessive false positives or are too lenient.
Why It's Vulnerable:
Misconfigured security services may fail to block legitimate threats or create alert fatigue, leading to missed detections.
Secure Example:
Regularly review and fine-tune security service configurations to balance security and usability.
Explanation: Properly configuring security services ensures they effectively protect against threats while minimizing false positives.
D. Weak Authentication for Services
Insecure Example: Using weak or no authentication for services like databases, APIs, or remote access tools.
Why It's Vulnerable: Weak or absent authentication mechanisms can be easily bypassed, granting attackers access to critical services.
Secure Example: Implement strong, multi-factor authentication for all service access points.
Explanation: Enforcing strong authentication protects your services from unauthorized access and potential breaches.
Conclusion
Security is a shared responsibility that spans across frontend, backend, server, and service-side components. By understanding the vulnerabilities discussed in this blog and implementing the recommended security practices, you can significantly reduce the risk of your applications and infrastructure being compromised. Always remember to stay vigilant, keep your systems updated, and continuously improve your security posture to protect against emerging threats.
This comprehensive guide aims to empower developers and system administrators to build and maintain secure applications that stand strong against the ever-evolving landscape of cyber threats.