SQL注入

安全的做法:

不安全的做法:

大部分Python操作数据库的第三方模块,如pymysql、sqlite3等,执行sql语句的函数,都支持参数化查询,如上安全的做法所示,可以给sql语句传递参数,这个参数经过过滤。而下面的字符串拼接是不经过过滤。所以会出现sql注入。

 

命令执行

危险的函数或模块列表:

  • os.popen*
  • os.system
  • os.spawn*
  • os.fork
  • os.exec*
  • popen2.*
  • commands.*
  • subprocess.call

这里着重说明了,subprocess.call函数:

危险的用法:

这里说一下shell这个参数的作用,如果shell为True,subprocess.call会给予更大的权限,因为使用shell=True, subprocess.call会在命令前添加/bin/sh -c(windows是cmd.exe /c)。测试:

执行subprocess.call函数的几点建议:

  1. 使用pipes.quote()函数去过滤用户输入,可以过滤命令拼接
  2. 尽量不要使用shell=True
  3. 即使不使用shell=True,也尽量去过滤用户输入
  4. 如果用户的输入是路径的话,可以使用下面目录遍历的防护方法进行防护

目录遍历

危险的代码例如:

防护思路:

abspath是获取绝对路径,这段代码的意思就是限定用户读取的目录为当前目录。我们可以把os.getcwd()替换成os.path.realpath限定当前目录下的任意子目录。

XSS

原作者提到如果webapp没有使用模板语言的话,又没有使用cgi.escape()对用户输入进行过滤直接加到程序返回给客户端的情况,就会产生XSS。cgi.escape()函数会把<>尖括号转化为html实体编码,如果使用cgi.escape(user_input, True),会把’”单引号双引号也转成实体编码。

其实就算使用了模板语言也很容易产生XSS。因为每一个模板语言都有一个可以不转义<>'"等html特殊字符的选项。以jinja2为例,jinja2默认会对所有传进来的变量进行转义,但有下面两种情况是例外的:

  1. 传进的变量是一个MarkupSafe.Markup对象,例如MarkupSafe.Markup('<script>alert(1)</script>>')
  2. 该模板使用|safe进行标记,例如

以上两种情况,就算你使用了jinja2模板传入参数也有可能会产生Xss。当然如果你直接把用户输入拼接到模板中,也同样会产生XSS,不过那会产生更加严重的SSTI。

异常处理

这里作者提到了异常处理的正确方式,其实我觉得并不只在Python里面有,是大部分程序员在开发时候的通病。处理异常的时候直接pass,不回显,也不记录异常信息,不分类处理异常,导致错误无法跟踪。这里我推荐看一下:https://www.zhihu.com/question/29459586中pig pig的回答,他的描述比原作者要详细一些。

至于这个我觉得超出了安全审计的范围,是代码规范和软件测试的范畴。在这里就不说明了。

作者:neargle

原文链接:http://blog.neargle.com/2016/07/25/log-of-simple-code-review-about-python-base-webapp/index.html