8
0
Files
Skriptentwickung/current/[DD_ECM]-Database/DEX_SQL/[PRDEX_TEST_DYNAMIC_SQL].sql
2026-02-25 16:36:19 +01:00

154 lines
5.4 KiB
Transact-SQL

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- [PRDEX_TEST_DYNAMIC_SQL]
-- =================================================================
-- Central guard for dynamic SQL safety checks
--
-- Returns: INTEGER; 0 = ok; 0 <> nicht ok
-- =================================================================
-- Copyright (c) 2025 by Digital Data GmbH
--
-- Digital Data GmbH • Ludwig-Rinn-Strasse 16 • D-35452 Heuchelheim
-- Tel.: 0641/202360 • E-Mail: info-flow@digitaldata.works
-- =================================================================
-- Creation Date / Author: 24.02.2026 / MK
-- Version Date / Editor: 24.02.2026 / MK
-- Version Number: 1.0.0.0
-- =================================================================
-- History:
-- 24.02.2026 / MK - First Version
CREATE OR ALTER PROCEDURE [dbo].[PRDEX_TEST_DYNAMIC_SQL](
@pQUERY NVARCHAR(MAX),
@pRETURN_STATUS INT,
@pQUERY_NAME NVARCHAR(100) = N'@QUERY'
)
AS
BEGIN TRY
--================================================-- Set session options --===============================================--
SET NOCOUNT ON;
----------------------------------------------------------------------------------------------------------------------------
--=========================================-- declare new vars because of parameter sniffing --===========================--
DECLARE @QUERY NVARCHAR(MAX) = ISNULL(@pQUERY,N''),
@RETURN_STATUS INT = ISNULL(@pRETURN_STATUS,50000),
@QUERY_NAME NVARCHAR(100) = ISNULL(@pQUERY_NAME,N'@QUERY'),
@QUERY_SCAN NVARCHAR(MAX) = N'',
@QUERY_SCAN_NORM NVARCHAR(MAX) = N'',
@COMMENT_START INT = 0,
@COMMENT_END INT = 0,
@SCAN_POS INT = 1,
@TOKEN_START INT = 0,
@TOKEN_END INT = 0,
@QUOTE_START INT = 0,
@QUOTE_END INT = 0,
@TOKEN NVARCHAR(200) = N'',
@HAS_UNRESOLVED_PLACEHOLDER BIT = 0,
@HAS_RESTRICTED_SQL BIT = 0,
@RETURN_ERROR_TEXT NVARCHAR(MAX) = N'';
----------------------------------------------------------------------------------------------------------------------------
--=========================================-- validate query content --====================================================--
SET @QUERY_SCAN = UPPER(@QUERY);
SET @COMMENT_START = CHARINDEX('/*',@QUERY_SCAN);
WHILE (@COMMENT_START > 0)
BEGIN
SET @COMMENT_END = CHARINDEX('*/',@QUERY_SCAN,@COMMENT_START + 2);
IF (@COMMENT_END = 0)
BREAK;
SET @QUERY_SCAN = STUFF(@QUERY_SCAN,@COMMENT_START,(@COMMENT_END - @COMMENT_START + 2),REPLICATE(' ',(@COMMENT_END - @COMMENT_START + 2)));
SET @COMMENT_START = CHARINDEX('/*',@QUERY_SCAN,@COMMENT_START + 1);
END;
SET @COMMENT_START = CHARINDEX('--',@QUERY_SCAN);
WHILE (@COMMENT_START > 0)
BEGIN
SET @COMMENT_END = CHARINDEX(CHAR(10),@QUERY_SCAN,@COMMENT_START + 2);
IF (@COMMENT_END = 0)
SET @COMMENT_END = LEN(@QUERY_SCAN) + 1;
SET @QUERY_SCAN = STUFF(@QUERY_SCAN,@COMMENT_START,(@COMMENT_END - @COMMENT_START),REPLICATE(' ',(@COMMENT_END - @COMMENT_START)));
SET @COMMENT_START = CHARINDEX('--',@QUERY_SCAN,@COMMENT_START + 1);
END;
SET @QUERY_SCAN_NORM = REPLACE(REPLACE(REPLACE(@QUERY_SCAN,CHAR(9),' '),CHAR(10),' '),CHAR(13),' ');
WHILE (CHARINDEX(' ',@QUERY_SCAN_NORM) > 0)
BEGIN
SET @QUERY_SCAN_NORM = REPLACE(@QUERY_SCAN_NORM,' ',' ');
END;
SET @QUOTE_START = CHARINDEX('''',@QUERY_SCAN);
WHILE (@QUOTE_START > 0)
BEGIN
SET @QUOTE_END = CHARINDEX('''',@QUERY_SCAN,@QUOTE_START + 1);
IF (@QUOTE_END = 0)
BREAK;
SET @QUERY_SCAN = STUFF(@QUERY_SCAN,@QUOTE_START,(@QUOTE_END - @QUOTE_START + 1),REPLICATE(' ',(@QUOTE_END - @QUOTE_START + 1)));
SET @QUOTE_START = CHARINDEX('''',@QUERY_SCAN,@QUOTE_START + 1);
END;
WHILE (1 = 1)
BEGIN
SET @TOKEN_START = CHARINDEX('%',@QUERY_SCAN,@SCAN_POS);
IF (@TOKEN_START = 0)
BREAK;
SET @TOKEN_END = CHARINDEX('%',@QUERY_SCAN,@TOKEN_START + 1);
IF (@TOKEN_END = 0)
BREAK;
SET @TOKEN = SUBSTRING(@QUERY_SCAN,@TOKEN_START + 1,@TOKEN_END - @TOKEN_START - 1);
IF (LEN(@TOKEN) > 0)
AND (LEFT(@TOKEN,1) LIKE '[A-Z_]')
AND (@TOKEN NOT LIKE '%[^A-Z0-9_]%')
BEGIN
SET @HAS_UNRESOLVED_PLACEHOLDER = 1;
BREAK;
END;
SET @SCAN_POS = @TOKEN_END + 1;
END;
SET @HAS_RESTRICTED_SQL = CASE WHEN
(CHARINDEX(';--',@QUERY_SCAN_NORM) > 0) OR
(CHARINDEX('; --',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%XP_CMDSHELL%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%SP_OA%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%OPENROWSET%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%OPENDATASOURCE%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%BULK INSERT%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%SP_CONFIGURE%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%RECONFIGURE%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%ALTER SERVER%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%ALTER LOGIN%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%CREATE LOGIN%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%DROP LOGIN%',@QUERY_SCAN_NORM) > 0) OR
(PATINDEX('%DROP DATABASE%',@QUERY_SCAN_NORM) > 0)
THEN 1 ELSE 0 END;
----------------------------------------------------------------------------------------------------------------------------
IF (@HAS_UNRESOLVED_PLACEHOLDER = 1) OR (@HAS_RESTRICTED_SQL = 1) BEGIN
SET @RETURN_ERROR_TEXT = CONCAT('Blocked unsafe query content in ',@QUERY_NAME,'. Detected unresolved placeholder tokens (%TOKEN%) or restricted statements.');
THROW @RETURN_STATUS,@RETURN_ERROR_TEXT,1;
END;
RETURN 0;
END TRY BEGIN CATCH
THROW;
END CATCH;
GO