# Header Injection
**Header injection** vulnerabilities occur when HTTP response headers are constructed from untrusted input. Header injection can be used by an attacker to send additional, malicious HTTP responses to a victim’s browser.
## Header Injection in Python
Consider the following code that takes the `language` parameter from the query string of the HTTP request and writes it out it to the `Content-Language` header:
“`python @app.route(‘/’) def home(): language = request.args[‘language’] or ‘en-us’response = render_welcome_page(language) response.headers = { ‘Content-Language’ : language } return response |
This code is intended to take a request with a language in the query string:
“` ?language=en-us “` |
And write the corresponding header in the HTTP response:
“` Content-Language: en-us “` |
However, the code does not strip out new-line characters, which means a URL with the following form:
“` ?language=en-us\nHTTP/1.1+200+OK “` |
…can be used to by an attacker to generate two separate HTTP responses, the second of which is under full control of an attacker. This is called **HTTP response splitting**, and can be used to launch various types of attack:
* *Cross-site scripting* (XSS) attacks, where malicious JavaScript code is sent to the victim’s browser and executed under your web-domain.
* *Cache-poisoning* attacks, where any downstream caching servers will have malicious content injected into them. This will affect subsequent victims that visit the same poisoned resource within the caching period.
* *Malware delivery*, whereby the second HTTP response contains a malicious payload, like a PDF file that takes advantage of vulnerabilities in common PDF viewing software.
## Mitigation
* Avoid writing untrusted content into HTTP responses headers wherever possible.
* Strip new-line characters from any content written to HTTP headers.
* Where the HTTP response header is generated from untrusted input, validate the input value against a server-side list of allowed values before generating the header value. In the code example above, the `langage` parameter should be checked against a list of valid language values.
## CWEs
* [CWE-644](https://cwe.mitre.org/data/definitions/644.html)