Skip to content

Commit 7cda901

Browse files
committed
Python: Add separate query for SimpleXMLRPCServer
This was a rough quick-n-dirty query, and should get some qhelp as well at some point.
1 parent 9406a97 commit 7cda901

5 files changed

Lines changed: 34 additions & 33 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @name SimpleXMLRPCServer DoS vulnerability
3+
* @description SimpleXMLRPCServer is vulnerable to DoS attacks from untrusted user input
4+
* @kind path-problem
5+
* @problem.severity warning
6+
* @precision high
7+
* @id py/simple-xml-rpc-server
8+
* @tags security
9+
* external/cwe/cwe-776
10+
*/
11+
12+
private import python
13+
private import semmle.python.dataflow.new.DataFlow
14+
private import semmle.python.Concepts
15+
private import experimental.semmle.python.Concepts
16+
private import semmle.python.ApiGraphs
17+
18+
from DataFlow::CallCfgNode call, string kinds
19+
where
20+
call = API::moduleImport("xmlrpc").getMember("server").getMember("SimpleXMLRPCServer").getACall() and
21+
kinds =
22+
strictconcat(XML::XMLVulnerabilityKind kind |
23+
kind.isBillionLaughs() or kind.isQuadraticBlowup()
24+
|
25+
kind, ", "
26+
)
27+
select call, "SimpleXMLRPCServer is vulnerable to: " + kinds + "."

python/ql/src/experimental/semmle/python/frameworks/Xml.qll

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -329,34 +329,4 @@ private module Xml {
329329
(kind.isBillionLaughs() or kind.isQuadraticBlowup())
330330
}
331331
}
332-
333-
/**
334-
* Gets a call to `xmlrpc.server.SimpleXMLRPCServer`.
335-
*
336-
* Given the following example:
337-
*
338-
* ```py
339-
* server = SimpleXMLRPCServer(("127.0.0.1", 8000))
340-
* server.register_function(foo, "foo")
341-
* server.serve_forever()
342-
* ```
343-
*
344-
* * `this` would be `SimpleXMLRPCServer(("127.0.0.1", 8000))`.
345-
* * `getAnInput()`'s result would be `foo`.
346-
* * `vulnerable(kind)`'s `kind` would be `Billion Laughs` and `Quadratic Blowup`.
347-
*/
348-
private class XMLRPCServer extends DataFlow::CallCfgNode, XML::XMLParser::Range {
349-
XMLRPCServer() {
350-
this =
351-
API::moduleImport("xmlrpc").getMember("server").getMember("SimpleXMLRPCServer").getACall()
352-
}
353-
354-
override DataFlow::Node getAnInput() {
355-
result = this.getAMethodCall("register_function").getArg(0)
356-
}
357-
358-
override predicate vulnerable(XML::XMLVulnerabilityKind kind) {
359-
kind.isBillionLaughs() or kind.isQuadraticBlowup()
360-
}
361-
}
362332
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| xmlrpc_server.py:7:10:7:48 | ControlFlowNode for SimpleXMLRPCServer() | SimpleXMLRPCServer is vulnerable to: Billion Laughs, Quadratic Blowup. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE-611/SimpleXmlRpcServer.ql
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from xmlrpc.server import SimpleXMLRPCServer
22

3-
def foo(n):
4-
return n
3+
def foo(n: str):
4+
print("foo called with arg:", n, type(n))
5+
return "ok"
56

67
server = SimpleXMLRPCServer(("127.0.0.1", 8000))
78
server.register_function(foo, "foo")
89
server.serve_forever()
910

10-
# billion_laughs -> curl 127.0.0.1:8000 --data-raw '<?xml version="1.0"?><!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)><!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]><methodCall><methodName>foo</methodName><params><param><value>&lol9;</value></param></params></methodCall>'
11+
# normal: curl 127.0.0.1:8000 --data-raw '<?xml version="1.0"?><methodCall><methodName>foo</methodName><params><param><value>42</value></param></params></methodCall>'
12+
# billion_laughs: curl 127.0.0.1:8000 --data-raw '<?xml version="1.0"?><!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)><!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]><methodCall><methodName>foo</methodName><params><param><value>&lol9;</value></param></params></methodCall>'

0 commit comments

Comments
 (0)