Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookieHTTPOnly.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// License: LGPL-3.0 License (c) find-sec-bugs
package cookie

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse

class CookieHTTPOnly {
// {fact rule=sensitive-cookie-without-http-only-flag@v1.0 defects=1}
def danger(res: HttpServletResponse): Unit = {
// ruleid: scala_cookie_rule-CookieHTTPOnly
val cookie = new Cookie("key", "value")
cookie.setSecure(true)
cookie.setMaxAge(60)
cookie.setHttpOnly(false) // danger

res.addCookie(cookie)
}
// {/fact}

// cookie.setHttpOnly(true) is missing
// {fact rule=sensitive-cookie-without-http-only-flag@v1.0 defects=1}
def danger2(res: HttpServletResponse): Unit = {
// ruleid: scala_cookie_rule-CookieHTTPOnly
val cookie = new Cookie("key", "value")
cookie.setSecure(true)
cookie.setMaxAge(60)
res.addCookie(cookie)
}
// {/fact}
}

34 changes: 34 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookieHTTPOnly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# yamllint disable
# License: MIT (c) GitLab Inc.
# yamllint enable
---
rules:
- id: "scala_cookie_rule-CookieHTTPOnly"
languages:
- "scala"
message: |
A new cookie is created without the HttpOnly flag set. The HttpOnly flag is a directive to the
browser to make sure that the cookie can not be red by malicious script. When a user is the
target of a "Cross-Site Scripting", the attacker would benefit greatly from getting the session
id for example.
metadata:
category: "security"
cwe: "CWE-1004"
shortDescription: "Sensitive Cookie Without 'HttpOnly' Flag"
technology:
- "scala"
security-severity: "MEDIUM"
pattern-either:
- patterns:
- pattern: |
val $C = new javax.servlet.http.Cookie(..., ...);
...
$RESP.addCookie($C);
- pattern-not-inside: |
val $C = new javax.servlet.http.Cookie(..., ...);
...
$C.setHttpOnly(true);
...
$RESP.addCookie($C);
- pattern: "(javax.servlet.http.Cookie $C).setHttpOnly(false);"
severity: "WARNING"
45 changes: 45 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookieInsecure.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// License: LGPL-3.0 License (c) find-sec-bugs
package cookie

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse


