Skip to content

Commit 142737d

Browse files
committed
C#: Move HtmlSinks from XSS.qll into separate file
1 parent fddbce0 commit 142737d

File tree

3 files changed

+225
-209
lines changed

3 files changed

+225
-209
lines changed

csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.system.Net
1616
import semmle.code.csharp.frameworks.system.Web
1717
import semmle.code.csharp.frameworks.system.web.UI
1818
import semmle.code.csharp.security.dataflow.SqlInjection
19-
import semmle.code.csharp.security.dataflow.XSS
19+
import semmle.code.csharp.security.dataflow.flowsinks.Html
2020
import semmle.code.csharp.security.dataflow.UrlRedirect
2121
import semmle.code.csharp.security.Sanitizers
2222
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2
@@ -114,7 +114,7 @@ module EncodingConfigurations {
114114

115115
override string getKind() { result = "HTML expression" }
116116

117-
override predicate requiresEncoding(Node n) { n instanceof XSS::HtmlSink }
117+
override predicate requiresEncoding(Node n) { n instanceof HtmlSink }
118118

119119
override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
120120
}

csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll

Lines changed: 17 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,13 @@
66
import csharp
77

88
module XSS {
9-
import semmle.code.csharp.security.dataflow.flowsources.Remote
10-
import semmle.code.csharp.frameworks.microsoft.AspNetCore
9+
import semmle.code.asp.AspNet
1110
import semmle.code.csharp.frameworks.system.Net
1211
import semmle.code.csharp.frameworks.system.Web
13-
import semmle.code.csharp.frameworks.system.web.Mvc
14-
import semmle.code.csharp.frameworks.system.web.WebPages
1512
import semmle.code.csharp.frameworks.system.web.UI
16-
import semmle.code.csharp.frameworks.system.web.ui.WebControls
17-
import semmle.code.csharp.frameworks.system.windows.Forms
1813
import semmle.code.csharp.security.Sanitizers
19-
import semmle.code.asp.AspNet
14+
import semmle.code.csharp.security.dataflow.flowsinks.Html
15+
import semmle.code.csharp.security.dataflow.flowsources.Remote
2016

2117
/**
2218
* Holds if there is tainted flow from `source` to `sink` that may lead to a
@@ -166,78 +162,21 @@ module XSS {
166162
UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr }
167163
}
168164

169-
/** A sink where the value of the expression may be rendered as HTML. */
170-
abstract class HtmlSink extends DataFlow::Node { }
171-
172-
/**
173-
* An expression that is used as an argument to an XSS sink method on
174-
* `HttpResponse`.
175-
*/
176-
private class HttpResponseSink extends Sink, HtmlSink {
177-
HttpResponseSink() {
178-
exists(Method m, SystemWebHttpResponseClass responseClass |
179-
m = responseClass.getAWriteMethod() or
180-
m = responseClass.getAWriteFileMethod() or
181-
m = responseClass.getATransmitFileMethod() or
182-
m = responseClass.getABinaryWriteMethod()
183-
|
184-
// Calls to these methods, or overrides of them
185-
this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument()
186-
)
187-
}
188-
}
189-
190-
/**
191-
* An expression that is used as an argument to an XSS sink method on
192-
* `HtmlTextWriter`.
193-
*/
194-
private class HtmlTextWriterSink extends Sink, HtmlSink {
195-
HtmlTextWriterSink() {
196-
exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos |
197-
paramPos = 0 and
198-
(
199-
m = writeClass.getAWriteMethod() or
200-
m = writeClass.getAWriteLineMethod() or
201-
m = writeClass.getAWriteLineNoTabsMethod() or
202-
m = writeClass.getAWriteBeginTagMethod() or
203-
m = writeClass.getAWriteAttributeMethod()
204-
)
205-
or
206-
// The second parameter to the `WriteAttribute` method is the attribute value, which we
207-
// should only consider as tainted if the call does not ask for the attribute value to be
208-
// encoded using the final parameter.
209-
m = writeClass.getAWriteAttributeMethod() and
210-
paramPos = 1 and
211-
not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true
212-
|
213-
c = m.getACall() and
214-
this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos))
215-
)
216-
}
217-
}
218-
219-
/**
220-
* An expression that is used as an argument to an XSS sink method on
221-
* `AttributeCollection`.
222-
*/
223-
private class AttributeCollectionSink extends Sink, HtmlSink {
224-
AttributeCollectionSink() {
225-
exists(SystemWebUIAttributeCollectionClass ac, Parameter p |
226-
p = ac.getAddMethod().getParameter(1) or
227-
p = ac.getItemProperty().getSetter().getParameter(0)
228-
|
229-
this.getExpr() = p.getAnAssignedArgument()
230-
)
231-
}
232-
}
165+
private class HtmlSinkSink extends Sink {
166+
HtmlSinkSink() { this instanceof HtmlSink }
233167

234-
/**
235-
* An expression that is used as the second argument `HtmlElement.SetAttribute`.
236-
*/
237-
private class SetAttributeSink extends Sink, HtmlSink {
238-
SetAttributeSink() {
239-
this.getExpr() =
240-
any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1)
168+
override string explanation() {
169+
this instanceof WebPageWriteLiteralSink and
170+
result = "System.Web.WebPages.WebPage.WriteLiteral() method"
171+
or
172+
this instanceof WebPageWriteLiteralToSink and
173+
result = "System.Web.WebPages.WebPage.WriteLiteralTo() method"
174+
or
175+
this instanceof MicrosoftAspNetCoreMvcHtmlHelperRawSink and
176+
result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method"
177+
or
178+
this instanceof MicrosoftAspNetRazorPageWriteLiteralSink and
179+
result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method"
241180
}
242181
}
243182

@@ -285,31 +224,6 @@ module XSS {
285224
}
286225
}
287226

