Thanks Gregory for this nice peace, good job!
Missed seeing one essential thing though in the injection part and that is a strong coupling to the metadata. If a user can select in any form the objects (table/view/procedure etc.) to use, one should do a firm check for it's existence. A quick sample would be
😎
DECLARE @SCHEMA NVARCHAR(128) = N'dbo';
DECLARE @TABLE NVARCHAR(128) = N'CLIENT';
DECLARE @COLUMN NVARCHAR(128) = N'CLIENT_NAME';
DECLARE @SQL_STR NVARCHAR(MAX) = N''
SELECT
@SQL_STR = N'SELECT ' +
COLUMN_NAME
+ N' FROM ' + TABLE_SCHEMA
+ NCHAR(46) + TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = @COLUMN
AND TABLE_NAME = @TABLE
AND TABLE_SCHEMA = @SCHEMA
--- and so on