mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
remove Zip::Entry.extract from query
This commit is contained in:
@@ -18,39 +18,26 @@ import codeql.ruby.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class DecompressionApiUse extends DataFlow::Node {
|
||||
|
||||
// this should find the first argument of Zlib::Inflate.inflate or Zip::File.extract
|
||||
DecompressionApiUse() {
|
||||
this = API::getTopLevelMember("Zlib").getMember("Inflate").getAMethodCall("inflate").getArgument(0) or
|
||||
this = API::getTopLevelMember("Zip").getMember("Entry").getAMethodCall("extract").getArgument(0)
|
||||
}
|
||||
|
||||
// this should find the first argument of Zlib::Inflate.inflate or Zip::File.extract
|
||||
DecompressionApiUse() {
|
||||
this =
|
||||
API::getTopLevelMember("Zlib").getMember("Inflate").getAMethodCall("inflate").getArgument(0)
|
||||
}
|
||||
}
|
||||
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "DecompressionApiUse" }
|
||||
|
||||
// this predicate will be used to contstrain our query to find instances where only remote user-controlled data flows to the sink
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source instanceof RemoteFlowSource
|
||||
}
|
||||
Configuration() { this = "DecompressionApiUse" }
|
||||
|
||||
// our Decompression APIs defined above will the the sinks we use for this query
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof DecompressionApiUse
|
||||
}
|
||||
// this predicate will be used to contstrain our query to find instances where only remote user-controlled data flows to the sink
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
// I think it would also be helpful to reduce false positives by adding a simple sanitizer config in the event
|
||||
// that the code first checks the file name against a string literal or array of string literals before calling
|
||||
// the decompression API
|
||||
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
|
||||
guard instanceof StringConstCompare or
|
||||
guard instanceof StringConstArrayInclusionCall
|
||||
}
|
||||
}
|
||||
|
||||
// our Decompression APIs defined above will the the sinks we use for this query
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionApiUse }
|
||||
}
|
||||
|
||||
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where
|
||||
config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source.", sink.getNode().asExpr().getExpr().getParent().toString(), sink.getNode().asExpr().getExpr().getParent().toString()
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source.",
|
||||
sink.getNode().asExpr().getExpr().getParent(),
|
||||
sink.getNode().asExpr().getExpr().getParent().toString()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
edges
|
||||
| decompression_api.rb:3:31:3:36 | call to params : | decompression_api.rb:3:31:3:44 | ...[...] |
|
||||
| decompression_api.rb:13:44:13:49 | call to params : | decompression_api.rb:13:44:13:57 | ...[...] |
|
||||
| decompression_api.rb:3:31:3:36 | call to params : | decompression_api.rb:3:31:3:43 | ...[...] |
|
||||
| decompression_api.rb:13:44:13:49 | call to params : | decompression_api.rb:13:44:13:56 | ...[...] |
|
||||
nodes
|
||||
| decompression_api.rb:3:31:3:36 | call to params : | semmle.label | call to params : |
|
||||
| decompression_api.rb:3:31:3:44 | ...[...] | semmle.label | ...[...] |
|
||||
| decompression_api.rb:3:31:3:43 | ...[...] | semmle.label | ...[...] |
|
||||
| decompression_api.rb:13:44:13:49 | call to params : | semmle.label | call to params : |
|
||||
| decompression_api.rb:13:44:13:57 | ...[...] | semmle.label | ...[...] |
|
||||
| decompression_api.rb:13:44:13:56 | ...[...] | semmle.label | ...[...] |
|
||||
subpaths
|
||||
#select
|
||||
| decompression_api.rb:3:31:3:44 | ...[...] | decompression_api.rb:3:31:3:36 | call to params : | decompression_api.rb:3:31:3:44 | ...[...] | This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source. | call to inflate | call to inflate |
|
||||
| decompression_api.rb:13:44:13:57 | ...[...] | decompression_api.rb:13:44:13:49 | call to params : | decompression_api.rb:13:44:13:57 | ...[...] | This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source. | call to inflate | call to inflate |
|
||||
| decompression_api.rb:3:31:3:43 | ...[...] | decompression_api.rb:3:31:3:36 | call to params : | decompression_api.rb:3:31:3:43 | ...[...] | This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source. | decompression_api.rb:3:9:3:44 | call to inflate | call to inflate |
|
||||
| decompression_api.rb:13:44:13:56 | ...[...] | decompression_api.rb:13:44:13:49 | call to params : | decompression_api.rb:13:44:13:56 | ...[...] | This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source. | decompression_api.rb:13:9:13:57 | call to inflate | call to inflate |
|
||||
|
||||
@@ -1,42 +1,15 @@
|
||||
class TestController < ActionController::Base
|
||||
def unsafe_zlib_unzip
|
||||
Zlib::Inflate.inflate(params[:fname])
|
||||
Zlib::Inflate.inflate(params[:file])
|
||||
end
|
||||
|
||||
def safe_zlib_unzip
|
||||
Zlib::Inflate.inflate("testfile.gz")
|
||||
Zlib::Inflate.inflate(file)
|
||||
end
|
||||
|
||||
|
||||
DECOMPRESSION_LIB = Zlib
|
||||
def unsafe_zlib_unzip_const
|
||||
DECOMPRESSION_LIB::Inflate.inflate(params[:fname])
|
||||
DECOMPRESSION_LIB::Inflate.inflate(params[:file])
|
||||
end
|
||||
|
||||
def unsafe_zlib_unzip
|
||||
Zip::File.open(params[:fname]) do |zip_file|
|
||||
zip_file.each do |entry|
|
||||
entry.extract(entry.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def safe_zlib_unzip
|
||||
Zip::Entry.extract("testfile.gz")
|
||||
end
|
||||
|
||||
def sanitized_zlib_unzip
|
||||
fname = params[:fname]
|
||||
if fname == "safe_file.gz"
|
||||
Zlib::Inflate.inflate(fname)
|
||||
end
|
||||
end
|
||||
|
||||
def sanitized_array_zlib_unzip
|
||||
fname = params[:fname]
|
||||
if ["safe_file1.gz", "safe_file2.gz"].include? fname
|
||||
Zlib::Inflate.inflate(fname)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user