288-
/**
289-
* An expression that is used as an argument to an XSS sink setter, on
290-
* a class within the `System.Web.UI` namespace.
291-
*/
292-
private class SystemWebSetterHtmlSink extends Sink, HtmlSink {
293-
SystemWebSetterHtmlSink() {
294-
exists(Property p, string name, ValueOrRefType declaringType |
295-
declaringType = p.getDeclaringType() and
296-
any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and
297-
this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and
298-
p.hasName(name)
299-
|
300-
name = "Caption" and
301-
(declaringType.hasName("Calendar") or declaringType.hasName("Table"))
302-
or
303-
name = "InnerHtml"
304-
)
305-
or
306-
exists(SystemWebUIWebControlsLabelClass c |
307-
// Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded
308-
this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument()
309-
)
310-
}
311-
}
312-
313227
/**
314228
* An expression that is used as an argument to an XSS sink setter, on
315229
* a class within the `System.Web.UI` namespace.
@@ -345,16 +259,6 @@ module XSS {
345259
}
346260
}
347261

348-
/**
349-
* An expression that is used as an argument to `HtmlHelper.Raw`, typically in
350-
* a `.cshtml` file.
351-
*/
352-
private class SystemWebMvcHtmlHelperRawSink extends Sink, HtmlSink {
353-
SystemWebMvcHtmlHelperRawSink() {
354-
this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument()
355-
}
356-
}
357-
358262
/**
359263
* Gets a member which is accessed by the given `AspInlineCode`.
360264
* The code body must consist only of an access to the member, possibly with qualified
@@ -493,31 +397,6 @@ module XSS {
493397
}
494398
}
495399

496-
/** An expression that is returned from a `ToHtmlString` method. */
497-
private class ToHtmlString extends Sink, HtmlSink {
498-
ToHtmlString() {
499-
exists(Method toHtmlString |
500-
toHtmlString =
501-
any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and
502-
toHtmlString.canReturn(this.getExpr())
503-
)
504-
}
505-
}
506-
507-
/**
508-
* An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`.
509-
*/
510-
private class HtmlString extends Sink, HtmlSink {
511-
HtmlString() {
512-
exists(Class c |
513-
c = any(SystemWebMvcMvcHtmlString m) or
514-
c = any(SystemWebHtmlString m)
515-
|
516-
this.getExpr() = c.getAConstructor().getACall().getAnArgument()
517-
)
518-
}
519-
}
520-
521400
/**
522401
* An expression passed as the `content` argument to the constructor of `StringContent`.
523402
*/
@@ -529,75 +408,6 @@ module XSS {
529408
).getArgumentForName("content")
530409
}
531410
}
532-
533-
/**
534-
* An expression that is used as an argument to `Page.WriteLiteral`, typically in
535-
* a `.cshtml` file.
536-
*/
537-
class WebPageWriteLiteralSink extends Sink, HtmlSink {
538-
WebPageWriteLiteralSink() {
539-
this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument()
540-
}
541-
542-
override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteral() method" }
543-
}
544-
545-
/**
546-
* An expression that is used as an argument to `Page.WriteLiteralTo`, typically in
547-
* a `.cshtml` file.
548-
*/
549-
class WebPageWriteLiteralToSink extends Sink, HtmlSink {
550-
WebPageWriteLiteralToSink() {
551-
this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument()
552-
}
553-
554-
override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" }
555-
}
556-
557-
abstract class AspNetCoreSink extends Sink, HtmlSink { }
558-
559-
/**
560-
* An expression that is used as an argument to `HtmlHelper.Raw`, typically in
561-
* a `.cshtml` file.
562-
*/
563-
class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreSink {
564-
MicrosoftAspNetCoreMvcHtmlHelperRawSink() {
565-
this.getExpr() =
566-
any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument()
567-
}
568-
569-
override string explanation() {
570-
result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method"
571-
}
572-
}
573-
574-
/**
575-
* An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in
576-
* a `.cshtml` file.
577-
*/
578-
class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreSink {
579-
MicrosoftAspNetRazorPageWriteLiteralSink() {
580-
this.getExpr() =
581-
any(MicrosoftAspNetCoreMvcRazorPageBase h)
582-
.getWriteLiteralMethod()
583-
.getACall()
584-
.getAnArgument()
585-
}
586-
587-
override string explanation() {
588-
result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method"
589-
}
590-
}
591-
592-
/** `HtmlString` that may be rendered as is need to have sanitized value. */
593-
class MicrosoftAspNetHtmlStringSink extends AspNetCoreSink {
594-
MicrosoftAspNetHtmlStringSink() {
595-
exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s |
596-
c.getTarget() = s.getAConstructor() and
597-
this.asExpr() = c.getAnArgument()
598-
)
599-
}
600-
}
601411
}
602412

603413
private Type getMemberType(Member m) {

0 commit comments

Comments
 (0)