Implementing CSRF Protection in a Go Web Application
Cross-Site Request Forgery (CSRF) is a serious security vulnerability that allows malicious websites to trick users into performing actions they didn't intend to on a trusted site. This challenge asks you to implement CSRF protection in a simple Go web application using a token-based approach. Protecting against CSRF is crucial for maintaining the integrity and security of web applications.
Problem Description
You are tasked with building a basic Go web application that includes CSRF protection. The application should have a form that allows users to submit data. To prevent CSRF attacks, you need to generate a unique, unpredictable token for each user session and include it in the form. When the form is submitted, the application must verify that the submitted token matches the token stored in the user's session. If the tokens don't match, the request should be rejected.
Key Requirements:
- Token Generation: Implement a function to generate a secure, random CSRF token.
- Token Storage: Store the generated token in the user's session. For simplicity, assume a basic in-memory session store.
- Token Inclusion: Embed the CSRF token as a hidden field in the HTML form.
- Token Verification: Verify the submitted token against the token stored in the session.
- Error Handling: Return an appropriate error response (e.g., HTTP 403 Forbidden) if the token is invalid.
- Session Management: Implement basic session management to store and retrieve tokens.
Expected Behavior:
- When a user visits the application, a unique CSRF token should be generated and stored in their session.
- The application should render a form containing a hidden input field with the CSRF token.
- When the user submits the form, the application should retrieve the token from the session and compare it to the token submitted in the form.
- If the tokens match, the request should be processed successfully.
- If the tokens do not match, the application should return a 403 Forbidden error.
Edge Cases to Consider:
- Session Expiration: What happens if the user's session expires before they submit the form? (For this challenge, assume the session is always active during the form submission.)
- Token Reuse: Ensure that tokens are not reused across multiple requests.
- Token Length: The token should be sufficiently long and random to prevent brute-force attacks.
Examples
Example 1:
Input: User visits the application, a token "abc123xyz" is generated and stored in the session. The form is rendered with a hidden input: <input type="hidden" name="csrf_token" value="abc123xyz">. User submits the form with csrf_token=abc123xyz.
Output: 200 OK (successful form submission)
Explanation: The submitted token matches the token in the session.
Example 2:
Input: User visits the application, a token "def456uvw" is generated and stored in the session. User copies the CSRF token from the HTML and submits the form with csrf_token=abc123xyz (a different token).
Output: 403 Forbidden
Explanation: The submitted token does not match the token in the session.
Example 3: (Edge Case - Token Tampering)
Input: User visits the application, a token "ghi789rst" is generated and stored in the session. User submits the form with csrf_token=ghi789rsq (slightly modified token).
Output: 403 Forbidden
Explanation: Even a slight modification to the token will result in a mismatch and a 403 error.
Constraints
- Token Length: The generated CSRF token should be at least 32 characters long.
- Randomness: The token generation should use a cryptographically secure random number generator.
- Session Storage: For simplicity, use an in-memory session store. Do not implement a persistent session store.
- Input Validation: Assume the
csrf_tokenparameter is always present in the POST request. (Focus on the CSRF protection logic, not extensive input validation.) - Performance: The token generation and verification should be efficient enough for a typical web application.
Notes
- You can use the
crypto/randpackage in Go for generating secure random numbers. - Consider using a library like
gorilla/sessionsfor session management, although a simple in-memory implementation is acceptable for this challenge. - Focus on the core CSRF protection logic. You don't need to implement a full-fledged web application with user authentication or other features.
- The goal is to demonstrate your understanding of CSRF vulnerabilities and how to mitigate them using tokens.
- Think about how to handle potential errors during token generation or session retrieval.