2022-07-04 10:29:30 +02:00
=== How to fix it in Core PHP
The following code is vulnerable to cross-site scripting because it returns an HTML response that contains user input.
User input embedded in HTML code should be HTML-encoded to prevent the injection of additional code.
PHP provides the built-in function `htmlspecialchars` to do this.
2022-07-04 14:52:28 +02:00
[cols="a"]
2022-07-04 10:29:30 +02:00
|===
2022-07-04 14:52:28 +02:00
h| Non-compliant code example
2022-07-04 10:29:30 +02:00
|
[source,php]
----
echo '<h1>' . $input . '</h1>'; // Noncompliant
----
2022-07-04 14:52:28 +02:00
h| Compliant solution
2022-07-04 10:29:30 +02:00
|
[source,php]
----
echo '<h1>' . htmlspecialchars($input) . '</h1>';
----
|===
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response with the content-type header.
For example, setting the content-type to `text/plain` using the built-in `header` function allows to safely reflect user input since browsers will not try to parse and execute the response.
2022-07-04 14:52:28 +02:00
[cols="a"]
2022-07-04 10:29:30 +02:00
|===
2022-07-04 14:52:28 +02:00
h| Non-compliant code example
2022-07-04 10:29:30 +02:00
|
[source,php]
----
echo $input; // Noncompliant
----
2022-07-04 14:52:28 +02:00
h| Compliant solution
2022-07-04 10:29:30 +02:00
|
[source,php]
----
header('Content-Type: text/plain');
echo $input;
----
|===
=== How does this work?
include::../../common/fix/data_encoding.adoc[]
=== Pitfalls
include::../../common/pitfalls/content-types.adoc[]
==== Single quoted variables in attributes
By default, `htmlspecialchars` does not encode single quotes, so if `++$input++` is untrusted, JavaScript code can be injected.
Make sure to set the option `ENT_QUOTES` to encode single quotes.
2022-07-04 14:52:28 +02:00
[cols="a"]
2022-07-04 10:29:30 +02:00
|===
2022-07-04 14:52:28 +02:00
h| Non-compliant code example
2022-07-04 10:29:30 +02:00
|
[source,php]
----
echo "<img src='" . htmlspecialchars($input) . "'>";
----
2022-07-04 14:52:28 +02:00
h| Compliant solution
2022-07-04 10:29:30 +02:00
|
[source,php]
----
echo "<img src='" . htmlspecialchars($input, ENT_QUOTES) . "'>";
----
|===
==== Headers and output
If the HTTP body is sent before `header` is called, no headers will be sent to the client.
To fix this issue, send the headers before any output.
2022-07-04 14:52:28 +02:00
[cols="a"]
2022-07-04 10:29:30 +02:00
|===
2022-07-04 14:52:28 +02:00
h| Non-compliant code example
2022-07-04 10:29:30 +02:00
|
[source,php]
----
echo 'No more headers at this point';
header('Content-Type: text/plain');
echo $input;
----
2022-07-04 14:52:28 +02:00
h| Compliant solution
2022-07-04 10:29:30 +02:00
|
[source,php]
----
header('Content-Type: text/plain');
echo $input;
----
|===
2022-09-13 16:28:34 +02:00
=== Going the extra mile
include::../../common/extra-mile/csp.adoc[]