Skip to content

Commit

Permalink
Merge pull request #981 from hhyo/bugfix/sql-escape
Browse files Browse the repository at this point in the history
对接受入参的SQL拼接增加参数转义,规避注入风险 fix #979
  • Loading branch information
hhyo authored Dec 6, 2020
2 parents 1b84227 + 0092338 commit 73a74e5
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 4 deletions.
4 changes: 4 additions & 0 deletions sql/binlog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: UTF-8 -*-
import MySQLdb
import logging
import os
import time
Expand Down Expand Up @@ -62,6 +63,9 @@ def del_binlog(request):
result = {'status': 1, 'msg': '实例不存在', 'data': []}
return HttpResponse(json.dumps(result), content_type='application/json')

# escape
binlog = MySQLdb.escape_string(binlog).decode('utf-8')

if binlog:
query_engine = get_engine(instance=instance)
query_result = query_engine.query(sql=fr"purge master logs to '{binlog}';")
Expand Down
9 changes: 9 additions & 0 deletions sql/data_dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def table_list(request):
try:
instance = Instance.objects.get(instance_name=instance_name, db_type='mysql')
query_engine = get_engine(instance=instance)
# escape
db_name = MySQLdb.escape_string(db_name).decode('utf-8')

sql = f"""SELECT
TABLE_NAME,
TABLE_COMMENT
Expand Down Expand Up @@ -62,6 +65,9 @@ def table_info(request):
try:
instance = Instance.objects.get(instance_name=instance_name, db_type='mysql')
query_engine = get_engine(instance=instance)
# escape
db_name = MySQLdb.escape_string(db_name).decode('utf-8')
tb_name = MySQLdb.escape_string(tb_name).decode('utf-8')

sql = f"""SELECT
TABLE_NAME as table_name,
Expand Down Expand Up @@ -141,6 +147,9 @@ def export(request):
"""导出数据字典"""
instance_name = request.GET.get('instance_name', '')
db_name = request.GET.get('db_name', '')
# escape
db_name = MySQLdb.escape_string(db_name).decode('utf-8')

try:
instance = user_instances(request.user, db_type=['mysql']).get(instance_name=instance_name)
query_engine = get_engine(instance=instance)
Expand Down
5 changes: 5 additions & 0 deletions sql/db_diagnostic.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import MySQLdb

import simplejson as json
from django.contrib.auth.decorators import permission_required

Expand Down Expand Up @@ -29,6 +31,9 @@ def process(request):
if AliyunRdsConfig.objects.filter(instance=instance, is_enable=True).exists():
result = aliyun_process_status(request)
else:
# escape
command_type = MySQLdb.escape_string(command_type).decode('utf-8')

if command_type == 'All':
sql = base_sql + ";"
elif command_type == 'Not Sleep':
Expand Down
12 changes: 9 additions & 3 deletions sql/instance.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: UTF-8 -*-
import MySQLdb
import os
import time

