Swift: Fix defaultImplicitTaintRead for sinks that are field accesses on a subclass of the type containing the field.

This commit is contained in:
Geoffrey White
2023-11-01 17:39:46 +00:00
parent 554007b305
commit 206acea41c
3 changed files with 57 additions and 7 deletions

View File

@@ -32,8 +32,12 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet cs)
// So when the node is a `PostUpdateNode` we allow any sequence of implicit read steps of an appropriate
// type to make sure we arrive at the sink with an empty access path.
exists(NominalTypeDecl d, Decl cx |
node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getType().getUnderlyingType() =
d.getType().getABaseType*() and
node.(DataFlow::PostUpdateNode)
.getPreUpdateNode()
.asExpr()
.getType()
.getUnderlyingType()
.getABaseType*() = d.getType() and
cx.asNominalTypeDecl() = d and
cs.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember()
)

View File

@@ -29,6 +29,9 @@ edges
| CommandInjection.swift:81:6:81:6 | [post] task2 [arguments, Collection element] | CommandInjection.swift:81:6:81:6 | [post] task2 |
| CommandInjection.swift:81:24:81:46 | [...] [Collection element] | CommandInjection.swift:81:6:81:6 | [post] task2 [arguments, Collection element] |
| CommandInjection.swift:81:31:81:31 | validatedString | CommandInjection.swift:81:24:81:46 | [...] [Collection element] |
| CommandInjection.swift:93:20:93:40 | arguments [Collection element] | CommandInjection.swift:94:20:94:20 | arguments [Collection element] |
| CommandInjection.swift:94:3:94:3 | [post] self [arguments, Collection element] | CommandInjection.swift:94:3:94:3 | [post] self |
| CommandInjection.swift:94:20:94:20 | arguments [Collection element] | CommandInjection.swift:94:3:94:3 | [post] self [arguments, Collection element] |
| CommandInjection.swift:99:8:99:12 | let ...? [some:0] | CommandInjection.swift:99:12:99:12 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:114:36:114:36 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:115:28:115:28 | userControlledString |
@@ -37,6 +40,10 @@ edges
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:121:28:121:36 | ... .+(_:_:) ... |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:125:46:125:46 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:126:22:126:22 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:130:45:130:45 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:131:36:131:36 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:132:21:132:21 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:133:22:133:22 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:134:24:134:24 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:144:42:144:42 | userControlledString |
| CommandInjection.swift:99:12:99:12 | userControlledString | CommandInjection.swift:145:75:145:75 | userControlledString |
@@ -54,6 +61,10 @@ edges
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:121:28:121:36 | ... .+(_:_:) ... |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:125:46:125:46 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:126:22:126:22 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:130:45:130:45 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:131:36:131:36 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:132:21:132:21 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:133:22:133:22 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:134:24:134:24 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:144:42:144:42 | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:145:75:145:75 | userControlledString |
@@ -87,6 +98,18 @@ edges
| CommandInjection.swift:126:2:126:7 | [post] ...? [arguments, Collection element] | CommandInjection.swift:126:2:126:7 | [post] ...? |
| CommandInjection.swift:126:21:126:42 | [...] [Collection element] | CommandInjection.swift:126:2:126:7 | [post] ...? [arguments, Collection element] |
| CommandInjection.swift:126:22:126:22 | userControlledString | CommandInjection.swift:126:21:126:42 | [...] [Collection element] |
| CommandInjection.swift:130:2:130:2 | [post] task6 [executableURL] | CommandInjection.swift:130:2:130:2 | [post] task6 |
| CommandInjection.swift:130:24:130:65 | call to URL.init(fileURLWithPath:) | CommandInjection.swift:130:2:130:2 | [post] task6 [executableURL] |
| CommandInjection.swift:130:45:130:45 | userControlledString | CommandInjection.swift:130:24:130:65 | call to URL.init(fileURLWithPath:) |
| CommandInjection.swift:131:2:131:2 | [post] task6 [executableURL] | CommandInjection.swift:131:2:131:2 | [post] task6 |
| CommandInjection.swift:131:24:131:56 | call to URL.init(string:) [some:0] | CommandInjection.swift:131:24:131:57 | ...! |
| CommandInjection.swift:131:24:131:57 | ...! | CommandInjection.swift:131:2:131:2 | [post] task6 [executableURL] |
| CommandInjection.swift:131:36:131:36 | userControlledString | CommandInjection.swift:131:24:131:56 | call to URL.init(string:) [some:0] |
| CommandInjection.swift:132:2:132:2 | [post] task6 [arguments, Collection element] | CommandInjection.swift:132:2:132:2 | [post] task6 |
| CommandInjection.swift:132:20:132:41 | [...] [Collection element] | CommandInjection.swift:132:2:132:2 | [post] task6 [arguments, Collection element] |
| CommandInjection.swift:132:21:132:21 | userControlledString | CommandInjection.swift:132:20:132:41 | [...] [Collection element] |
| CommandInjection.swift:133:21:133:42 | [...] [Collection element] | CommandInjection.swift:93:20:93:40 | arguments [Collection element] |
| CommandInjection.swift:133:22:133:22 | userControlledString | CommandInjection.swift:133:21:133:42 | [...] [Collection element] |
| CommandInjection.swift:134:24:134:24 | userControlledString | CommandInjection.swift:144:42:144:42 | userControlledString |
| CommandInjection.swift:134:24:134:24 | userControlledString | CommandInjection.swift:145:75:145:75 | userControlledString |
| CommandInjection.swift:134:24:134:24 | userControlledString | CommandInjection.swift:148:35:148:35 | userControlledString |
@@ -183,6 +206,10 @@ nodes
| CommandInjection.swift:81:6:81:6 | [post] task2 [arguments, Collection element] | semmle.label | [post] task2 [arguments, Collection element] |
| CommandInjection.swift:81:24:81:46 | [...] [Collection element] | semmle.label | [...] [Collection element] |
| CommandInjection.swift:81:31:81:31 | validatedString | semmle.label | validatedString |
| CommandInjection.swift:93:20:93:40 | arguments [Collection element] | semmle.label | arguments [Collection element] |
| CommandInjection.swift:94:3:94:3 | [post] self | semmle.label | [post] self |
| CommandInjection.swift:94:3:94:3 | [post] self [arguments, Collection element] | semmle.label | [post] self [arguments, Collection element] |
| CommandInjection.swift:94:20:94:20 | arguments [Collection element] | semmle.label | arguments [Collection element] |
| CommandInjection.swift:99:8:99:12 | let ...? [some:0] | semmle.label | let ...? [some:0] |
| CommandInjection.swift:99:12:99:12 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
@@ -217,6 +244,21 @@ nodes
| CommandInjection.swift:126:2:126:7 | [post] ...? [arguments, Collection element] | semmle.label | [post] ...? [arguments, Collection element] |
| CommandInjection.swift:126:21:126:42 | [...] [Collection element] | semmle.label | [...] [Collection element] |
| CommandInjection.swift:126:22:126:22 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:130:2:130:2 | [post] task6 | semmle.label | [post] task6 |
| CommandInjection.swift:130:2:130:2 | [post] task6 [executableURL] | semmle.label | [post] task6 [executableURL] |
| CommandInjection.swift:130:24:130:65 | call to URL.init(fileURLWithPath:) | semmle.label | call to URL.init(fileURLWithPath:) |
| CommandInjection.swift:130:45:130:45 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:131:2:131:2 | [post] task6 | semmle.label | [post] task6 |
| CommandInjection.swift:131:2:131:2 | [post] task6 [executableURL] | semmle.label | [post] task6 [executableURL] |
| CommandInjection.swift:131:24:131:56 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
| CommandInjection.swift:131:24:131:57 | ...! | semmle.label | ...! |
| CommandInjection.swift:131:36:131:36 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:132:2:132:2 | [post] task6 | semmle.label | [post] task6 |
| CommandInjection.swift:132:2:132:2 | [post] task6 [arguments, Collection element] | semmle.label | [post] task6 [arguments, Collection element] |
| CommandInjection.swift:132:20:132:41 | [...] [Collection element] | semmle.label | [...] [Collection element] |
| CommandInjection.swift:132:21:132:21 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:133:21:133:42 | [...] [Collection element] | semmle.label | [...] [Collection element] |
| CommandInjection.swift:133:22:133:22 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:134:24:134:24 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:144:42:144:42 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:145:67:145:95 | [...] | semmle.label | [...] |
@@ -290,6 +332,7 @@ subpaths
#select
| CommandInjection.swift:75:2:75:2 | [post] task1 | CommandInjection.swift:69:40:69:94 | call to String.init(contentsOf:) | CommandInjection.swift:75:2:75:2 | [post] task1 | This command depends on a $@. | CommandInjection.swift:69:40:69:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:81:6:81:6 | [post] task2 | CommandInjection.swift:69:40:69:94 | call to String.init(contentsOf:) | CommandInjection.swift:81:6:81:6 | [post] task2 | This command depends on a $@. | CommandInjection.swift:69:40:69:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:94:3:94:3 | [post] self | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:94:3:94:3 | [post] self | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:114:2:114:2 | [post] task3 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:114:2:114:2 | [post] task3 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:115:2:115:2 | [post] task3 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:115:2:115:2 | [post] task3 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:119:2:119:2 | [post] task4 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:119:2:119:2 | [post] task4 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
@@ -297,6 +340,9 @@ subpaths
| CommandInjection.swift:121:2:121:2 | [post] task4 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:121:2:121:2 | [post] task4 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:125:2:125:7 | [post] ...? | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:125:2:125:7 | [post] ...? | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:126:2:126:7 | [post] ...? | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:126:2:126:7 | [post] ...? | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:130:2:130:2 | [post] task6 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:130:2:130:2 | [post] task6 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:131:2:131:2 | [post] task6 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:131:2:131:2 | [post] task6 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:132:2:132:2 | [post] task6 | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:132:2:132:2 | [post] task6 | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:144:42:144:42 | userControlledString | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:144:42:144:42 | userControlledString | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:145:67:145:95 | [...] | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:145:67:145:95 | [...] | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:148:23:148:56 | ...! | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:148:23:148:56 | ...! | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |

View File

@@ -91,7 +91,7 @@ class MyProcess : Process {
var harmlessField: String?
func setArguments(_ arguments: [String]) {
self.arguments = arguments
self.arguments = arguments // BAD
}
}
@@ -127,10 +127,10 @@ func testCommandInjectionMore(mySafeString: String) {
try! task5?.run()
let task6 = MyProcess()
task6.executableURL = URL(fileURLWithPath: userControlledString) // BAD [NOT DETECTED]
task6.executableURL = URL(string: userControlledString)! // BAD [NOT DETECTED]
task6.arguments = [userControlledString] // BAD [NOT DETECTED]
task6.setArguments([userControlledString]) // BAD [NOT DETECTED]
task6.executableURL = URL(fileURLWithPath: userControlledString) // BAD
task6.executableURL = URL(string: userControlledString)! // BAD
task6.arguments = [userControlledString] // BAD
task6.setArguments([userControlledString]) // BAD (flagged inside `setArguments`)
task6.harmlessField = userControlledString // GOOD
try! task6.run()