mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Separating some reusable code into QLL libraries.
Fixing bugs from code review.
This commit is contained in:
36
csharp/ql/src/Likely Bugs/ICryptoTransform.qll
Normal file
36
csharp/ql/src/Likely Bugs/ICryptoTransform.qll
Normal file
@@ -0,0 +1,36 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.DataFlow
|
||||
|
||||
import csharp
|
||||
class ImplementsICryptoTransform extends Class {
|
||||
ImplementsICryptoTransform() {
|
||||
this.getABaseType*().hasQualifiedName("System.Security.Cryptography", "ICryptoTransform")
|
||||
}
|
||||
}
|
||||
|
||||
predicate usesICryptoTransformType( ValueOrRefType t ) {
|
||||
exists( ImplementsICryptoTransform ict |
|
||||
ict = t
|
||||
or usesICryptoTransformType( t.getAChild() )
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasICryptoTransformMember( Class c) {
|
||||
c.getAField().getType() instanceof UsesICryptoTransform
|
||||
}
|
||||
|
||||
class UsesICryptoTransform extends Class {
|
||||
UsesICryptoTransform() {
|
||||
usesICryptoTransformType(this) or hasICryptoTransformMember(this)
|
||||
}
|
||||
}
|
||||
|
||||
class LambdaCapturingICryptoTransformSource extends DataFlow::Node {
|
||||
LambdaCapturingICryptoTransformSource() {
|
||||
exists( LambdaExpr l, LocalScopeVariable lsvar, UsesICryptoTransform ict |
|
||||
l = this.asExpr() |
|
||||
ict = lsvar.getType()
|
||||
and lsvar.getACapturingCallable() = l
|
||||
)
|
||||
}
|
||||
}
|
||||
18
csharp/ql/src/Likely Bugs/ParallelSink.qll
Normal file
18
csharp/ql/src/Likely Bugs/ParallelSink.qll
Normal file
@@ -0,0 +1,18 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.DataFlow
|
||||
|
||||
abstract class ParallelSink extends DataFlow::Node {
|
||||
}
|
||||
|
||||
class LambdaParallelSink extends ParallelSink {
|
||||
LambdaParallelSink() {
|
||||
exists( Class c, Method m, MethodCall mc, Expr e |
|
||||
e = this.asExpr() |
|
||||
c.getABaseType*().hasQualifiedName("System.Threading.Tasks", "Parallel")
|
||||
and c.getAMethod() = m
|
||||
and m.getName() = "Invoke"
|
||||
and m.getACall() = mc
|
||||
and mc.getAnArgument() = e
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ public static void RunThreadUnSafeICryptoTransformLambdaFixed()
|
||||
var b = new Barrier(threadCount);
|
||||
Action start = () => {
|
||||
b.SignalAndWait();
|
||||
// The hash object is no longer shared
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
// The hash object is no longer shared
|
||||
var sha1 = SHA1.Create();
|
||||
var pwd = Guid.NewGuid().ToString();
|
||||
var bytes = Encoding.UTF8.GetBytes(pwd);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @name Potential usage of a n object implementing ICryptoTransform class in a way that would be unsafe for concurrent threads.
|
||||
* @name Potential usage of an object implementing ICryptoTransform class in a way that would be unsafe for concurrent threads.
|
||||
* @description An instance of a class that either implements or has a field of type System.Security.Cryptography.ICryptoTransform is being captured by a lambda,
|
||||
* and used in what seems to be a thread initialization method.
|
||||
* Using this an instance of this class in concurrent threads is dangerous as it may not only result in an error,
|
||||
* Using an instance of this class in concurrent threads is dangerous as it may not only result in an error,
|
||||
* but under some circumstances may also result in incorrect results.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
@@ -15,47 +15,21 @@
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.DataFlow
|
||||
|
||||
class ICryptoTransform extends Class {
|
||||
ICryptoTransform() {
|
||||
this.getABaseType*().hasQualifiedName("System.Security.Cryptography", "ICryptoTransform")
|
||||
}
|
||||
}
|
||||
|
||||
predicate usesICryptoTransformType( Type t ) {
|
||||
exists( ICryptoTransform ict |
|
||||
ict = t
|
||||
or usesICryptoTransformType( t.getAChild() )
|
||||
or usesICryptoTransformType( t.(Class).getAMember() )
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasICryptoTransformMember( Class c) {
|
||||
c.getAField().getType() instanceof UsesICryptoTransform
|
||||
}
|
||||
|
||||
class UsesICryptoTransform extends Class {
|
||||
UsesICryptoTransform() {
|
||||
usesICryptoTransformType(this) or hasICryptoTransformMember(this)
|
||||
}
|
||||
}
|
||||
import ParallelSink
|
||||
import ICryptoTransform
|
||||
|
||||
class NotThreadSafeCryptoUsageIntoStartingCallingConfig extends TaintTracking::Configuration {
|
||||
NotThreadSafeCryptoUsageIntoStartingCallingConfig() { this = "NotThreadSafeCryptoUsageIntoStartingCallingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists( LambdaExpr l, LocalScopeVariable lsvar, UsesICryptoTransform ict |
|
||||
l = source.asExpr() |
|
||||
ict = lsvar.getType()
|
||||
and lsvar.getACapturingCallable() = l
|
||||
)
|
||||
source instanceof LambdaCapturingICryptoTransformSource
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists( DelegateCreation dc, Expr e |
|
||||
e = sink.asExpr() |
|
||||
dc.getArgument() = e
|
||||
and dc.getType().getName().matches("%Start")
|
||||
e = sink.asExpr() |
|
||||
dc.getArgument() = e
|
||||
and dc.getType().getName().matches("%Start")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -64,33 +38,22 @@ class NotThreadSafeCryptoUsageIntoParallelInvokeConfig extends TaintTracking::Co
|
||||
NotThreadSafeCryptoUsageIntoParallelInvokeConfig() { this = "NotThreadSafeCryptoUsageIntoParallelInvokeConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists( LambdaExpr l, LocalScopeVariable lsvar, UsesICryptoTransform ict |
|
||||
l = source.asExpr() |
|
||||
ict = lsvar.getType()
|
||||
and lsvar.getACapturingCallable() = l
|
||||
)
|
||||
source instanceof LambdaCapturingICryptoTransformSource
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists( Class c, Method m, MethodCall mc, Expr e |
|
||||
e = sink.asExpr() |
|
||||
c.getABaseType*().hasQualifiedName("System.Threading.Tasks", "Parallel")
|
||||
and c.getAMethod() = m
|
||||
and m.getName() = "Invoke"
|
||||
and m.getACall() = mc
|
||||
and mc.getAnArgument() = e
|
||||
)
|
||||
sink instanceof ParallelSink
|
||||
}
|
||||
}
|
||||
|
||||
from Expr e, string m
|
||||
from Expr e, string m, LambdaExpr l
|
||||
where
|
||||
exists( NotThreadSafeCryptoUsageIntoParallelInvokeConfig config, LambdaExpr l |
|
||||
config.hasFlow(DataFlow::exprNode(l), DataFlow::exprNode(e))
|
||||
and m = "A Lambda expression at " + l.getLocation() + " seems to be used to start a new thread using System.Threading.Tasks.Parallel.Invoke, and is capturing a local variable that either implements 'System.Security.Cryptography.ICryptoTransform' or has a field of this type."
|
||||
exists( NotThreadSafeCryptoUsageIntoParallelInvokeConfig config |
|
||||
config.hasFlow(DataFlow::exprNode(l), DataFlow::exprNode(e))
|
||||
and m = "A $@ seems to be used to start a new thread using System.Threading.Tasks.Parallel.Invoke, and is capturing a local variable that either implements 'System.Security.Cryptography.ICryptoTransform' or has a field of this type."
|
||||
)
|
||||
or exists ( NotThreadSafeCryptoUsageIntoStartingCallingConfig config, LambdaExpr l |
|
||||
config.hasFlow(DataFlow::exprNode(l), DataFlow::exprNode(e))
|
||||
and m = "A Lambda expression at " + l.getLocation() + " seems to be used to start a new thread is capturing a local variable that either implements 'System.Security.Cryptography.ICryptoTransform' or has a field of this type."
|
||||
or exists ( NotThreadSafeCryptoUsageIntoStartingCallingConfig config |
|
||||
config.hasFlow(DataFlow::exprNode(l), DataFlow::exprNode(e))
|
||||
and m = "A $@ seems to be used to start a new thread is capturing a local variable that either implements 'System.Security.Cryptography.ICryptoTransform' or has a field of this type."
|
||||
)
|
||||
select e, m
|
||||
select e, m, l, "lambda expression"
|
||||
|
||||
Reference in New Issue
Block a user