Merge from master and resolve conflicts

This commit is contained in:
Dave Bartolomeo
2019-12-04 10:14:52 -07:00
240 changed files with 12094 additions and 9744 deletions

View File

@@ -0,0 +1,52 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
The <code>requestValidationMode</code> attribute in ASP.NET is used to configure built-in validation to
protect applications against code injections. Downgrading or disabling
this configuration is not recommended. The default value of 4.5
is the only recommended value, as previous versions only test a subset of requests.
</p>
</overview>
<recommendation>
<p>
Always set <code>requestValidationMode</code> to 4.5, or leave it at its default value.
</p>
</recommendation>
<example>
<p>
The following example shows the <code>requestValidationMode</code>
attribute set to a value of 4.0, which disables some protections and
ignores individual <code>Page</code> directives:
</p>
<sample src="ASPNetRequestValidationModeBad.config" />
<p>
Setting the value to 4.5 enables request validation for all requests:
</p>
<sample src="ASPNetRequestValidationModeGood.config" />
</example>
<references>
<li>
Microsoft:
<a
href="https://docs.microsoft.com/en-us/dotnet/api/system.web.configuration.httpruntimesection.requestvalidationmode?view=netframework-4.8">HttpRuntimeSection.RequestValidationMode Property
</a>.
</li>
<li>
OWASP:
<a
href="https://www.owasp.org/index.php/ASP.NET_Request_Validation">ASP.NET Request Validation</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,20 @@
/**
* @name Insecure configuration for ASP.NET requestValidationMode
* @description Setting 'requestValidationMode' to less than 4.5 disables built-in validations
* included by default in ASP.NET. Disabling or downgrading this protection is not
* recommended.
* @kind problem
* @id cs/insecure-request-validation-mode
* @problem.severity warning
* @tags security
* external/cwe/cwe-016
*/
import csharp
from XMLAttribute reqValidationMode
where
reqValidationMode.getName().toLowerCase() = "requestvalidationmode" and
reqValidationMode.getValue().toFloat() < 4.5
select reqValidationMode,
"Insecure value for requestValidationMode (" + reqValidationMode.getValue() + ")."

View File

@@ -0,0 +1,5 @@
<configuration>
<system.web>
<httpRuntime requestValidationMode="4.0"/>
</system.web>
</configuration>

View File

@@ -0,0 +1,5 @@
<configuration>
<system.web>
<httpRuntime requestValidationMode="4.5"/>
</system.web>
</configuration>

View File

