[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:
parent
e1e5c536e7
commit
e9cdf322c6
2 changed files with 56 additions and 0 deletions
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
28
frappe/tests/test_search.py
Normal file
28
frappe/tests/test_search.py
Normal 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)')
|
||||
Loading…
Add table
Reference in a new issue