python - 在 Django 后端使用 Clamav 设置文件上传流扫描
问题描述
使用 React/Django 应用程序。我有用户通过 React 前端上传的文件,这些文件最终在 Django/DRF 后端。我们在服务器上不断运行防病毒 (AV),但我们希望在将其写入磁盘之前添加流扫描。
如何设置它有点让我头疼。以下是我正在查看的一些来源。
您如何对上传到您的 java webapp 的文件进行病毒扫描?
尽管公认的最佳答案描述了它“......非常容易”设置,但我正在努力。
我显然需要cat testfile | clamscan -
按照帖子和相应的文档:
您如何对上传到您的 java webapp 的文件进行病毒扫描?
因此,如果我的后端如下所示:
class SaveDocumentAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
# this is for handling the files we do want
# it writes the files to disk and writes them to the database
for f in request.FILES.getlist('file'):
max_id = Uploads.objects.all().aggregate(Max('id'))
if max_id['id__max'] == None:
max_id = 1
else:
max_id = max_id['id__max'] + 1
data = {
'user_id': request.user.id,
'sur_id': kwargs.get('sur_id'),
'co': User.objects.get(id=request.user.id).co,
'date_uploaded': datetime.datetime.now(),
'size': f.size
}
filename = str(data['co']) + '_' + \
str(data['sur_id']) + '_' + \
str(max_id) + '_' + \
f.name
data['doc_path'] = filename
self.save_file(f, filename)
serializer = SaveDocumentSerializer(data=data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(status=HTTP_200_OK)
# Handling the document
def save_file(self, file, filename):
with open('fileupload/' + filename, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
我想我需要在save_file
方法中添加一些东西,比如:
for chunk in file.chunks():
# run bash comman from python
cat chunk | clamscan -
if passes_clamscan:
destination.write(chunk)
return HttpResponse('It passed')
else:
return HttpResponse('Virus detected')
所以我的问题是:
1) 如何从 Python 运行 Bash?
2)如何接收扫描的结果响应,以便可以将其发送回用户,并且可以通过后端的响应来完成其他事情?(比如创建逻辑来向用户和管理员发送一封电子邮件,说明他们的文件有病毒)。
我一直在玩这个,但运气不佳。
此外,那里有 Github 存储库声称将 Clamav 与 Django 结合得很好,但它们要么多年未更新,要么现有文档非常糟糕。请参阅以下内容:
https://github.com/vstoykov/django-clamd
解决方案
Ok, got this working with clamd. I modified my SaveDocumentAPIView
to the following. This scans the files before they are written to disk and prevents them from being written if they infected. Still allows uninfected files through, so the user doesn't have to re-upload them.
class SaveDocumentAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
# create array for files if infected
infected_files = []
# setup unix socket to scan stream
cd = clamd.ClamdUnixSocket()
# this is for handling the files we do want
# it writes the files to disk and writes them to the database
for f in request.FILES.getlist('file'):
# scan stream
scan_results = cd.instream(f)
if (scan_results['stream'][0] == 'OK'):
# start to create the file name
max_id = Uploads.objects.all().aggregate(Max('id'))
if max_id['id__max'] == None:
max_id = 1
else:
max_id = max_id['id__max'] + 1
data = {
'user_id': request.user.id,
'sur_id': kwargs.get('sur_id'),
'co': User.objects.get(id=request.user.id).co,
'date_uploaded': datetime.datetime.now(),
'size': f.size
}
filename = str(data['co']) + '_' + \
str(data['sur_id']) + '_' + \
str(max_id) + '_' + \
f.name
data['doc_path'] = filename
self.save_file(f, filename)
serializer = SaveDocumentSerializer(data=data)
if serializer.is_valid(raise_exception=True):
serializer.save()
elif (scan_results['stream'][0] == 'FOUND'):
send_mail(
'Virus Found in Submitted File',
'The user %s %s with email %s has submitted the following file ' \
'flagged as containing a virus: \n\n %s' % \
(
user_obj.first_name,
user_obj.last_name,
user_obj.email,
f.name
),
'The Company <no-reply@company.com>',
['admin@company.com']
)
infected_files.append(f.name)
return Response({'filename': infected_files}, status=HTTP_200_OK)
# Handling the document
def save_file(self, file, filename):
with open('fileupload/' + filename, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
推荐阅读
- excel - 表格数据从 Excel 输入到 Anylogic 中的系统动态库存
- kubernetes - Kubernetes 控制平面通信
- angular - 访问服务之外的值
- python - 组 lat/lon ,如果它们出现在边界框内
- sql - 在 SQL SERVER 的逗号分隔列中获取不同的值
- matlab - 如何从 Simulink 到 Matlab 获得非线性系统的响应曲线特征(上升时间、稳定时间、稳态、过冲)?
- flutter - 单击文本按钮颤动时如何显示包含卡片的ListView
- mysql - SQL 查询性能问题不存在
- java - 在sleuth中添加新标签应该怎么做,比如客户端ip地址,我想在日志中添加客户端ip地址,当然有traceId,spanId
- typescript - 我可以强制 TypeScript 解析 Pick 的类型吗
展示?