Skip to content

Commit e8d0827

Browse files
committed
Add tornado source
1 parent b866f1b commit e8d0827

File tree

5 files changed

+90
-16
lines changed

5 files changed

+90
-16
lines changed

python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,27 @@ private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIp
4646
}
4747
}
4848

49+
private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck {
50+
TornadoClientSuppliedIpUsedInSecurityCheck() {
51+
exists(RemoteFlowSource rfs, DataFlow::LocalSourceNode lsn |
52+
rfs.getSourceType() = "tornado.web.RequestHandler" and rfs.asCfgNode() = lsn.asCfgNode()
53+
|
54+
lsn.flowsTo(DataFlow::exprNode(this.getFunction()
55+
.asExpr()
56+
.(Attribute)
57+
.getObject()
58+
.(Attribute)
59+
.getObject()
60+
.(Attribute)
61+
.getObject())) and
62+
this.getFunction().asExpr().(Attribute).getName() in ["get", "get_list"] and
63+
this.getFunction().asExpr().(Attribute).getObject().(Attribute).getName() = "headers" and
64+
this.getArg(0).asCfgNode().getNode().(StrConst).getText().toLowerCase() =
65+
clientIpParameterName()
66+
)
67+
}
68+
}
69+
4970
private string clientIpParameterName() {
5071
result in [
5172
"x-forwarded-for", "x_forwarded_for", "x-real-ip", "x_real_ip", "proxy-client-ip",
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
edges
2-
| ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip |
3-
| ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip |
2+
| flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip |
3+
| flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip |
4+
| tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip |
45
nodes
5-
| ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
6-
| ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip |
7-
| ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
8-
| ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip |
6+
| flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
7+
| flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip |
8+
| flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
9+
| flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip |
10+
| tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
11+
| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip |
912
#select
10-
| ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input |
11-
| ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | ClientSuppliedIpUsedInSecurityCheck.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input |
13+
| flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input |
14+
| flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input |
15+
| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | this user input |
Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@ def bad2():
2222
raise Exception('ip illegal')
2323
return 'bad2'
2424

25-
@app.route('/good1')
26-
def good1():
27-
client_ip = request.headers.get('x-forwarded-for')
28-
client_ip = client_ip.split(',')[client_ip.split(',').length - 1]
29-
if not client_ip == '127.0.0.1':
30-
raise Exception('ip illegal')
31-
return 'good1'
32-
3325
if __name__ == '__main__':
3426
app.debug = True
3527
app.run()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python
2+
# -*- coding: UTF-8 -*-
3+
"""
4+
@Desc :ip address spoofing
5+
"""
6+
from flask import Flask
7+
from flask import request
8+
9+
app = Flask(__name__)
10+
11+
@app.route('/good1')
12+
def good1():
13+
client_ip = request.headers.get('x-forwarded-for')
14+
client_ip = client_ip.split(',')[len(client_ip.split(',')) - 1]
15+
if not client_ip == '127.0.0.1':
16+
raise Exception('ip illegal')
17+
return 'good1'
18+
19+
if __name__ == '__main__':
20+
app.debug = True
21+
app.run()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env python
2+
# -*- coding: UTF-8 -*-
3+
"""
4+
@Desc :ip address spoofing
5+
"""
6+
import tornado.httpserver
7+
import tornado.options
8+
import tornado.web
9+
import tornado.ioloop
10+
11+
from tornado.options import define, options
12+
13+
define("port", default=8000, help="run on the given port,default 8000", type=int)
14+
15+
16+
class IndexHandler(tornado.web.RequestHandler):
17+
def get(self):
18+
client_ip = self.request.headers.get('x-forwarded-for')
19+
if client_ip:
20+
client_ip = client_ip.split(',')[len(client_ip.split(',')) - 1]
21+
else:
22+
client_ip = self.request.headers.get('REMOTE_ADDR', None)
23+
if not client_ip == '127.0.0.1':
24+
raise Exception('ip illegal')
25+
self.write("hello.")
26+
27+
handlers = [(r"/", IndexHandler)]
28+
29+
if __name__ == "__main__":
30+
tornado.options.parse_command_line()
31+
app = tornado.web.Application(
32+
handlers
33+
)
34+
http_server = tornado.httpserver.HTTPServer(app)
35+
http_server.listen(options.port)
36+
tornado.ioloop.IOLoop.instance().start()

0 commit comments

Comments
 (0)