I use the mysql-connector-python driver for executing database operations. Recently, I came across stored procedures in MySQL and decided to migrate some of my APIs from utilizing cursor.execute() to cursor.callproc(proc_name, args=()). This transition has proven successful, and everything works seamlessly. However, I'm uncertain about the vulnerability of these stored procedures to SQL injection.
To assess this, I created a test stored procedure and examined its susceptibility to SQL injection payloads.
Stored Procedure:
DELIMITER //
CREATE PROCEDURE TestProcedure(IN arg_test VARCHAR(150))
BEGIN
IF EXISTS (SELECT 1 FROM Random_Table WHERE test = arg_test) THEN
SELECT 'success' AS message;
ELSE
SELECT 'failed' AS message;
END IF;
END //
DELIMITER ;
Payloads:
' or 1=1 --" or 1=1 --
Surprisingly, none of these payloads yielded any successful results. Seeking further assurance, I consulted one of the database administrators in the company. Although he expressed uncertainty, he suggested that these stored procedures function similarly to prepared statements. This aligns with my observation that the cursor.callproc() method accepts user inputs as arguments via the args parameter, resembling prepared statements.
If this interpretation is accurate, it implies that using the cursor.callproc() method ensures a secure backend, free from SQL injection concerns. Despite these positive indications, I would like to seek additional confirmation here to guarantee the safety of this approach.
Like it often happens, the problem is in the terminology. And it creates a lot of trouble (and vulnerabilities). A programmer should be always strict in their definitions.
What you are talking about here is using stored procedure's parameter. Such a parameter is a special case related to stored procedures, and very similar in nature to SQL variables.
In this case your database doesn't add the contents of
arg_testinto the SQL body (as it would have been in python if you did something like+ arg_test +) and then evaluate the resulting SQL. On the contrary, is usesarg_testas though it's a variable (in this sense, it's indeed similar to prepared statements, but technically it's entirely different matters).While speaking of stored procedures, they are irrelevant to injections. By itself, just using a procedure doesn't guarantee anything. One can write a procedure which is immune to injection, and write another which is prone to injection. Just like any other code.
But as long as you are just using a parameter passed to the procedure - it's safe.