Expand Down Expand Up @@ -251,9 +252,9 @@ def instance_resource(request):
"""
instance_id = request.GET.get('instance_id')
instance_name = request.GET.get('instance_name')
db_name = request.GET.get('db_name')
schema_name = request.GET.get('schema_name')
tb_name = request.GET.get('tb_name')
db_name = request.GET.get('db_name', '')
schema_name = request.GET.get('schema_name', '')
tb_name = request.GET.get('tb_name', '')

resource_type = request.GET.get('resource_type')
if instance_id:
Expand All @@ -267,6 +268,11 @@ def instance_resource(request):
result = {'status': 0, 'msg': 'ok', 'data': []}

try:
# escape
db_name = MySQLdb.escape_string(db_name).decode('utf-8')
schema_name = MySQLdb.escape_string(schema_name).decode('utf-8')
tb_name = MySQLdb.escape_string(tb_name).decode('utf-8')

query_engine = get_engine(instance=instance)
if resource_type == 'database':
resource = query_engine.get_all_databases()
Expand Down
17 changes: 17 additions & 0 deletions sql/instance_account.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: UTF-8 -*-
import MySQLdb
import simplejson as json
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.password_validation import validate_password
Expand Down Expand Up @@ -93,6 +94,11 @@ def create(request):
except ValidationError as msg:
return JsonResponse({'status': 1, 'msg': f'{msg}', 'data': []})

# escape
user = MySQLdb.escape_string(user).decode('utf-8')
host = MySQLdb.escape_string(host).decode('utf-8')
password1 = MySQLdb.escape_string(password1).decode('utf-8')

engine = get_engine(instance=instance)
# 在一个事务内执行
hosts = host.split("|")
Expand Down Expand Up @@ -155,6 +161,10 @@ def grant(request):
priv_type = int(request.POST.get('priv_type'))
privs = json.loads(request.POST.get('privs'))
grant_sql = ''

# escape
user_host = MySQLdb.escape_string(user_host).decode('utf-8')

# 全局权限
if priv_type == 0:
global_privs = privs['global_privs']
Expand Down Expand Up @@ -235,6 +245,10 @@ def reset_pwd(request):
except Instance.DoesNotExist:
return JsonResponse({'status': 1, 'msg': '你所在组未关联该实例', 'data': []})

# escape
user_host = MySQLdb.escape_string(user_host).decode('utf-8')
reset_pwd1 = MySQLdb.escape_string(reset_pwd1).decode('utf-8')

# TODO 目前使用系统自带验证,后续实现验证器校验
try:
validate_password(reset_pwd1, user=None, password_validators=None)
Expand Down Expand Up @@ -270,6 +284,9 @@ def delete(request):
except Instance.DoesNotExist:
return JsonResponse({'status': 1, 'msg': '你所在组未关联该实例', 'data': []})

# escape
user_host = MySQLdb.escape_string(user_host).decode('utf-8')

engine = get_engine(instance=instance)
exec_result = engine.execute(db_name='information_schema', sql=f"DROP USER {user_host};")
if exec_result.error:
Expand Down
5 changes: 5 additions & 0 deletions sql/instance_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
@file: instance_database.py
@time: 2019/09/19
"""
import MySQLdb

import simplejson as json
from django.contrib.auth.decorators import permission_required
from django.http import JsonResponse, HttpResponse
Expand Down Expand Up @@ -102,6 +104,9 @@ def create(request):
except Users.DoesNotExist:
return JsonResponse({'status': 1, 'msg': '负责人不存在', 'data': []})

# escape
db_name = MySQLdb.escape_string(db_name).decode('utf-8')

engine = get_engine(instance=instance)
exec_result = engine.execute(db_name='information_schema', sql=f"create database {db_name};")
if exec_result.error:
Expand Down
5 changes: 4 additions & 1 deletion sql/sql_optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
@file: sql_optimize.py
@time: 2019/03/04
"""
import MySQLdb
import re

import simplejson as json
Expand Down Expand Up @@ -148,12 +149,14 @@ def optimize_sqltuning(request):
sqltext = sqlparse.split(sqltext)[0]
if re.match(r"^select|^show|^explain", sqltext, re.I) is None:
result = {'status': 1, 'msg': '只支持查询SQL!', 'data': []}
return HttpResponse(json.dumps(result),content_type='application/json')
return HttpResponse(json.dumps(result), content_type='application/json')
try:
user_instances(request.user).get(instance_name=instance_name)
except Instance.DoesNotExist:
result = {'status': 1, 'msg': '你所在组未关联该实例!', 'data': []}
return HttpResponse(json.dumps(result), content_type='application/json')
# escape
db_name = MySQLdb.escape_string(db_name).decode('utf-8')

sql_tunning = SqlTuning(instance_name=instance_name, db_name=db_name, sqltext=sqltext)
result = {'status': 0, 'msg': 'ok', 'data': {}}
Expand Down

0 comments on commit 73a74e5

Please sign in to comment.