3

How can I construct a query based on parameters I receive? I want to add to the end of the query.

I tried something like this but it didn't work:

DELIMITER $$
CREATE PROCEDURE `get_users`(IN sortstring TEXT)
BEGIN
PREPARE statement FROM
 "SELECT username, password FROM users ?";
SET @param = sortstring;
EXECUTE statement USING @param;
END$$

And I would pass to sortstring something like:

ORDER BY username DESC

Can I do this simpler by using concat or something?

Shef
  • 44,808
  • 15
  • 79
  • 90
monokh
  • 1,970
  • 3
  • 22
  • 31

1 Answers1

2

You need to deconstruct the sortstring and check all its parts against a whitelist of allowed terms.

See the following pseudo code. I haven't fully tested it, but lets say it's the idea that counts.

DELIMITER $$

CREATE PROCEDURE `get_users`(IN sortstring TEXT)
BEGIN
  //check sortstring against a whitelist of allowed sortstrings
  DECLARE sortpart VARCHAR(255);
  DECLARE done BOOLEAN DEFAULT false;
  DECLARE allok BOOLEAN DEFAULT true; 
  DECLARE i INTEGER DEFAULT 1;

  WHILE ((NOT done) AND allOK) DO
    SET sortpart = SUBSTRING_INDEX(sortstring,',',i);
    SET i = i + 1;
    SET done = (sortpart IS NULL);
    IF NOT DONE THEN
      SELECT 1 INTO allok WHERE EXISTS 
        (SELECT 1 FROM whitelist 
         WHERE allowed_sort_claused = sortpart AND tablename = 'users');
    END IF
  END WHILE;
  IF allOK THEN     
    PREPARE statement FROM 
      CONCAT('SELECT username, passhashwithsalt FROM users ',sortstring);
    EXECUTE statement;
    DEALLOCATE PREPARE statement;
  ELSE SELECT 'error' as username, 'error' as passhashwithsalt;
  END IF; 

END$$

See: How to prevent SQL injection with dynamic tablenames?

The error in your code
You cannot use columnnames or SQL-keywords as parameters. You can only use values as parameters. For that reason your query will never pass prepare.
The ? in SELECT x FROM t1 ? wil just be replaced by SELECT x FROM t1 'ORDER BY field1, field2' Which makes no sense.

Community
  • 1
  • 1
Johan
  • 74,508
  • 24
  • 191
  • 319