记一下PythonWeb代码审计应该注意的地方
读《Code Review For Python-Based Web Apps》(《PythonWebApp代码审计》)做的笔记,正好自己也在写相关的文章:讨论PythonWeb开发中可能会遇到的安全问题,所以就翻译了一下作者原文,省去一些不必要的口水,并添加了一些自己的想法。
SQL注入
安全的做法:
1 | stmt = "SELECT * FROM table WHERE id=?" |
不安全的做法:1
2
3"SELECT * FROM table WHERE id=" + value
"SELECT * FROM table WHERE id=%s" % value
"SELECT * FROM table WHERE id={0}".format(value)
大部分Python操作数据库的第三方模块,如pymysql、sqlite3等,执行sql语句的函数,都支持参数化查询,如上安全的做法所示,可以给sql语句传递参数,这个参数经过过滤。而下面的字符串拼接是不经过过滤。所以会出现sql注入。
命令执行
危险的函数或模块列表:
- os.popen*
- os.system
- os.spawn*
- os.fork
- os.exec*
- popen2.*
- commands.*
- subprocess.call
这里着重说明了,subprocess.call函数:
危险的用法:
1 | subprocess.call("cat " + user_input, shell=True) |
这里说一下shell这个参数的作用,如果shell为True,subprocess.call会给予更大的权限,因为使用shell=True
, subprocess.call会在命令前添加/bin/sh -c
(windows是cmd.exe /c
)。测试:
执行subprocess.call函数的几点建议:
- 使用pipes.quote()函数去过滤用户输入,可以过滤命令拼接
- 尽量不要使用shell=True
- 即使不使用shell=True,也尽量去过滤用户输入
- 如果用户的输入是路径的话,可以使用下面目录遍历的防护方法进行防护
目录遍历
危险的代码例如:
1 | open(user_input) |
防护思路:
1 | cwd = os.getcwd() |
abspath是获取绝对路径,这段代码的意思就是限定用户读取的目录为当前目录。我们可以把os.getcwd()
替换成os.path.realpath
限定当前目录下的任意子目录。
XSS
原作者提到如果webapp没有使用模板语言的话,又没有使用cgi.escape()对用户输入进行过滤直接加到程序返回给客户端的情况,就会产生XSS。cgi.escape()函数会把<>尖括号转化为html实体编码,如果使用cgi.escape(user_input, True),会把’”单引号双引号也转成实体编码。
其实就算使用了模板语言也很容易产生XSS。因为每一个模板语言都有一个可以不转义<>'"
等html特殊字符的选项。以jinja2为例,jinja2默认会对所有传进来的变量进行转义,但有下面两种情况是例外的:
- 传进的变量是一个
MarkupSafe.Markup
对象,例如MarkupSafe.Markup('<script>alert(1)</script>>')
- 该模板使用|safe进行标记,例如
以上两种情况,就算你使用了jinja2模板传入参数也有可能会产生Xss。当然如果你直接把用户输入拼接到模板中,也同样会产生XSS,不过那会产生更加严重的SSTI。
异常处理
这里作者提到了异常处理的正确方式,其实我觉得并不只在Python里面有,是大部分程序员在开发时候的通病。处理异常的时候直接pass,不回显,也不记录异常信息,不分类处理异常,导致错误无法跟踪。这里我推荐看一下:https://www.zhihu.com/question/29459586
中pig pig的回答,他的描述比原作者要详细一些。
至于这个我觉得超出了安全审计的范围,是代码规范和软件测试的范畴。在这里就不说明了。
https://blog.neargle.com/2016/07/25/log-of-simple-code-review-about-python-base-webapp/
本博客所有内容只用于安全研究,请勿用于恶意攻击。
本文URL: "https://blog.neargle.com/2016/07/25/log-of-simple-code-review-about-python-base-webapp/index.html"