remove standalone archive api query

This commit is contained in:
thiggy1342
2022-06-15 01:38:52 +00:00
committed by GitHub
parent 0832e299f2
commit df226ee610
4 changed files with 0 additions and 164 deletions

View File

@@ -1,71 +0,0 @@
/**
* @name User-controlled filename in archive library
* @description User-controlled data that flows into File I/O of archive libraries could be dangerous
* @kind path-problem
* @problem.severity error
* @security-severity 7.5
* @precision medium
* @id rb/user-controlled-path-traversal-archive-library
* @tags security external/cwe/cwe-22
*/
import ruby
import codeql.ruby.ApiGraphs
import codeql.ruby.DataFlow
import codeql.ruby.dataflow.RemoteFlowSources
import codeql.ruby.dataflow.BarrierGuards
import codeql.ruby.TaintTracking
import DataFlow::PathGraph
class ArchiveApiFileOpen extends DataFlow::Node {
// this should find the first argument of Zlib::Inflate.inflate or Zip::File.extract
ArchiveApiFileOpen() {
this instanceof RubyZipFileOpen or
this instanceof TarReaderFileOpen
}
}
class RubyZipFileOpen extends DataFlow::Node {
// find any use of Zip::File.open()
RubyZipFileOpen() {
this = API::getTopLevelMember("Zip").getMember("File").getAMethodCall("open").getArgument(0)
}
}
class TarReaderFileOpen extends DataFlow::Node {
// this should find a use of File.open() in context of a block opened in context of Gem::Package::TarReader.new()
TarReaderFileOpen() {
this = API::getTopLevelMember("File").getAMethodCall("open").getArgument(0) and
this.asExpr().getExpr().getParent+() = API::getTopLevelMember("Gem").getMember("Package").getMember("TarReader").getAnInstantiation().asExpr().getExpr()
}
}
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ArchiveApiFileOpen" }
// 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
}
// our Decompression APIs defined above will the the sinks we use for this query
override predicate isSink(DataFlow::Node sink) {
sink instanceof ArchiveApiFileOpen
}
// 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
}
}
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where
config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This call to $@ appears to extract an archive using user-controlled data $@ to set the filename. If the filename is not properly handled, they could end up writing to unintended places in the filesystem.", sink.getNode().asExpr().getExpr().getParent().toString(), sink.getNode().asExpr().getExpr().getParent().toString(), source.toString(), source.toString()

View File

@@ -1,24 +0,0 @@
edges
| ArchiveApiPathTraversal.rb:5:26:5:31 | call to params : | ArchiveApiPathTraversal.rb:5:26:5:42 | ...[...] : |
| ArchiveApiPathTraversal.rb:5:26:5:42 | ...[...] : | ArchiveApiPathTraversal.rb:43:17:43:27 | destination : |
| ArchiveApiPathTraversal.rb:10:11:10:16 | call to params : | ArchiveApiPathTraversal.rb:10:11:10:23 | ...[...] : |
| ArchiveApiPathTraversal.rb:10:11:10:23 | ...[...] : | ArchiveApiPathTraversal.rb:61:13:61:16 | file : |
| ArchiveApiPathTraversal.rb:43:17:43:27 | destination : | ArchiveApiPathTraversal.rb:46:38:46:48 | destination : |
| ArchiveApiPathTraversal.rb:46:28:46:67 | call to join : | ArchiveApiPathTraversal.rb:53:21:53:36 | destination_file |
| ArchiveApiPathTraversal.rb:46:38:46:48 | destination : | ArchiveApiPathTraversal.rb:46:28:46:67 | call to join : |
| ArchiveApiPathTraversal.rb:61:13:61:16 | file : | ArchiveApiPathTraversal.rb:62:20:62:23 | file |
nodes
| ArchiveApiPathTraversal.rb:5:26:5:31 | call to params : | semmle.label | call to params : |
| ArchiveApiPathTraversal.rb:5:26:5:42 | ...[...] : | semmle.label | ...[...] : |
| ArchiveApiPathTraversal.rb:10:11:10:16 | call to params : | semmle.label | call to params : |
| ArchiveApiPathTraversal.rb:10:11:10:23 | ...[...] : | semmle.label | ...[...] : |
| ArchiveApiPathTraversal.rb:43:17:43:27 | destination : | semmle.label | destination : |
| ArchiveApiPathTraversal.rb:46:28:46:67 | call to join : | semmle.label | call to join : |
| ArchiveApiPathTraversal.rb:46:38:46:48 | destination : | semmle.label | destination : |
| ArchiveApiPathTraversal.rb:53:21:53:36 | destination_file | semmle.label | destination_file |
| ArchiveApiPathTraversal.rb:61:13:61:16 | file : | semmle.label | file : |
| ArchiveApiPathTraversal.rb:62:20:62:23 | file | semmle.label | file |
subpaths
#select
| ArchiveApiPathTraversal.rb:53:21:53:36 | destination_file | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params : | ArchiveApiPathTraversal.rb:53:21:53:36 | destination_file | This call to $@ appears to extract an archive using user-controlled data $@ to set the filename. If the filename is not properly handled, they could end up writing to unintended places in the filesystem. | call to open | call to open | call to params : | call to params : |
| ArchiveApiPathTraversal.rb:62:20:62:23 | file | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params : | ArchiveApiPathTraversal.rb:62:20:62:23 | file | This call to $@ appears to extract an archive using user-controlled data $@ to set the filename. If the filename is not properly handled, they could end up writing to unintended places in the filesystem. | call to open | call to open | call to params : | call to params : |

View File

@@ -1 +0,0 @@
experimental/archive-api-path-traversal/ArchiveApiPathTraversal.ql

View File

@@ -1,68 +0,0 @@
class TestContoller < ActionController::Base
# this is vulnerable
def upload
untar params[:file], params[:filename]
end
# this is vulnerable
def unpload_zip
unzip params[:file]
end
# these are not vulnerable because of the string compare sanitizer
def safe_upload_string_compare
filename = params[:filename]
if filename == "safefile.tar"
untar params[:file], filename
end
end
def safe_upload_zip_string_compare
filename = params[:filename]
if filename == "safefile.zip"
unzip filename
end
end
# these are not vulnerable beacuse of the string array compare sanitizer
def safe_upload_string_array_compare
filename = params[:filename]
if ["safefile1.tar", "safefile2.tar"].include? filename
untar params[:file], filename
end
end
def safe_upload_zip_string_array_compare
filename = params[:filename]
if ["safefile1.zip", "safefile2.zip"].include? filename
unzip filename
end
end
def untar(io, destination)
Gem::Package::TarReader.new io do |tar|
tar.each do |tarfile|
destination_file = File.join destination, tarfile.full_name
if tarfile.directory?
FileUtils.mkdir_p destination_file
else
destination_directory = File.dirname(destination_file)
FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
File.open destination_file, "wb" do |f|
f.print tarfile.read
end
end
end
end
end
def unzip(file)
Zip::File.open(file) do |zip_file|
zip_file.each do |entry|
entry.extract
end
end
end
end