scala.play.security.tainted-slick-sqli.tainted-slick-sqli

Author
unknown
Download Count*
License
Detected a tainted SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Avoid using using user input for generating SQL strings.
Run Locally
Run in CI
Defintion
rules:
- id: tainted-slick-sqli
mode: taint
metadata:
references:
- https://scala-slick.org/doc/3.3.3/sql.html#splicing-literal-values
- https://scala-slick.org/doc/3.2.0/sql-to-slick.html#non-optimal-sql-code
category: security
cwe:
- "CWE-89: Improper Neutralization of Special Elements used in an SQL
Command ('SQL Injection')"
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
technology:
- scala
- slick
- play
confidence: HIGH
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
message: Detected a tainted SQL statement. This could lead to SQL injection if
variables in the SQL statement are not properly sanitized. Avoid using
using user input for generating SQL strings.
pattern-sources:
- patterns:
- pattern-either:
- patterns:
- pattern: $REQ
- pattern-either:
- pattern-inside: |
Action {
$REQ: Request[$T] =>
...
}
- pattern-inside: |
Action(...) {
$REQ: Request[$T] =>
...
}
- pattern-inside: |
Action.async {
$REQ: Request[$T] =>
...
}
- pattern-inside: |
Action.async(...) {
$REQ: Request[$T] =>
...
}
- patterns:
- pattern: $PARAM
- pattern-either:
- pattern-inside: |
def $CTRL(..., $PARAM: $TYPE, ...) = Action {
...
}
- pattern-inside: |
def $CTRL(..., $PARAM: $TYPE, ...) = Action(...) {
...
}
- pattern-inside: |
def $CTRL(..., $PARAM: $TYPE, ...) = Action.async {
...
}
- pattern-inside: >
def $CTRL(..., $PARAM: $TYPE, ...) = Action.async(...)
{
...
}
pattern-sinks:
- patterns:
- pattern-either:
- pattern: $MODEL.overrideSql(...)
- pattern: sql"..."
- pattern-inside: |
import slick.$DEPS
...
severity: ERROR
languages:
- scala
Examples
tainted-slick-sqli.scala
package controllers
import play.api.mvc._
import javax.inject._
import slick.jdbc.H2Profile.api._
import models.UserModel
@Singleton
class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController{
val db = Database.forConfig("h2mem1")
def oneAction() = Action { implicit request: Request[AnyContent] =>
val bodyVals = request.body.asFormUrlEncoded
val smth = bodyVals.get("username").head
// ruleid: tainted-slick-sqli
val action = sql"select ID, NAME, AGE from #$smth".as[(Int,String,Int)]
db.run(action)
Ok("ok")
}
def twoAction(name: String) = Action {
val people = TableQuery[People]
// ruleid: tainted-slick-sqli
people.map(p => (p.id,p.name,p.age)).result.overrideSql(s"SELECT id, name, age FROM Person WHERE $name")
Ok("ok")
}
def threeAction(name: String) = Action.async(parse.json) {
val people = TableQuery[People]
// ruleid: tainted-slick-sqli
people.map(p => (p.id,p.name,p.age)).result.overrideSql(s"SELECT id, name, age FROM Person WHERE $name")
Ok("ok")
}
def helloWorldPage() = Action { implicit request: Request[AnyContent] =>
// ok: tainted-slick-sqli
Ok(views.html.helloWorld())
}
def okAction1() = Action { implicit request: Request[AnyContent] =>
val smth = "hardcoded_value"
// ok: tainted-slick-sqli
val action = sql"select ID, NAME, AGE from #$smth".as[(Int,String,Int)]
db.run(action)
Ok("ok")
}
def okAction2(name: String) = Action { implicit request: Request[AnyContent] =>
val people = TableQuery[People]
people.map(p => (p.id,p.name,p.age))
.result
// ok: tainted-slick-sqli
.overrideSql(s"SELECT id, name, age FROM Person WHERE name = 'FooBar'")
Ok("ok")
}
}
Short Link: https://sg.run/k9K2