Best 7 Tips to Prevent HTTP Response Splitting in TypeScript ERP
Introduction to HTTP Response Splitting
HTTP Response Splitting is a critical vulnerability caused by improper handling of user inputs in HTTP headers. When an attacker injects newline (\r\n
) characters into user input, it can lead to malicious manipulation of HTTP responses. This vulnerability is particularly dangerous in ERP systems built with TypeScript, where dynamic handling of headers is often implemented.
In this guide, we’ll:
- Explain HTTP Response Splitting in depth.
- Provide 7 actionable tips to mitigate the risk.
- Share real-world coding examples in TypeScript to help developers secure their ERP systems.
- Showcase how our free Website Security Scanner can identify such vulnerabilities.
What Is HTTP Response Splitting?
HTTP Response Splitting happens when user-supplied data is directly included in an HTTP header without sanitization. Malicious input like \r\n
can break the response into two or more parts, allowing attackers to:
- Inject malicious headers.
- Perform Cross-Site Scripting (XSS) or Cache Poisoning attacks.
- Redirect users to untrusted websites.
For example, consider the following TypeScript code:
import { Response } from "express";
function vulnerableEndpoint(req: any, res: Response) {
const userInput = req.query.redirect;
res.setHeader("Location", userInput); // Vulnerable to HTTP Response Splitting
res.status(302).end();
}
If redirect
contains malicious input like:
http://example.com%0D%0ASet-Cookie:malicious=true
The server will process it as two headers, enabling the attacker to manipulate the HTTP response.
7 Tips to Prevent HTTP Response Splitting in TypeScript
1. Sanitize All User Inputs
Sanitization ensures special characters like \r
, \n
, and %0D%0A
are removed from user inputs.
Fixed Example:
function sanitizeInput(input: string): string {
return input.replace(/[\r\n]/g, ""); // Removes CRLF characters
}
function secureEndpoint(req: any, res: Response) {
const userInput = sanitizeInput(req.query.redirect);
res.setHeader("Location", encodeURIComponent(userInput));
res.status(302).end();
}
By removing malicious characters, the risk of splitting is mitigated.
2. Use Encoding Functions
Always encode untrusted data before using it in HTTP headers.
Example Using encodeURIComponent
:
function encodeInput(req: any, res: Response) {
const userInput = req.query.redirect;
res.setHeader("Location", encodeURIComponent(userInput));
res.status(302).end();
}
This ensures that unsafe characters like \r
and \n
are safely encoded.
3. Implement Middleware for Validation
A centralized middleware can sanitize all inputs before they reach the endpoint.
Example Middleware:
import { Request, Response, NextFunction } from "express";
function inputSanitizer(req: Request, res: Response, next: NextFunction) {
for (const key in req.query) {
if (typeof req.query[key] === "string") {
req.query[key] = req.query[key].replace(/[\r\n]/g, ""); // Sanitize inputs
}
}
next();
}
// Apply middleware to all routes
app.use(inputSanitizer);
app.get("/endpoint", (req: Request, res: Response) => {
const redirectUrl = req.query.redirect || "/";
res.setHeader("Location", encodeURIComponent(redirectUrl));
res.status(302).end();
});
4. Restrict User Input Format
Use regular expressions to ensure inputs conform to safe formats.
Example with Regex Validation:
function validateInput(input: string): boolean {
const pattern = /^[a-zA-Z0-9-_:/?&=.]*$/; // Only allow safe URL characters
return pattern.test(input);
}
function safeEndpoint(req: any, res: Response) {
const userInput = req.query.redirect;
if (!validateInput(userInput)) {
res.status(400).send("Invalid input");
return;
}
res.setHeader("Location", encodeURIComponent(userInput));
res.status(302).end();
}
5. Use TypeScript’s Type System
Leverage TypeScript to enforce stricter input handling.
Example with Strong Types:
type SafeInput = string & { __safeInputBrand: void };
function sanitizeAndBrandInput(input: string): SafeInput {
const sanitized = input.replace(/[\r\n]/g, "") as SafeInput;
return sanitized;
}
function endpoint(req: any, res: Response) {
const userInput = sanitizeAndBrandInput(req.query.redirect);
res.setHeader("Location", encodeURIComponent(userInput));
res.status(302).end();
}
6. Automate Security Testing
Run automated tests to ensure new code does not introduce vulnerabilities.
Example Test with Mocha and Chai:
import chai from "chai";
import chaiHttp from "chai-http";
chai.use(chaiHttp);
describe("HTTP Response Splitting Prevention", () => {
it("should sanitize input to prevent CRLF injection", (done) => {
chai.request(app)
.get("/endpoint?redirect=/safe-url%0d%0aMalicious")
.end((err, res) => {
chai.expect(res.status).to.equal(302);
chai.expect(res.header["location"]).to.not.include("Malicious");
done();
});
});
});
7. Leverage Security Tools
Scan your ERP system regularly with our free tool to check Website Vulnerability.
Screenshot 1: Free Tool Webpage
Screenshot 2: Vulnerability Report
Additional Resources
Check out these related posts for more insights:
- Prevent Insecure Deserialization in TypeScript
- Prevent Host Header Injection in TypeScript
- Prevent Open Redirect in TypeScript
- SQL Injection (SQLi) in Laravel
For detailed insights, visit our blog archive: CyberSrely Blog.
Also, read our guide on Fixing Insecure Deserialization in OpenCart.
Conclusion
Securing ERP systems against HTTP Response Splitting is critical. By sanitizing inputs, encoding data, and leveraging security tools, you can protect your application from this and related vulnerabilities. Start by scanning your website today with our Website Security Checker.