class CookieInsecure {
def danger(res: HttpServletResponse): Unit = {
// {fact rule=sensitive-information-leak@v1.0 defects=1}
// ruleid: scala_cookie_rule-CookieInsecure
val cookie = new Cookie("key", "value")
cookie.setHttpOnly(true)
// {/fact}
cookie.setMaxAge(60)
// {fact rule=sensitive-information-leak@v1.0 defects=1}
// ruleid: scala_cookie_rule-CookieInsecure
cookie.setSecure(false) // danger
// {/fact}

res.addCookie(cookie)
}

// {fact rule=sensitive-information-leak@v1.0 defects=1}
// cookie.setSecure(true); is missing
def danger2(res: HttpServletResponse): Unit = {
// ruleid: scala_cookie_rule-CookieInsecure
val cookie = new Cookie("key", "value")
cookie.setHttpOnly(true)
cookie.setMaxAge(60)
res.addCookie(cookie)
}
// {/fact}

// {fact rule=sensitive-information-leak@v1.0 defects=0}
def ok(res: HttpServletResponse): Unit = {
val cookie = new Cookie("key", "value")
cookie.setHttpOnly(true)
cookie.setMaxAge(60)
cookie.setSecure(true) // safe

res.addCookie(cookie)
}
// {/fact}
}
33 changes: 33 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookieInsecure.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# yamllint disable
# License: MIT (c) GitLab Inc.
# yamllint enable
---
rules:
- id: "scala_cookie_rule-CookieInsecure"
languages:
- "scala"
message: |
"A new cookie is created without the Secure flag set. The Secure flag is a
directive to the browser to make sure that the cookie is not sent for insecure communication
(http://)"
metadata:
category: "security"
cwe: "CWE-539"
shortDescription: "Information Exposure Through Persistent Cookies"
technology:
- "scala"
security-severity: "MEDIUM"
patterns:
- pattern-not-inside: |
val $C = new javax.servlet.http.Cookie(..., ...);
...
$C.setSecure(true);
...
$RESP.addCookie($C);
- pattern-either:
- pattern: |
val $C = new javax.servlet.http.Cookie(..., ...);
...
$RESP.addCookie($C);
- pattern: "($C:javax.servlet.http.Cookie).setSecure(false);"
severity: "WARNING"
19 changes: 19 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookiePersistent.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// License: LGPL-3.0 License (c) find-sec-bugs
package cookie

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse

class CookiePersistent {
// {fact rule=insecure-cookie@v1.0 defects=1}
def danger(res: HttpServletResponse): Unit = {
val cookie = new Cookie("key", "value")
cookie.setSecure(true)
cookie.setHttpOnly(true)
// ruleid: scala_cookie_rule-CookiePersistent
cookie.setMaxAge(31536000) // danger

res.addCookie(cookie)
}
// {/fact}
}
25 changes: 25 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookiePersistent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# yamllint disable
# License: MIT (c) GitLab Inc.
# yamllint enable
---
rules:
- id: "scala_cookie_rule-CookiePersistent"
languages:
- "scala"
message: |
"Storing sensitive data in a persistent cookie for an extended period can lead to a breach of
confidentiality or account compromise."
metadata:
category: "security"
cwe: "CWE-614"
shortDescription: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute"
technology:
- "scala"
security-severity: "MEDIUM"
patterns:
- pattern: |
($C: Cookie).setMaxAge($AGE)
- metavariable-comparison:
comparison: "$AGE >= 31536000"
metavariable: "$AGE"
severity: "WARNING"
35 changes: 35 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookieUsage.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// License: LGPL-3.0 License (c) find-sec-bugs
package cookie

import javax.servlet.ServletException
import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import java.io.IOException

class CookieUsage {
@Override
@throws[ServletException]
@throws[IOException]
protected def doGet(req: HttpServletRequest, resp: HttpServletResponse): Unit = {
for (cookie <- req.getCookies) {
// {fact rule=insecure-cookie@v1.0 defects=1}
// ruleid: scala_cookie_rule-CookieUsage
cookie.getName
// {/fact}
// {fact rule=insecure-cookie@v1.0 defects=1}
// ruleid: scala_cookie_rule-CookieUsage
cookie.getValue
// {/fact}
// {fact rule=insecure-cookie@v1.0 defects=1}
// ruleid: scala_cookie_rule-CookieUsage
cookie.getPath
// {/fact}
}
}

def getCookieName(req: HttpServletRequest) = {
val c: Cookie = req.getCookies.head
c.getName
}
}
38 changes: 38 additions & 0 deletions PR_6_scala/scala/cookie/rule-CookieUsage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# yamllint disable
# License: MIT (c) GitLab Inc.
# yamllint enable
---
rules:
- id: "scala_cookie_rule-CookieUsage"
languages:
- "scala"
message: |
The information stored in a custom cookie should not be sensitive or related to the session.
In most cases, sensitive data should only be stored in session and referenced by the user's
session cookie.
metadata:
category: "security"
cwe: "CWE-614"
shortDescription: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute"
technology:
- "scala"
security-severity: "MEDIUM"
patterns:
- pattern-inside: |
def $FUNC(..., $REQ: HttpServletRequest, ...): $TYPE = {
...
}
- pattern-either:
- patterns:
- pattern-inside: |
for ($C <- $REQ.getCookies) {
...
}
- pattern-either:
- pattern: "$C.getName"
- pattern: "$C.getValue"
- pattern: "$C.getPath"
- pattern: "($C: Cookie).getName()"
- pattern: "($C: Cookie).getValue"
- pattern: "($C: Cookie).getPath"
severity: "WARNING"
80 changes: 80 additions & 0 deletions PR_6_scala/scala/cookie/rule-HttpResponseSplitting.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// License: LGPL-3.0 License (c) find-sec-bugs
package cookie

import javax.servlet.ServletException
import javax.servlet.http.Cookie
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpServletResponseWrapper
import java.io.IOException


class HttpResponseSplitting extends HttpServlet {

// {fact rule=http-response-splitting@v1.0 defects=1}
@throws[ServletException]
@throws[IOException]
override protected def doGet(req: HttpServletRequest, resp: HttpServletResponse): Unit = {
val input = req.getParameter("input")
val c = new Cookie("name", null)
// ruleid: scala_cookie_rule-HttpResponseSplitting
c.setValue(input)
c.setHttpOnly(true)
c.setSecure(true)
resp.addCookie(c)
}
// {/fact}

// {fact rule=http-response-splitting@v1.0 defects=1}
@throws[ServletException]
@throws[IOException]
override protected def doPost(req: HttpServletRequest, resp: HttpServletResponse): Unit = {
val input = req.getParameter("input")
// ruleid: scala_cookie_rule-HttpResponseSplitting
val c = new Cookie("name", input)
c.setHttpOnly(true)
c.setSecure(true)
resp.addCookie(c)
}
// {/fact}

// {fact rule=http-response-splitting@v1.0 defects=1}
@throws[ServletException]
@throws[IOException]
override protected def doDelete(req: HttpServletRequest, resp: HttpServletResponse): Unit = {
val data = req.getParameter("input")
val input = data.replaceAll("\n", "")
// ruleid: scala_cookie_rule-HttpResponseSplitting
val c = new Cookie("name", input)
c.setHttpOnly(true)
c.setSecure(true)
resp.addCookie(c)
}
// {/fact}

// {fact rule=http-response-splitting@v1.0 defects=0}
@throws[ServletException]
@throws[IOException]
override protected def doOptions(req: HttpServletRequest, resp: HttpServletResponse): Unit = { // BAD
val tainted = req.getParameter("input")
resp.setHeader("test", tainted)
// OK: False negative but reported by spotbugs
val data = req.getParameter("input")
val normalized = data.replaceAll("\n", "\n")
resp.setHeader("test", normalized)
val normalized2 = data.replaceAll("\n", req.getParameter("test"))
resp.setHeader("test2", normalized2)
// OK
val normalized3 = org.apache.commons.text.StringEscapeUtils.unescapeJava(tainted)
resp.setHeader("test3", normalized3)
val normalized4 = getString(tainted)
resp.setHeader("test4", normalized4)
val wrapper = new HttpServletResponseWrapper(resp)
wrapper.addHeader("test", tainted)
wrapper.setHeader("test2", tainted)
}
// {/fact}

private def getString(s: String) = s
}
42 changes: 42 additions & 0 deletions PR_6_scala/scala/cookie/rule-HttpResponseSplitting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# yamllint disable
# License: MIT (c) GitLab Inc.
# yamllint enable
---
rules:
- id: "scala_cookie_rule-HttpResponseSplitting"
languages:
- "scala"
message: |
When an HTTP request contains unexpected CR and LF characters, the server may respond with an
output stream that is interpreted as two different HTTP responses (instead of one). An attacker
can control the second response and mount attacks such as cross-site scripting and cache
poisoning attacks.
metadata:
category: "security"
cwe: "CWE-113"
shortDescription: "Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP
Response Splitting')"
technology:
- "scala"
security-severity: "MEDIUM"
mode: "taint"
pattern-sanitizers:
- patterns:
- pattern-inside: |-
$STR.replaceAll("$REPLACE_CHAR", "$REPLACE");
- pattern: "$STR"
- metavariable-regex:
metavariable: "$REPLACE_CHAR"
regex: "(.*\\\\r\\\\n.*)"
- metavariable-regex:
metavariable: "$REPLACE"
regex: "(?!(\\\\r\\\\n))"
- pattern: "org.owasp.encoder.Encode.forUriComponent(...)"
- pattern: "org.owasp.encoder.Encode.forUri(...)"
- pattern: "java.net.URLEncoder.encode(..., $CHARSET)"
pattern-sinks:
- pattern: "new javax.servlet.http.Cookie(\"$KEY\", ...)"
- pattern: "($C:javax.servlet.http.Cookie).setValue(...)"
pattern-sources:
- pattern: "($REQ: javax.servlet.http.HttpServletRequest).getParameter(...)"
severity: "WARNING"
Loading