diff --git a/docs/header_names/allowed_framework_names.adoc b/docs/header_names/allowed_framework_names.adoc index d91acac3d7a..8bfffe474f5 100644 --- a/docs/header_names/allowed_framework_names.adoc +++ b/docs/header_names/allowed_framework_names.adoc @@ -54,6 +54,7 @@ * Jdom2 * JSP * Legacy Mongo Java API +* NanoHTTPD * OkHttp * OpenAI * Realm diff --git a/rules/S5131/java/how-to-fix-it/nanohttpd.adoc b/rules/S5131/java/how-to-fix-it/nanohttpd.adoc new file mode 100644 index 00000000000..220b2a242d7 --- /dev/null +++ b/rules/S5131/java/how-to-fix-it/nanohttpd.adoc @@ -0,0 +1,106 @@ +== How to fix it in a NanoHTTPD + +=== Code examples + +The following code is vulnerable to cross-site scripting because it returns an HTML response that contains user input. + +Third-party data, such as user input, is not to be trusted. If embedded in HTML code, it should be HTML-encoded to prevent the injection of additional code. +This can be done with the https://owasp.org/www-project-java-encoder/[OWASP Java Encoder] or similar libraries. + +==== Noncompliant code example + +[source,java,diff-id=41,diff-type=noncompliant] +---- +import fi.iki.elonen.NanoHTTPD; + +public class App extends NanoHTTPD { + + @Override + public Response serve(IHTTPSession session) { + String name = session.getParms().get("input"); + return newFixedLengthResponse( // Noncompliant + "

Hello, " + name + "!

" + ); + } +} +---- + +==== Compliant solution + +[source,java,diff-id=41,diff-type=compliant] +---- +import fi.iki.elonen.NanoHTTPD; +import org.owasp.encoder.Encode; + +public class App extends NanoHTTPD { + + @Override + public Response serve(IHTTPSession session) { + String name = session.getParms().get("input"); + return newFixedLengthResponse( + "

Hello, " + Encode.forHtml(name) + "!

" + ); + } +} +---- + +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` allows to safely reflect user input. +In this case, browsers will not try to parse and execute the response. + +==== Noncompliant code example + +[source,java,diff-id=42,diff-type=noncompliant] +---- +import fi.iki.elonen.NanoHTTPD; + +public class App extends NanoHTTPD { + + @Override + public Response serve(IHTTPSession session) { + String name = session.getParms().get("input"); + return newFixedLengthResponse( // Noncompliant - text/html by default + "Hello, " + name + "!" + ); + } +} +---- + +==== Compliant solution + +[source,java,diff-id=42,diff-type=compliant] +---- +import fi.iki.elonen.NanoHTTPD; +import fi.iki.elonen.NanoHTTPD.Response.Status; + +public class App extends NanoHTTPD { + + @Override + public Response serve(IHTTPSession session) { + String name = session.getParms().get("input"); + return newFixedLengthResponse( + Status.OK, + "text/plain", + "Hello, " + name + "!" + ); + } +} +---- + +=== How does this work? + +include::../../common/fix/data_encoding.adoc[] + +`org.owasp.encoder.Encode.forHtml` is the recommended method to encode HTML entities. + +=== Pitfalls + +include::../../common/pitfalls/content-types.adoc[] + +include::../../common/pitfalls/validation.adoc[] + +=== Going the extra mile + +include::../../common/extra-mile/csp.adoc[] + diff --git a/rules/S5131/java/rule.adoc b/rules/S5131/java/rule.adoc index d192e851f30..3196ef6e983 100644 --- a/rules/S5131/java/rule.adoc +++ b/rules/S5131/java/rule.adoc @@ -16,6 +16,8 @@ include::how-to-fix-it/spring.adoc[] include::how-to-fix-it/thymeleaf.adoc[] +include::how-to-fix-it/nanohttpd.adoc[] + == Resources include::../common/resources/docs.adoc[] diff --git a/rules/S5131/kotlin/how-to-fix-it/nanohttpd.adoc b/rules/S5131/kotlin/how-to-fix-it/nanohttpd.adoc new file mode 100644 index 00000000000..a24e95daa5c --- /dev/null +++ b/rules/S5131/kotlin/how-to-fix-it/nanohttpd.adoc @@ -0,0 +1,106 @@ +== How to fix it in a NanoHTTPD + +=== Code examples + +The following code is vulnerable to cross-site scripting because it returns an HTML response that contains user input. + +Third-party data, such as user input, is not to be trusted. If embedded in HTML code, it should be HTML-encoded to prevent the injection of additional code. +This can be done with the https://owasp.org/www-project-java-encoder/[OWASP Java Encoder] or similar libraries. + +==== Noncompliant code example + +[source,kotlin,diff-id=41,diff-type=noncompliant] +---- +import fi.iki.elonen.NanoHTTPD + +class App : NanoHTTPD() { + + @Override + fun serve(session: IHTTPSession): Response { + val name = session.getParms().get("input"); + return newFixedLengthResponse( // Noncompliant + "

Hello, $name!

" + ); + } +} +---- + +==== Compliant solution + +[source,kotlin,diff-id=41,diff-type=compliant] +---- +import fi.iki.elonen.NanoHTTPD +import org.owasp.encoder.Encode + +class App : NanoHTTPD() { + + @Override + fun serve(session: IHTTPSession): Response { + val name = session.getParms().get("input"); + return newFixedLengthResponse( + "

Hello, ${Encode.forHtml(name)}!

" + ); + } +} +---- + +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` allows to safely reflect user input. +In this case, browsers will not try to parse and execute the response. + +==== Noncompliant code example + +[source,kotlin,diff-id=42,diff-type=noncompliant] +---- +import fi.iki.elonen.NanoHTTPD + +class App : NanoHTTPD() { + + @Override + fun serve(session: IHTTPSession): Response { + val name = session.getParms().get("input"); + return newFixedLengthResponse( // Noncompliant - text/html by default + "Hello, $name!" + ); + } +} +---- + +==== Compliant solution + +[source,kotlin,diff-id=42,diff-type=compliant] +---- +import fi.iki.elonen.NanoHTTPD +import fi.iki.elonen.NanoHTTPD.Response.Status + +class App : NanoHTTPD() { + + @Override + fun serve(session: IHTTPSession): Response { + val name = session.getParms().get("input"); + return newFixedLengthResponse( + Status.OK, + "text/plain", + "Hello, $name!" + ); + } +} +---- + +=== How does this work? + +include::../../common/fix/data_encoding.adoc[] + +`org.owasp.encoder.Encode.forHtml` is the recommended method to encode HTML entities. + +=== Pitfalls + +include::../../common/pitfalls/content-types.adoc[] + +include::../../common/pitfalls/validation.adoc[] + +=== Going the extra mile + +include::../../common/extra-mile/csp.adoc[] + diff --git a/rules/S5131/kotlin/rule.adoc b/rules/S5131/kotlin/rule.adoc index dd0abf95fae..ca679d04bfe 100644 --- a/rules/S5131/kotlin/rule.adoc +++ b/rules/S5131/kotlin/rule.adoc @@ -12,6 +12,8 @@ include::how-to-fix-it/servlet.adoc[] include::how-to-fix-it/spring.adoc[] +include::how-to-fix-it/nanohttpd.adoc[] + == Resources include::../common/resources/docs.adoc[]