[security][fix] Sanitize search fields to avoid sql injection (#5713)

* [security][fix] Sanitize search fields to avoid sql injection

* Test Cases for Sanitizer

* Test Cases fix

* [fix] test case
This commit is contained in:
Saurabh 2018-06-25 11:23:32 +05:30 committed by Rushabh Mehta
parent e1e5c536e7
commit e9cdf322c6
2 changed files with 56 additions and 0 deletions

View file

@ -8,6 +8,31 @@ from frappe.utils import cstr, unique
from frappe import _
from six import string_types
def sanitize_searchfield(searchfield):
blacklisted_keywords = ['select', 'delete', 'drop', 'update', 'case', 'and', 'or', 'like']
def _raise_exception():
frappe.throw(_('Invalid Search Field'), frappe.DataError)
if len(searchfield) >= 3:
# to avoid 1=1
if '=' in searchfield:
_raise_exception()
# in mysql -- is used for commenting the query
elif ' --' in searchfield:
_raise_exception()
# to avoid and, or and like
elif any(' {0} '.format(keyword) in searchfield.split() for keyword in blacklisted_keywords):
_raise_exception()
# to avoid select, delete, drop, update and case
elif any(keyword in searchfield.split() for keyword in blacklisted_keywords):
_raise_exception()
# this is called by the Link Field
@frappe.whitelist()
def search_link(doctype, txt, query=None, filters=None, page_length=20, searchfield=None):
@ -24,6 +49,9 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0,
meta = frappe.get_meta(doctype)
if searchfield:
sanitize_searchfield(searchfield)
if not searchfield:
searchfield = "name"

View file

@ -0,0 +1,28 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals
import unittest
import frappe
from frappe.desk.search import search_link
class TestSearch(unittest.TestCase):
def test_search_field_sanitizer(self):
# pass
search_link('DocType', 'User', query=None, filters=None, page_length=20, searchfield='name')
result = frappe.response['results'][0]
self.assertTrue('User' in result['value'])
#raise exception on injection
self.assertRaises(frappe.DataError,
search_link, 'DocType', 'Customer', query=None, filters=None,
page_length=20, searchfield='1=1')
self.assertRaises(frappe.DataError,
search_link, 'DocType', 'Customer', query=None, filters=None,
page_length=20, searchfield='select * from tabSessions) --')
self.assertRaises(frappe.DataError,
search_link, 'DocType', 'Customer', query=None, filters=None,
page_length=20, searchfield='name or (select * from tabSessions)')