Merge pull request #19277 from resilient-tech/refactor-sanitize_searchfield

fix: use stricter regex for `sanitize_searchfield`
This commit is contained in:
Ankush Menat 2022-12-15 17:47:07 +05:30 committed by GitHub
commit c0e5408659
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 32 deletions

View file

@ -7,45 +7,18 @@ import re
import frappe
from frappe import _, is_whitelisted
from frappe.database.schema import SPECIAL_CHAR_PATTERN
from frappe.permissions import has_permission
from frappe.utils import cint, cstr, unique
def sanitize_searchfield(searchfield):
blacklisted_keywords = ["select", "delete", "drop", "update", "case", "and", "or", "like"]
if not searchfield:
return
def _raise_exception(searchfield):
if SPECIAL_CHAR_PATTERN.search(searchfield):
frappe.throw(_("Invalid Search Field {0}").format(searchfield), frappe.DataError)
if len(searchfield) == 1:
# do not allow special characters to pass as searchfields
regex = re.compile(r'^.*[=;*,\'"$\-+%#@()_].*')
if regex.match(searchfield):
_raise_exception(searchfield)
if len(searchfield) >= 3:
# to avoid 1=1
if "=" in searchfield:
_raise_exception(searchfield)
# in mysql -- is used for commenting the query
elif " --" in searchfield:
_raise_exception(searchfield)
# to avoid and, or and like
elif any(f" {keyword} " in searchfield.split() for keyword in blacklisted_keywords):
_raise_exception(searchfield)
# to avoid select, delete, drop, update and case
elif any(keyword in searchfield.split() for keyword in blacklisted_keywords):
_raise_exception(searchfield)
else:
regex = re.compile(r'^.*[=;*,\'"$\-+%#@()].*')
if any(regex.match(f) for f in searchfield.split()):
_raise_exception(searchfield)
# this is called by the Link Field
@frappe.whitelist()

View file

@ -1,10 +1,16 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
import re
import frappe
from frappe.app import make_form_dict
from frappe.desk.search import get_names_for_mentions, search_link, search_widget
from frappe.desk.search import (
get_names_for_mentions,
sanitize_searchfield,
search_link,
search_widget,
)
from frappe.tests.utils import FrappeTestCase
from frappe.utils import set_request
from frappe.website.serve import get_response
@ -179,6 +185,17 @@ class TestSearch(FrappeTestCase):
search_link("User", "user@random", searchfield="name")
self.assertListEqual(frappe.response["results"], [])
def test_sanitize_searchfield(self):
for searchfield in ("1=1", "name or (select * from tabSessions)", ";", "`tabSessions`"):
self.assertRaisesRegex(
frappe.DataError,
re.compile(r"^(Invalid Search Field .*)$"),
sanitize_searchfield,
searchfield,
)
sanitize_searchfield("name")
@frappe.validate_and_sanitize_search_inputs
def get_data(doctype, txt, searchfield, start, page_len, filters):