@@ -510,13 +510,20 @@ private predicate simpleParameterFlow(
pragma[noinline]
private predicate simpleArgumentFlowsThrough0(
ParameterNode p, ReturnNode ret, ReturnKind kind, DataFlowType t, Configuration config
) {
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind()
}
pragma[noinline]
private predicate simpleArgumentFlowsThrough1(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, DataFlowType t, Configuration config
) {
nodeCand1(arg, unbind(config)) and
not outBarrier(arg, config) and
exists(ParameterNode p, ReturnNode ret |
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind() and
simpleArgumentFlowsThrough0(p, ret, kind, t, config) and
viableParamArg(call, p, arg)
)
}
@@ -534,7 +541,7 @@ private predicate simpleArgumentFlowsThrough(
exists(DataFlowCall call, ReturnKind kind |
nodeCand1(out, unbind(config)) and
not inBarrier(out, config) and
simpleArgumentFlowsThrough0(call, arg, kind, t, config) and
simpleArgumentFlowsThrough1(call, arg, kind, t, config) and
out = getAnOutNode(call, kind)
)
}

View File

@@ -510,13 +510,20 @@ private predicate simpleParameterFlow(
pragma[noinline]
private predicate simpleArgumentFlowsThrough0(
ParameterNode p, ReturnNode ret, ReturnKind kind, DataFlowType t, Configuration config
) {
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind()
}
pragma[noinline]
private predicate simpleArgumentFlowsThrough1(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, DataFlowType t, Configuration config
) {
nodeCand1(arg, unbind(config)) and
not outBarrier(arg, config) and
exists(ParameterNode p, ReturnNode ret |
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind() and
simpleArgumentFlowsThrough0(p, ret, kind, t, config) and
viableParamArg(call, p, arg)
)
}
@@ -534,7 +541,7 @@ private predicate simpleArgumentFlowsThrough(
exists(DataFlowCall call, ReturnKind kind |
nodeCand1(out, unbind(config)) and
not inBarrier(out, config) and
simpleArgumentFlowsThrough0(call, arg, kind, t, config) and
simpleArgumentFlowsThrough1(call, arg, kind, t, config) and
out = getAnOutNode(call, kind)
)
}

View File

@@ -510,13 +510,20 @@ private predicate simpleParameterFlow(
pragma[noinline]
private predicate simpleArgumentFlowsThrough0(
ParameterNode p, ReturnNode ret, ReturnKind kind, DataFlowType t, Configuration config
) {
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind()
}
pragma[noinline]
private predicate simpleArgumentFlowsThrough1(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, DataFlowType t, Configuration config
) {
nodeCand1(arg, unbind(config)) and
not outBarrier(arg, config) and
exists(ParameterNode p, ReturnNode ret |
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind() and
simpleArgumentFlowsThrough0(p, ret, kind, t, config) and
viableParamArg(call, p, arg)
)
}
@@ -534,7 +541,7 @@ private predicate simpleArgumentFlowsThrough(
exists(DataFlowCall call, ReturnKind kind |
nodeCand1(out, unbind(config)) and
not inBarrier(out, config) and
simpleArgumentFlowsThrough0(call, arg, kind, t, config) and
simpleArgumentFlowsThrough1(call, arg, kind, t, config) and
out = getAnOutNode(call, kind)
)
}

View File

@@ -510,13 +510,20 @@ private predicate simpleParameterFlow(
pragma[noinline]
private predicate simpleArgumentFlowsThrough0(
ParameterNode p, ReturnNode ret, ReturnKind kind, DataFlowType t, Configuration config
) {
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind()
}
pragma[noinline]
private predicate simpleArgumentFlowsThrough1(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, DataFlowType t, Configuration config
) {
nodeCand1(arg, unbind(config)) and
not outBarrier(arg, config) and
exists(ParameterNode p, ReturnNode ret |
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind() and
simpleArgumentFlowsThrough0(p, ret, kind, t, config) and
viableParamArg(call, p, arg)
)
}
@@ -534,7 +541,7 @@ private predicate simpleArgumentFlowsThrough(
exists(DataFlowCall call, ReturnKind kind |
nodeCand1(out, unbind(config)) and
not inBarrier(out, config) and
simpleArgumentFlowsThrough0(call, arg, kind, t, config) and
simpleArgumentFlowsThrough1(call, arg, kind, t, config) and
out = getAnOutNode(call, kind)
)
}

View File

@@ -510,13 +510,20 @@ private predicate simpleParameterFlow(
pragma[noinline]
private predicate simpleArgumentFlowsThrough0(
ParameterNode p, ReturnNode ret, ReturnKind kind, DataFlowType t, Configuration config
) {
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind()
}
pragma[noinline]
private predicate simpleArgumentFlowsThrough1(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, DataFlowType t, Configuration config
) {
nodeCand1(arg, unbind(config)) and
not outBarrier(arg, config) and
exists(ParameterNode p, ReturnNode ret |
simpleParameterFlow(p, ret, t, config) and
kind = ret.getKind() and
simpleArgumentFlowsThrough0(p, ret, kind, t, config) and
viableParamArg(call, p, arg)
)
}
@@ -534,7 +541,7 @@ private predicate simpleArgumentFlowsThrough(
exists(DataFlowCall call, ReturnKind kind |
nodeCand1(out, unbind(config)) and
not inBarrier(out, config) and
simpleArgumentFlowsThrough0(call, arg, kind, t, config) and
simpleArgumentFlowsThrough1(call, arg, kind, t, config) and
out = getAnOutNode(call, kind)
)
}

View File

@@ -360,7 +360,7 @@ private module ImplCommon {
*/
cached
predicate read(Node node1, Content f, Node node2) {
readStep(node1, f, node2) and storeStep(_, f, _)
readStep(node1, f, node2)
or
exists(DataFlowCall call, ReturnKind kind |
read0(call, kind, node1, f) and

View File

@@ -113,6 +113,12 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
scope = e2 and
isSuccessor = true
)
or
e2 = any(OperatorCall oc |
oc.getTarget().(ConversionOperator).fromLibrary() and
e1 = oc.getAnArgument() and
isSuccessor = true
)
)
}

View File

@@ -190,10 +190,16 @@ private module Internal {
abstract RuntimeCallable getADynamicTarget();
}
pragma[noinline]
private predicate hasOverrider(OverridableCallable oc, ValueOrRefType t) {
exists(oc.getAnOverrider(t))
}
pragma[noinline]
private predicate hasCallable(OverridableCallable source, ValueOrRefType t, OverridableCallable c) {
c.getSourceDeclaration() = source and
t.hasCallable(c) and
hasOverrider(c, t) and
hasQualifierTypeOverridden0(t, _) and
hasQualifierTypeOverridden1(source, _)
}
@@ -215,15 +221,19 @@ private module Internal {
pragma[noinline]
private predicate hasQualifierTypeOverridden0(ValueOrRefType t, DispatchMethodOrAccessorCall call) {
exists(Type t0 | t0 = getAPossibleType(call.getQualifier(), false) |
t = t0
hasOverrider(_, t) and
(
exists(Type t0 | t0 = getAPossibleType(call.getQualifier(), false) |
t = t0
or
Unification::subsumes(t0, t)
or
t = t0.(Unification::UnconstrainedTypeParameter).getAnUltimatelySuppliedType()
)
or
Unification::subsumes(t0, t)
or
t = t0.(Unification::UnconstrainedTypeParameter).getAnUltimatelySuppliedType()
constrainedTypeParameterQualifierTypeSubsumes(t,
getAConstrainedTypeParameterQualifierType(call))
)
or
constrainedTypeParameterQualifierTypeSubsumes(t, getAConstrainedTypeParameterQualifierType(call))
}
pragma[noinline]

View File

@@ -359,24 +359,25 @@ class Instruction extends Construction::TInstruction {
*/
int getDisplayIndexInBlock() {
exists(IRBlock block |
block = getBlock() and
(
exists(int index, int phiCount |
phiCount = count(block.getAPhiInstruction()) and
this = block.getInstruction(index) and
result = index + phiCount
this = block.getInstruction(result)
or
this = rank[-result - 1](PhiInstruction phiInstr |
phiInstr = block.getAPhiInstruction()
|
phiInstr order by phiInstr.getUniqueId()
)
or
this instanceof PhiInstruction and
this = rank[result + 1](PhiInstruction phiInstr |
phiInstr = block.getAPhiInstruction()
|
phiInstr order by phiInstr.getUniqueId()
)
)
)
}
private int getLineRank() {
this = rank[result](Instruction instr |
instr.getAST().getFile() = getAST().getFile() and
instr.getAST().getLocation().getStartLine() = getAST().getLocation().getStartLine()
|
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
/**
* Gets a human-readable string that uniquely identifies this instruction
* within the function. This string is used to refer to this instruction when
@@ -385,8 +386,7 @@ class Instruction extends Construction::TInstruction {
* Example: `r1_1`
*/
string getResultId() {
result = getResultPrefix() + getBlock().getDisplayIndex().toString() + "_" +
getDisplayIndexInBlock().toString()
result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank()
}
/**

View File

@@ -359,24 +359,25 @@ class Instruction extends Construction::TInstruction {
*/
int getDisplayIndexInBlock() {
exists(IRBlock block |
block = getBlock() and
(
exists(int index, int phiCount |
phiCount = count(block.getAPhiInstruction()) and
this = block.getInstruction(index) and
result = index + phiCount
this = block.getInstruction(result)
or
this = rank[-result - 1](PhiInstruction phiInstr |
phiInstr = block.getAPhiInstruction()
|
phiInstr order by phiInstr.getUniqueId()
)
or
this instanceof PhiInstruction and
this = rank[result + 1](PhiInstruction phiInstr |
phiInstr = block.getAPhiInstruction()
|
phiInstr order by phiInstr.getUniqueId()
)
)
)
}
private int getLineRank() {
this = rank[result](Instruction instr |
instr.getAST().getFile() = getAST().getFile() and
instr.getAST().getLocation().getStartLine() = getAST().getLocation().getStartLine()
|
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
/**
* Gets a human-readable string that uniquely identifies this instruction
* within the function. This string is used to refer to this instruction when
@@ -385,8 +386,7 @@ class Instruction extends Construction::TInstruction {
* Example: `r1_1`
*/
string getResultId() {
result = getResultPrefix() + getBlock().getDisplayIndex().toString() + "_" +
getDisplayIndexInBlock().toString()
result = getResultPrefix() + getAST().getLocation().getStartLine() + "_" + getLineRank()
}
/**

View File

@@ -1,5 +1,6 @@
import AliasAnalysis
private import SimpleSSAImports
import SimpleSSAPublicImports
private class IntValue = Ints::IntValue;

View File

@@ -2,4 +2,3 @@ import semmle.code.csharp.ir.implementation.raw.IR
import semmle.code.csharp.ir.internal.IntegerConstant as Ints
import semmle.code.csharp.ir.implementation.internal.OperandTag
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
import semmle.code.csharp.ir.internal.Overlap

View File

@@ -0,0 +1 @@
import semmle.code.csharp.ir.internal.Overlap