代码审计:python代码审计汇总(持续更新中)

后续有时间会持续更新补充,当前整理为一些重点漏洞的,如下:

命令注入、

代码注入、

不安全的反序列化、

sql注入、

任意文件下载、

文件上传(文件操作)、

XXE、

SSRF、

XSS、

直接重定向、

日志伪造、

模板注入SSTI、

不安全的随机数、

格式化的字符串

OS命令注入

主要是程序中通过Python的OS接口执行系统命令,常见的危险函数有等一些接口。

1、os.system( )

def myserve(request,fullname):
os.system("sudo rm -f %s"%fullname)

fullname是用户可控的,恶意用户只需利用shell的拼接符;就可以完成一次很好的攻击。

2、popen( )

os.popen( )
subprocess.popen( )

popen()函数是Python中用于执行外部命令的函数之一。它可以将一个shell命令作为参数传递给操作系统,并在Python中执行该命令的结果。

popen()函数是在subprocess模块中定义的。使用之前,我们需要先导入这个模块:

import subprocess

要执行一个命令,我们可以使用subprocess.Popen()函数。它的基本语法如下:

subprocess.Popen(cmd, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

3、platform.popen( )

import platform
print platform.popen('dir').read()

4、commands模块的一些方法

import commands

commands.getoutput('ifconfig')
commands.getstatusoutput('ifconfig')

subprocess模块的一些方法

subprocess.run()
subprocess.Popen()
subprocess.call()
subprocess.check_call()
subprocess.getstatusoutput()
subprocess.getoutput()
subprocess.check_output()

subprocess中的shell参数,如果shell=True的话,curl命令是被Bash(Sh)启动,所以支持shell语法。 如果shell=False的话,启动的是可执行程序本身,后面的参数不再支持shell语法。

防御办法需保证

(1)shell=True未设置

(2)转义变量的函数:Python 2.x使用pipes.quote(),Python 3.3或更高版本使用shlex.quote();

PS:其中Java中的Runtime.getRuntime().exec()效果类似shell=False,而PHP中的shell_exec就类似于shell=True,PHP中的exec则类似于shell=False。

spawn( ):

pty.spawn('whoami')

importlib.import_module()

importlib.import_module('os').system('whoami')
importlib.__import__('os').system('whoami')

代码注入

任意代码执行需关注的函数:

**eval():**将字符串str当成有效的表达式来求值并返回计算结果。

**exec():**执行 shell 命令、代码。与 eval() 函数类似,都是用于执行字符串形式的代码。然而,exec() 函数更加强大,可以执行多条语句甚至整个代码块。

eval('__import__("os").system("dir")')
exec('__import__("os").system("dir")')

案例参考:

(1)eval() 函数 :python的序列话函数eval,将字符串str当成有效的表达式来求值并返回计算结果。

代码示例:

>>>x = 7
>>> eval( '3 * x' )
21

例1:request引入的login参数

def eval_test(request,login):
login = eval(login)

如果恶意用户从外界传入 import(“os”).system(“rm /tmp -fr”) 就可以清空tmp目录。

例2:input引入的参数

user input = input("请输入一个表达式:")
result = eval (user input)
print("结果::", result)

**为了避免此类问题,,**可以使用其他替代方法,如

ast.literal_eval () 或 int() 、 float() 、eval ()函数的安全子集

(2)exec函数

exec() 函数与 eval() 函数类似,都是用于执行字符串形式的代码。然而,exec() 函数更加强大,可以执行多条语句甚至整个代码块。因此,不正确使用 exec() 函数可能会导致安全漏洞。下面是一个示例:

user_input = input("请输入一段代码:")
exec(user_input)

上述代码中,恶意用户可以输入恶意代码来执行潜在的危险操作。为了提高安全性,可以限制可执行的代码范围,或使用其他更安全的替代方法。

**execfile():**execfile() 函数可以用来执行一个文件。返回表达式执行结果。

execfile(filename[, globals[, locals]])

filename -- 文件名。
globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。

**compile():**是一个内置函数,用于将字符串形式的 Python 代码编译为可执行的代码对象,或者将 AST(抽象语法树)对象编译为代码对象。

**timeit():**timeit.timeit( ) 创建一个Timer实例,并运行代码进行计时,默认将代码执行一百万次。timeit模块是Python内置的用于统计小段代码执行时间的模块,它同时提供命令行调用接口。

import timeit

timeit.timeit("__import__('os').system('dir')",number=1)

**timeit.repeat():**指定重复次数的执行timeit方法,返回一个结果列表。

不安全的反序列化

Python中用于反序列化的模块有:

marshal

PyYAML——>yaml.safe_load()

yaml.load

import yaml

yamlString = getYamlFromUser()
yaml.load(yamlString)

pickle/cpickle

shelve

PIL

Unzip

1、pickle模块

pickle 是Python中的一个库,用于序列化和反序列化Python对象。然而,pickle 可能存在安全风险,因为它可以执行任意代码。下面是一个示例:

import pickle

class User:

def __init__(self, name):
user = User("Alice")
pickle_data = pickle.dumps(user)
loaded_user = pickle.loads(pickle_data)
print("用户名称:", loaded_user.name)

上述代码中,pickle.dumps() 和 pickle.loads() 函数可将 user 对象序列化和反序列化。然而,如果从不受信任的源加载数据,可能导致执行未经授权的操作。为了避免此类问题,可以使用其他更安全的序列化方法,如 json 或 yaml。

2、cPickle模块

cPickle.loads("cos\nsystem\n(S'uname -a'\ntR.")

Sql注入

在一般的Python web框架中都对sql注入做了防护,但是千万别认为就没有注入风险,使用不当也会导致sql注入。

例如:

%user_idres = cur.execute(sql)

修复:正确的使用(直白一点就是:使用”逗号”,而不是”百分号”)

错误的示范:

def getUsers(user_id):
sql = ‘select * from auth_user where id =%s’
%user_idres = cur.execute(sql)

修复:

execute() 函数本身有接受sql语句参数位的,

可以通过python自身的函数处理sql注入问题。

args = (id, type)

cur.execute(
'select id,name from user_table where id = %s and name = %s',args )

rs=c.execute(
"select * from log where
f_UserName=:usr",{"usr":"fanfan"})
rs=c.execute(
"select * from log where f_UserName=:1 ",["fanfan"])

使用如此参数带入方式,python会自动过滤args中的特殊字符,制止SQL注入的产生。

错误用法:

sql =
“select id,type,name from xl_bugs
where id = %s and type = %s” % (id, type)
cur.execute(sql)

正确用法:

cursor.execute(
'select name,password fromt b1
where name=%s and password=%s',('min',1234))
result= cursor.fetchone()
print(result)

正确的使用(直白一点就是:使用”逗号”,而不是”百分号”)

任意文件下载

程序员编写了一个下载报表或者任务的功能,如果没有控制好参数就会导致任意文件下载,

例如:fullname参数

def export_task(request,filename):
return HttpResponse(fullname)

文件操作漏洞

Python代码中文件处理需关注的函数有:

file()

file.save()

open()

codecs.open()

示例:以下代码会处理上传的文件,并将它们移到 Web 根目录下的一个目录中。攻击者可以将恶意文件上传到该程序,并随后从服务器中请求这些文件。

from django.core.files.storage import default_storage
from django.core.files.base import File
...
def handle_upload(request):
files = request.FILES
for f in files.values():
path = default_storage.save('upload/', File(f))
...

即使程序将上传的文件存储在一个无法通过 Web 访问的目录中,攻击者仍然有可能通过向服务器环境引入恶意内容来发动其他攻击。

如果程序容易出现

path manipulationcommand injection 或 remote include 漏洞,

那么攻击者就可能上传带恶意内容的文件,并利用另一种漏洞促使程序读取或执行该文件。

XXE

关注Python代码是否导入使用xml处理解析类:

xml.dom.*

xml.etree.ElementTree

xml.sax.*

错误示例代码如:

from xml import etree
tree1 = etree.parse('test.xml')
print etree.tostring(tree1.getroot())

SSRF

关注代码是否存在发起请求的库及函数,常见的有自带库requests.get()及urllib/urllib2库,

用法为

url = request.GET['url']
handle = urllib.urlopen(url)
//urllib.request.urlopen(url)。

XSS

下列代码若输入可控则可造成XSS:

return HttpResponse('hello %s' %(name))

安全的写法为

return render_to_response('hello.html', {'name':name})

直接重定向

以下 Python 代码会在用户单击链接时,指示用户浏览器打开从 dest 请求参数中解析的 URL。

...
strDest = request.field("dest")
redirect(strDest)
...

日志伪造

关注logging()函数及LOGGER 等关键字,查看是否输出口令、密钥和其他敏感信息及输入是否可插入%0A%0D进行日志伪造。

模板注入(SSTI)

所谓模板注入,又称服务器端模板注入(SSTI),通常发生在使用Jinja2、Django等模板引擎在Web应用程序中渲染模板时。

攻击者通过在模板中注入恶意代码,使得渲染后的页面能够执行这些代码。如果服务器端模板引擎没有对输入进行适当的验证和过滤,就可能导致SSTI攻击。

flask的渲染方法有render_template和render_template_string两种,render_template()是用来渲染一个指定的文件的,render_template_string则是用来渲染一个字符串的,不正确的使用flask中的render_template_string方法会引发SSTI

以下是一个简单的Python SSTI攻击示例,假设你有一个Web应用程序,它使用Flask框架并且存在SSTI攻击:

from flask import Flask, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
name = request.args.get('name', 'Guest')
return render_template_string('Hello, {{ name }}!', name=name)
if __name__ == '__main__':
app.run(debug=True)

攻击者可以通过注入SSTI表达式来改变模板的渲染,例如:

http://your-app.com/?name={{ 7*7 }}

如果存在SSTI攻击,攻击者可以执行恶意的命令,例如:

http://your-app.com/?name={{ config.class.init.globals[‘os’].popen(‘whoami’).read() }}

这将执行os.popen(‘whoami’).read()命令,显示当前操作系统的用户名。

Flask中的SSTI防御策略

(1)使用ORM(Object-Relational Mapping)框架

ORM框架如SQLAlchemy可以为数据库操作提供一层抽象,减少直接编写SQL语句的需求。这降低了SQL注入的风险,间接地防范了SSTI攻击。

(2)验证和过滤输入

在处理用户输入时,应始终进行验证和过滤。对于模板中的变量,应确保其不包含任何恶意代码。在Flask中,可以使用Jinja2模板引擎提供的Markup类来自动转义变量,防止XSS攻击。例如:

from flask import Flask, render_template_string
from jinja2 import Markup, Environment, FileSystemLoader

app = Flask(__name__)
env = Environment(loader=FileSystemLoader('templates'))
@app.route('/')
def index():
user_input = '<img src=x onerror=alert(1)>'  # 恶意代码
template = env.get_template('index.html')
output = template.render(user_input=Markup(user_input))  # 自动转义变量
return output

(3)使用Web框架提供的工具

许多Web框架提供了工具来帮助开发者防范SSTI攻击。在Flask中,可以使用render_template函数来渲染模板,该函数会自动处理输入并进行转义。因此,建议尽可能使用render_template而不是直接使用render_template_string

(4)保持框架和库的更新

及时更新Flask及其依赖库可以确保你使用的是最新版本,新版本通常会修复已知的安全漏洞。此外,关注安全社区和官方发布的信息,以便及时了解最新的安全威胁和防御策略。

除了上述防御策略外,还应遵循其他一些最佳实践来提高安全性。例如:限制对模板文件的访问权限、避免在模板中存储敏感数据、使用HTTPOnly cookie等。

其他

不安全随机数:

当用于安全加密用途时,不可采用形如random.randint(0, 100)不安全的随机数生成机制;

在Linux和类Unix下用,需使用/dev/random生成安全随机数,在windows下,使用random模块中的SystemRandom类来实现。

格式化字符串:

使用形如下列格式化字符串容易造成敏感信息泄露:

is %s" % (‘jayway’, )或"Myname is {}".format(‘jayway’)

“My name is %(name)%” % {‘name’:‘jayway’}

python代码审计工具:

Bandit安装

Bandit 安装需要Python环境支持,安装Python3后,执行以下命令:

pip install bandit

安装bandit完成后,执行以下命令:

bandit -r F:\PythonSpace\sm\bank\ -f html -o 1.html

其中:

F:\PythonSpace\sm\bank\ 为扫描的源码目录

-f html 指定生成html报告,工具支持多种格式,如csv,custom,html,json,screen,txt,xml,yaml。

-o 1.html 指定导出的文件名

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑战士安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值