Skip to content

Commit 7fa7f2d

Browse files
author
james
committed
docs: add rst versions of java slide decks and improve a few c++ slides
1 parent 1bd0c69 commit 7fa7f2d

20 files changed

+1118
-112
lines changed

docs/language/ql-training-rst/_static-training/java-data-flow-code-example.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/language/ql-training-rst/_static-training/java-expression-ast.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/language/ql-training-rst/_static-training/mismatched-calls-and-returns.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/language/ql-training-rst/_static-training/slides-semmle-2/static/theme/css/default.css

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -744,11 +744,7 @@ table tr:nth-child(odd) {
744744
table th {
745745
color: white;
746746
font-size: 1em;
747-
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0MCUiIHN0b3AtY29sb3I9IiM0Mzg3ZmQiLz48c3RvcCBvZmZzZXQ9IjgwJSIgc3RvcC1jb2xvcj0iIzJhN2NkZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==') no-repeat;
748-
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(40%, #4387fd), color-stop(80%, #2a7cdf)) no-repeat;
749-
background: -moz-linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;
750-
background: -webkit-linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;
751-
background: linear-gradient(to bottom, #4387fd 40%, #2a7cdf 80%) no-repeat;
747+
background: grey;
752748
}
753749
/* line 494, ../scss/default.scss */
754750
table td, table th {
@@ -758,17 +754,16 @@ table td, table th {
758754
/* line 499, ../scss/default.scss */
759755
table td.highlight {
760756
color: #515151;
761-
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0MCUiIHN0b3AtY29sb3I9IiNmZmQxNGQiLz48c3RvcCBvZmZzZXQ9IjgwJSIgc3RvcC1jb2xvcj0iI2Y2YzAwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==') no-repeat;
762-
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(40%, #ffd14d), color-stop(80%, #f6c000)) no-repeat;
763-
background: -moz-linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;
764-
background: -webkit-linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;
765-
background: linear-gradient(to bottom, #ffd14d 40%, #f6c000 80%) no-repeat;
757+
background: grey;
766758
}
767759
/* line 504, ../scss/default.scss */
768760
table.rows {
769761
border-bottom: none;
770762
border-right: 1px solid #797979;
771763
}
764+
table td {
765+
background: white;
766+
}
772767

773768
/* line 510, ../scss/default.scss */
774769
q {
@@ -1469,6 +1464,15 @@ hgroup .pre {
14691464
color: white;
14701465
}
14711466

1467+
.subheading {
1468+
position: absolute;
1469+
top: 62.5%;
1470+
}
1471+
1472+
.subheading p {
1473+
position: relative;
1474+
}
1475+
14721476
/* purple background slides (new section)*/
14731477

14741478
.background2 {
@@ -1593,7 +1597,7 @@ p.first.admonition-title {
15931597
width: inherit;
15941598
}
15951599

1596-
/* images */
1600+
/********* images ************/
15971601
/* general styles to scale and centre images*/
15981602

15991603
.image-box {
@@ -1606,7 +1610,7 @@ img {
16061610
margin: auto;
16071611
}
16081612

1609-
/* deck-specific styles for individual images*/
1613+
/********* deck-specific styles for individual images *********/
16101614
/* intro to ql */
16111615
img.analysis {
16121616
width: 90%;
@@ -1619,6 +1623,26 @@ img.analysis {
16191623
right: -10%;
16201624
}
16211625

1626+
.java-expression-ast {
1627+
background-image: url("../../java-expression-ast.svg");
1628+
background-size: cover;
1629+
}
1630+
1631+
/* java data flow code example */
1632+
1633+
.java-data-flow-code-example {
1634+
background-image: url("../../java-data-flow-code-example.svg");
1635+
background-size: cover;
1636+
}
1637+
1638+
/* extra global data flow slies*/
1639+
1640+
.mismatched-calls-and-returns {
1641+
background-image: url("../../mismatched-calls-and-returns.svg");
1642+
background-size: cover;
1643+
}
1644+
1645+
/******* Other custom styles *******/
16221646
/* custom styles for lists*/
16231647

16241648
ol {

docs/language/ql-training-rst/cpp/data-flow-cpp.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,4 +343,4 @@ Beyond local data flow
343343
- Results are still underwhelming.
344344
- Dealing with parameter passing becomes cumbersome.
345345
- Instead, let’s turn the problem around and find user-controlled data that flows into a ``printf`` format argument, potentially through calls.
346-
- This needs :doc:`global data flow <global-data-flow-cpp>`.
346+
- This needs :doc:`global data flow <global-data-flow-cpp>`.

docs/language/ql-training-rst/cpp/global-data-flow-cpp.rst

Lines changed: 1 addition & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -252,86 +252,4 @@ Data flow models
252252
Extra slides
253253
============
254254

255-
Exercise: How not to do global data flow
256-
========================================
257-
258-
Implement a ``flowStep`` predicate extending ``localFlowStep`` with steps through function calls and returns. Why might we not want to use this?
259-
260-
.. code-block:: ql
261-
262-
predicate stepIn(Call c, DataFlow::Node arg, DataFlow::ParameterNode parm) {
263-
exists(int i | arg.asExpr() = c.getArgument(i) |
264-
parm.asParameter() = c.getTarget().getParameter(i))
265-
}
266-
267-
predicate stepOut(Call c, DataFlow::Node ret, DataFlow::Node res) {
268-
exists(ReturnStmt retStmt | retStmt.getEnclosingFunction() = c.getTarget() |
269-
ret.asExpr() = retStmt.getExpr() and res.asExpr() = c)
270-
}
271-
272-
predicate flowStep(DataFlow::Node pred, DataFlow::Node succ) {
273-
DataFlow::localFlowStep(pred, succ) or
274-
stepIn(_, pred, succ) or
275-
stepOut(_, pred, succ)
276-
}
277-
278-
Mismatched calls and returns
279-
============================
280-
281-
.. container:: column-left
282-
283-
.. code-block:: ql
284-
285-
char *logFormat(char *fmt) {
286-
log("Observed format string %s.", fmt);
287-
return fmt;
288-
}
289-
290-
...
291-
char *dangerousFmt = unvalidatedUserData();
292-
printf(logFormat(dangerousFmt), args);
293-
...
294-
char *safeFmt = "Hello %s!";
295-
printf(logFormat(safeFmt), name);
296-
297-
.. container:: column-right
298-
299-
Infeasible path due to mismatched call/return pair!
300-
301-
Balancing calls and returns
302-
===========================
303-
304-
- If we simply take ``flowStep*``, we might mismatch calls and returns, causing imprecision, which in turn may cause false positives.
305-
306-
- Instead, make sure that matching ``stepIn``/``stepOut`` pairs talk about the same call site:
307-
308-
.. code-block:: ql
309-
310-
predicate balancedPath(DataFlow::Node src, DataFlow::Node snk) {
311-
src = snk or DataFlow::localFlowStep(src, snk) or
312-
exists(DataFlow::Node m | balancedPath(src, m) | balancedPath(m, snk)) or
313-
exists(Call c, DataFlow::Node parm, DataFlow::Node ret |
314-
stepIn(c, src, parm) and
315-
balancedPath(parm, ret) and
316-
stepOut(c, ret, snk)
317-
)
318-
}
319-
320-
Summary-based global data flow
321-
==============================
322-
323-
- To avoid traversing the same paths many times, we compute *function summaries* that record if a function parameter flows into a return value:
324-
325-
.. code-block:: ql
326-
327-
predicate returnsParameter(Function f, int i) {
328-
exists (Parameter p, ReturnStmt retStmt, Expr ret |
329-
p = f.getParameter(i) and
330-
retStmt.getEnclosingFunction() = f and
331-
ret = retStmt.getExpr() and
332-
balancedPath(DataFlow::parameterNode(p), DataFlow::exprNode(ret))
333-
)
334-
}
335-
336-
- Use this predicate in balancedPath instead of ``stepIn``/``stepOut`` pairs.
337-
255+
.. include:: ../slide-snippets/global-data-flow-extra-slides.rst

docs/language/ql-training-rst/index.rst

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,4 @@ QL training and variant analysis examples
1010
:maxdepth: 1
1111
:hidden:
1212

13-
./cpp/intro-ql-cpp
14-
./cpp/bad-overflow-guard
15-
./cpp/program-representation-cpp
16-
./cpp/data-flow-cpp
17-
./cpp/snprintf
18-
./cpp/global-data-flow-cpp
19-
./cpp/control-flow-cpp
20-
21-
.. toctree::
22-
:glob:
23-
:maxdepth: 1
24-
:hidden:
25-
26-
./java/intro-ql-java
13+
./**/*
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
=======================
2+
Exercise: Apache Struts
3+
=======================
4+
5+
.. container:: subheading
6+
7+
Unsafe deserialization leading to an RCE
8+
9+
CVE-2017-9805
10+
11+
.. container:: semmle-logo
12+
13+
Semmle :sup:`TM`
14+
15+
.. rst-class:: setup
16+
17+
Setup
18+
=====
19+
20+
For this example you should download:
21+
22+
- `QL for Eclipse <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/install-plugin-free.html>`__
23+
- `Apache Struts snapshot <https://downloads.lgtm.com/snapshots/java/apache/struts/apache-struts-7fd1622-CVE-2018-11776.zip>`__
24+
25+
.. note::
26+
27+
For this example, we will be analyzing `Apache Struts <https://github.com/apache/struts>`__.
28+
29+
You can also query the project in `the query console <https://lgtm.com/query/project:1878521151/lang:java/>`__ on LGTM.com.
30+
31+
Note that results generated in the query console are likely to differ to those generated in the QL plugin as LGTM.com analyzes the most recent revisions of each project that has been added–the snapshot available to download above is based on an historical version of the code base.
32+
33+
Unsafe deserialization in Struts
34+
================================
35+
36+
Apache Struts provides a ContentTypeHandler interface, which can be implemented for specific content types. It defines the following interface method:
37+
38+
.. code-block:: java
39+
40+
void toObject(Reader in, Object target);
41+
42+
43+
which is intended to populate the “target” object with data from the reader, usually through deserialization. However, the in parameter should be considered untrusted, and should not be deserialized without sanitization.
44+
45+
RCE in Apache Struts
46+
====================
47+
48+
- Vulnerable code looked like this (`original <https://lgtm.com/projects/g/apache/struts/snapshot/b434c23f95e0f9d5bde789bfa07f8fc1d5a8951d/files/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java?sort=name&dir=ASC&mode=heatmap#L45>`__):
49+
50+
.. code-block:: java
51+
52+
public void toObject(Reader in, Object target) {
53+
XStream xstream = createXStream();
54+
xstream.fromXML(in, target);
55+
}
56+
57+
- Xstream allows deserialization of **dynamic proxies**, which permit remote code execution.
58+
59+
- Disclosed as `CVE-2017-9805 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9805>`__
60+
61+
- Blog post: https://lgtm.com/blog/apache_struts_CVE-2017-9805
62+
63+
Finding the RCE yourself
64+
========================
65+
66+
#. Create a QL class to find the interface ``org.apache.struts2.rest.handler.ContentTypeHandler``
67+
68+
**Hint**: Use predicate ``hasQualifiedName(...)``
69+
70+
#. Identify methods called ``toObject``, which are defined on direct subtypes of ``ContentTypeHandler``
71+
72+
**Hint**: Use ``Method.getDeclaringType()`` and ``Type.getASupertype()``
73+
74+
#. Implement a ``DataFlow::Configuration``, defining the source as the first parameter of a ``toObject`` method, and the sink as an instance of ``UnsafeDeserializationSink``.
75+
76+
**Hint**: Use ``Node::asParameter()``
77+
78+
#. Construct the query as a path-problem query, and verify you find one result.
79+
80+
Model answer, step 1
81+
====================
82+
83+
.. code-block:: ql
84+
85+
import java
86+
87+
/** The interface `org.apache.struts2.rest.handler.ContentTypeHandler`. */
88+
class ContentTypeHandler extends RefType {
89+
ContentTypeHandler() {
90+
this.hasQualifiedName("org.apache.struts2.rest.handler", "ContentTypeHandler")
91+
}
92+
}
93+
94+
Model answer, step 2
95+
====================
96+
97+
.. code-block:: ql
98+
99+
/** A `toObject` method on a subtype of `org.apache.struts2.rest.handler.ContentTypeHandler`. */
100+
class ContentTypeHandlerDeserialization extends Method {
101+
ContentTypeHandlerDeserialization() {
102+
this.getDeclaringType().getASupertype() instanceof ContentTypeHandler and
103+
this.hasName("toObject")
104+
105+
Model answer, step 3
106+
====================
107+
108+
.. code-block:: ql
109+
110+
import UnsafeDeserialization
111+
import semmle.code.java.dataflow.DataFlow::DataFlow
112+
/**
113+
* Configuration that tracks the flow of taint from the first parameter of
114+
* `ContentTypeHandler.toObject` to an instance of unsafe deserialization.
115+
*/
116+
class StrutsUnsafeDeserializationConfig extends Configuration {
117+
StrutsUnsafeDeserializationConfig() { this = "StrutsUnsafeDeserializationConfig" }
118+
override predicate isSource(Node source) {
119+
source.asParameter() = any(ContentTypeHandlerDeserialization des).getParameter(0)
120+
}
121+
override predicate isSink(Node sink) { sink instanceof UnsafeDeserializationSink }
122+
}
123+
124+
Model answer, step 4
125+
====================
126+
127+
.. code-block:: ql
128+
129+
import PathGraph
130+
...
131+
from PathNode source, PathNode sink, StrutsUnsafeDeserializationConfig conf
132+
where conf.hasFlowPath(source, sink)
133+
and sink.getNode() instanceof UnsafeDeserializationSink
134+
select sink.getNode().(UnsafeDeserializationSink).getMethodAccess(), source, sink, "Unsafe deserialization of $@.", source, "user input"
135+
136+
More full-featured version: https://github.com/Semmle/demos/tree/master/ql_demos/java/Apache_Struts_CVE-2017-9805

0 commit comments

Comments
 (0)