-
Notifications
You must be signed in to change notification settings - Fork 250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java: Arbitrary user-controlled read/write on user-controlled path #839
Labels
The Bug Slayer
Submissions to The Bug Slayer bounty
Comments
susi_server_db.zip Here is the slightly cleaned and modernized query from github/codeql#3794 (I did not update the query there, because it will likely not be merged). /**
* @name User-controlled content written on user-controlled path expression.
* @description Writing user-controlled data to an user-controlled paths can allow an attacker to write arbitrary files.
* @kind path-problem
* @problem.severity error
* @precision medium
* @id java/tainted-file-write
* @tags security
* external/cwe/cwe-706
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
import semmle.code.java.security.XSS
import TaintedPathFlow::PathGraph
import semmle.code.java.security.PathCreation
/** Holds if `node1` is used in the creation of `node2` and not guarded. */
predicate usedInPathCreation(DataFlow::Node node1, DataFlow::Node node2) {
exists(Expr e | e = node1.asExpr() | e = node2.asExpr().(PathCreation).getAnInput())
}
module TaintedPathConfig implements DataFlow::StateConfigSig {
class FlowState = string;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof RemoteFlowSource and state = "remote-file-name"
}
predicate isSink(DataFlow::Node sink, FlowState state) {
sink instanceof FileWriteSink and state = "file-write-on-tainted-file-instance"
}
predicate isBarrier(DataFlow::Node node) {
exists(Type t | t = node.getType() | t instanceof BoxedType or t instanceof PrimitiveType)
}
// override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
// guard instanceof ContainsDotDotSanitizer
// // TODO add guards from zipslip.ql
// }
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
usedInPathCreation(node1, node2) and state1 = "remote-file-name" and state2 = "remote-file-name"
or
node1 instanceof TaintedPathSink and
state1 = "remote-file-name" and
node2.asExpr() = node1.(TaintedPathSink).getTaintedFile() and
state2 = "tainted-file-instance"
or
exists(NewClassExpr fos | fos.getConstructedType().hasQualifiedName(_, "FileOutputStream") |
fos.getAnArgument() = node1.asExpr() and node2.asExpr() = fos
) and
state1 = "tainted-file-instance" and
state2 = "file-write-on-tainted-file-instance"
}
}
module TaintedPathFlow = TaintTracking::GlobalWithState<TaintedPathConfig>;
private class TaintedPathSink extends DataFlow::Node {
Expr path;
TaintedPathSink() {
exists(Expr e, PathCreation p | e = asExpr() | e = p.getAnInput() and path = p)
}
Expr getTaintedFile() { result = path }
}
module UserControlledWrite implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) {
exists(FileWriteSink fws | fws.getWrittenContent() = sink)
}
}
module UserControlledWriteFlow = TaintTracking::Global<UserControlledWrite>;
/**
* Modles the `write` method of `java.io.OutputStream`
*/
private class WriteMethod extends Method {
WriteMethod() {
this.hasName("write") and this.getDeclaringType().hasQualifiedName("java.io", "OutputStream")
}
}
abstract private class FileWriteSink extends DataFlow::Node {
abstract DataFlow::Node getWrittenContent();
}
/**
* Models a write to a file via a direct or indirect call to the `write` method of `java.io.OutputStream`.
*/
private class OutputStreamWriteSink extends FileWriteSink {
Expr content;
OutputStreamWriteSink() {
exists(MethodCall mc | mc.getMethod().overrides*(any(WriteMethod wm)) |
mc.getQualifier() = this.asExpr() and mc.getAnArgument() = content
)
}
override DataFlow::Node getWrittenContent() { result.asExpr() = content }
}
from
TaintedPathFlow::PathNode remoteFileCreationSource, TaintedPathFlow::PathNode taintedFile,
DataFlow::Node remoteContentSource
where
TaintedPathFlow::flowPath(remoteFileCreationSource, taintedFile) and
UserControlledWriteFlow::flow(remoteContentSource,
taintedFile.getNode().(FileWriteSink).getWrittenContent())
select taintedFile.getNode(), remoteFileCreationSource, taintedFile,
"Potential $@ written to a file derived from $@.", taintedFile, "user-controlled content",
remoteFileCreationSource.getNode(), "a remote source" |
Closing as per this discussion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
CVE(s) ID list
All For One submission
#136
Details
This has been originally found on lgtm.com
As it has been shut down, I can not provide links to it, so I have to create new dbs.
This will take some time.
Are you planning to discuss this vulnerability submission publicly? (Blog Post, social networks, etc).
Blog post link
https://intrigus.org/advisories/2021/07/19/ISL-2020-002-loklak-loklak_server/ https://intrigus.org/advisories/2021/07/19/ISL-2020-001-fossasia-susiserver/
The text was updated successfully, but these errors were encountered: