pgadmin4/web/regression/feature_tests/file_manager_test.py
2024-01-01 14:13:48 +05:30

193 lines
7.6 KiB
Python

##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2024, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
import os
import sys
import time
import tempfile
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import StaleElementReferenceException, \
TimeoutException
from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.feature_utils.locators import QueryToolLocators
class CheckFileManagerFeatureTest(BaseFeatureTest):
"""Tests to check file manager for XSS."""
scenarios = [
("File manager feature test",
dict())
]
def before(self):
if os.name == 'nt':
self.skipTest("This test is skipped for Windows. As Windows "
"does not allow the '<' and '>' character while "
"specifying the file name.")
self.page.add_server(self.server)
self.wait = WebDriverWait(self.page.driver, 10)
filename = self.server_information['type'] + \
str(self.server_information['server_version'])
self.XSS_FILE = '<img src=x ' + filename + '=alert("1")>.sql'
self.tmpDir = os.path.join(tempfile.gettempdir(), 'pga4_test')
# Create temp directory
if not os.path.exists(self.tmpDir):
os.makedirs(self.tmpDir)
if self.parallel_ui_tests:
xss_file_path = self.XSS_FILE
else:
xss_file_path = os.path.join(self.tmpDir, self.XSS_FILE)
# Remove any previous file
if os.path.isfile(xss_file_path):
os.remove(xss_file_path)
def after(self):
self.page.close_query_tool(False)
self.page.remove_server(self.server)
def runTest(self):
print("Tests to check if File manager is vulnerable to XSS... ",
file=sys.stderr, end="")
self._navigate_to_query_tool()
self.page.fill_codemirror_area_with("SELECT 1;")
self._create_new_file()
self._open_file_manager_and_check_xss_file()
print("OK.", file=sys.stderr)
print("File manager sorting of data", file=sys.stderr)
self._check_file_sorting()
print("OK.", file=sys.stderr)
def _navigate_to_query_tool(self):
self.page.expand_database_node("Server", self.server['name'],
self.server['db_password'],
self.test_db)
self.page.open_query_tool()
def _create_new_file(self):
self.page.find_by_css_selector(QueryToolLocators.btn_save_file) \
.click()
# Set the XSS value in input
WebDriverWait(self.driver, 15).until(EC.presence_of_element_located(
(By.XPATH, QueryToolLocators.change_file_types_dd_xpath)))
# Save the file
if not self.parallel_ui_tests:
self.page.fill_input_by_css_selector(
QueryToolLocators.folder_path_css, '',
key_after_input=Keys.ENTER)
self.page.fill_input_by_css_selector(
QueryToolLocators.folder_path_css,
self.tmpDir, input_keys=True, key_after_input=Keys.ENTER)
self.page.find_by_css_selector(
QueryToolLocators.folder_path_css).send_keys(Keys.ENTER)
input_file_path_ele = \
self.page.find_by_xpath(QueryToolLocators.save_file_path_xpath)
input_file_path_ele.send_keys(self.XSS_FILE)
self.page.click_modal('Save')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
def _open_file_manager_and_check_xss_file(self):
load_file = self.page.find_by_css_selector(
QueryToolLocators.btn_load_file_css)
load_file.click()
WebDriverWait(self.driver, 15).until(EC.presence_of_element_located(
(By.XPATH, QueryToolLocators.change_file_types_dd_xpath)))
# Open the file
if not self.parallel_ui_tests:
self.page.fill_input_by_css_selector(
QueryToolLocators.folder_path_css, '',
key_after_input=Keys.ENTER)
self.page.fill_input_by_css_selector(
QueryToolLocators.folder_path_css,
self.tmpDir, key_after_input=Keys.ENTER)
self.page.find_by_css_selector(
QueryToolLocators.folder_path_css).send_keys(Keys.ENTER)
time.sleep(2)
self.page.fill_input_by_css_selector(
QueryToolLocators.search_file_edit_box_css, self.XSS_FILE,
input_keys=True)
self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.select_file_content_css)))
table = self.page.driver.find_element(
By.CSS_SELECTOR, QueryToolLocators.select_file_content_css)
retry_count = 0
while retry_count < 5:
try:
contents = table.get_attribute('innerHTML')
break
except (StaleElementReferenceException, TimeoutException):
retry_count += 1
self.page.click_modal('Cancel')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
filename = self.server_information['type'] + \
str(self.server_information['server_version'])
self._check_escaped_characters(
contents,
'&lt;img src=x ' + filename +
'=alert("1")&gt;.sql', 'File manager'
)
def _check_escaped_characters(self, source_code, string_to_find, source):
# For XSS we need to search against element's html code
assert source_code.find(
string_to_find
) != -1, "{0} might be vulnerable to XSS, source code is: {1}".format(
source, source_code)
def _check_file_sorting(self):
load_file = self.page.find_by_css_selector(
QueryToolLocators.btn_load_file_css)
load_file.click()
WebDriverWait(self.driver, 15).until(EC.presence_of_element_located(
(By.XPATH, QueryToolLocators.change_file_types_dd_xpath)))
# Intermittently facing issue on first click it is not successful
# so tried couple of times.
success = self.page.retry_click(
(By.CSS_SELECTOR,
"div [role='grid'] div[role='columnheader'][aria-colindex='1']"),
(By.CSS_SELECTOR,
"div [role='grid'] div[role='columnheader']"
"[aria-colindex='1'][aria-sort='ascending']"))
if not success:
raise RuntimeError("Unable to sort in ascending order while "
"clicked on 'Name' column")
# Added time.sleep so that the element to be clicked.
time.sleep(0.05)
# Click and Check for sort Descending
# Intermittently facing issue on first click it is not successful
# so tried couple of times.
success = self.page.retry_click(
(By.CSS_SELECTOR,
"div [role='grid'] div[role='columnheader'][aria-colindex='1']"),
(By.CSS_SELECTOR,
"div [role='grid'] div[role='columnheader']"
"[aria-colindex='1'][aria-sort='descending']"))
if not success:
raise RuntimeError("Unable to sort in descending order while "
"clicked on 'Name' column")
self.page.click_modal('Cancel')