PHP - Add new column with placeholder MS SQL preventing SQL Injection
I am working on a PHP application based on MS SQL that, among other things, can add a column to a table, either bit, int or varchar. My current code is similar to this:
$sql = "ALTER TABLE myTable ADD ? ".$type;
$values = array($columnname);
if($type == "varchar")
$sql = $sql."(".$length.")";
$sql = $sql.";";
sqlsrv_query($conn, $sql, $values);
However, I only get back an error that tells me there's an incorrect syntax near '@P1'. I thought about inserting the column name into the string directly, but I'm afraid of SQL injection as it is a text input. I'm not as worried about it for the type and the length as those are a select and a number input.
I am hoping one of you can give me some advice on how to add the column without exposing myself to SQL injection. Thank you in advance!
(As this question has been marked a 'possible duplicate' I'd like to clarify that I'm specifically asking about adding a new column without exposing myself to SQL injection, not just inserting values into a table. I hope I made this clear.)
php sql sql-server sql-injection
add a comment |
I am working on a PHP application based on MS SQL that, among other things, can add a column to a table, either bit, int or varchar. My current code is similar to this:
$sql = "ALTER TABLE myTable ADD ? ".$type;
$values = array($columnname);
if($type == "varchar")
$sql = $sql."(".$length.")";
$sql = $sql.";";
sqlsrv_query($conn, $sql, $values);
However, I only get back an error that tells me there's an incorrect syntax near '@P1'. I thought about inserting the column name into the string directly, but I'm afraid of SQL injection as it is a text input. I'm not as worried about it for the type and the length as those are a select and a number input.
I am hoping one of you can give me some advice on how to add the column without exposing myself to SQL injection. Thank you in advance!
(As this question has been marked a 'possible duplicate' I'd like to clarify that I'm specifically asking about adding a new column without exposing myself to SQL injection, not just inserting values into a table. I hope I made this clear.)
php sql sql-server sql-injection
Possible duplicate of How can I prevent SQL injection in PHP?
– Sanu0786
Nov 23 '18 at 7:17
You probably cannot use parameters to specify identifier names (table names, column names, etc).
– Salman A
Nov 23 '18 at 7:23
@SalmanA Yes, I suspected that as well, but I'm not sure how else to do it without exposing myself to SQL injection.
– pttg
Nov 23 '18 at 7:25
add a comment |
I am working on a PHP application based on MS SQL that, among other things, can add a column to a table, either bit, int or varchar. My current code is similar to this:
$sql = "ALTER TABLE myTable ADD ? ".$type;
$values = array($columnname);
if($type == "varchar")
$sql = $sql."(".$length.")";
$sql = $sql.";";
sqlsrv_query($conn, $sql, $values);
However, I only get back an error that tells me there's an incorrect syntax near '@P1'. I thought about inserting the column name into the string directly, but I'm afraid of SQL injection as it is a text input. I'm not as worried about it for the type and the length as those are a select and a number input.
I am hoping one of you can give me some advice on how to add the column without exposing myself to SQL injection. Thank you in advance!
(As this question has been marked a 'possible duplicate' I'd like to clarify that I'm specifically asking about adding a new column without exposing myself to SQL injection, not just inserting values into a table. I hope I made this clear.)
php sql sql-server sql-injection
I am working on a PHP application based on MS SQL that, among other things, can add a column to a table, either bit, int or varchar. My current code is similar to this:
$sql = "ALTER TABLE myTable ADD ? ".$type;
$values = array($columnname);
if($type == "varchar")
$sql = $sql."(".$length.")";
$sql = $sql.";";
sqlsrv_query($conn, $sql, $values);
However, I only get back an error that tells me there's an incorrect syntax near '@P1'. I thought about inserting the column name into the string directly, but I'm afraid of SQL injection as it is a text input. I'm not as worried about it for the type and the length as those are a select and a number input.
I am hoping one of you can give me some advice on how to add the column without exposing myself to SQL injection. Thank you in advance!
(As this question has been marked a 'possible duplicate' I'd like to clarify that I'm specifically asking about adding a new column without exposing myself to SQL injection, not just inserting values into a table. I hope I made this clear.)
php sql sql-server sql-injection
php sql sql-server sql-injection
edited Nov 23 '18 at 7:24
asked Nov 23 '18 at 7:17
pttg
64
64
Possible duplicate of How can I prevent SQL injection in PHP?
– Sanu0786
Nov 23 '18 at 7:17
You probably cannot use parameters to specify identifier names (table names, column names, etc).
– Salman A
Nov 23 '18 at 7:23
@SalmanA Yes, I suspected that as well, but I'm not sure how else to do it without exposing myself to SQL injection.
– pttg
Nov 23 '18 at 7:25
add a comment |
Possible duplicate of How can I prevent SQL injection in PHP?
– Sanu0786
Nov 23 '18 at 7:17
You probably cannot use parameters to specify identifier names (table names, column names, etc).
– Salman A
Nov 23 '18 at 7:23
@SalmanA Yes, I suspected that as well, but I'm not sure how else to do it without exposing myself to SQL injection.
– pttg
Nov 23 '18 at 7:25
Possible duplicate of How can I prevent SQL injection in PHP?
– Sanu0786
Nov 23 '18 at 7:17
Possible duplicate of How can I prevent SQL injection in PHP?
– Sanu0786
Nov 23 '18 at 7:17
You probably cannot use parameters to specify identifier names (table names, column names, etc).
– Salman A
Nov 23 '18 at 7:23
You probably cannot use parameters to specify identifier names (table names, column names, etc).
– Salman A
Nov 23 '18 at 7:23
@SalmanA Yes, I suspected that as well, but I'm not sure how else to do it without exposing myself to SQL injection.
– pttg
Nov 23 '18 at 7:25
@SalmanA Yes, I suspected that as well, but I'm not sure how else to do it without exposing myself to SQL injection.
– pttg
Nov 23 '18 at 7:25
add a comment |
1 Answer
1
active
oldest
votes
As comments above have stated, you can use a parameter placeholder only to substitute for a scalar value — that is, where you would otherwise use a single quoted string, quoted date/time, or numeric literal.
Parameters don't work for identifiers like table names or column names, nor SQL keywords, nor SQL expressions, nor lists of values (you would have to use one placeholder for each scalar value in a list).
For cases where you want to make a column name or SQL keywords dynamic as you are trying to do, you will be vulnerable to SQL injection unless you make sure to restrict the dynamic part to unharmful strings.
For example, you can do this with delimiting and escaping.
$columnname = str_replace("]", "]]", $columnname);
$sql = "ALTER TABLE myTable ADD [$columnname] $type";
MS SQL Server uses square brackets to delimit an identifier that may contain special characters. The str_replace() is just in case the column name itself contains square brackets. Read https://sqlsunday.com/2014/09/21/identifiers-in-tsql/ for more explanation.
What about $type? How can we make sure that's safe? The other technique is whitelisting. To make $type safe, you would need to check it against a list of allowed values.
switch ($type) {
case "int":
// OK, nothing to change
break;
case "varchar":
$type = "varchar($length)"
break;
// ...add cases for other allowed types...
default:
die("Unrecognized type: $type");
}
You can either die with an error in the default
clause, or you can set $type
to a reasonable default. Depends on how you want to handle it.
You might ask, Why so much code? Why can't this be simpler?
Because you require the software to do something that is dynamic. You're trying to make code do the right thing no matter what some user inputs. If you didn't need to support user input, you could make the column name and type fixed, and then it would be simple.
1
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53442175%2fphp-add-new-column-with-placeholder-ms-sql-preventing-sql-injection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
As comments above have stated, you can use a parameter placeholder only to substitute for a scalar value — that is, where you would otherwise use a single quoted string, quoted date/time, or numeric literal.
Parameters don't work for identifiers like table names or column names, nor SQL keywords, nor SQL expressions, nor lists of values (you would have to use one placeholder for each scalar value in a list).
For cases where you want to make a column name or SQL keywords dynamic as you are trying to do, you will be vulnerable to SQL injection unless you make sure to restrict the dynamic part to unharmful strings.
For example, you can do this with delimiting and escaping.
$columnname = str_replace("]", "]]", $columnname);
$sql = "ALTER TABLE myTable ADD [$columnname] $type";
MS SQL Server uses square brackets to delimit an identifier that may contain special characters. The str_replace() is just in case the column name itself contains square brackets. Read https://sqlsunday.com/2014/09/21/identifiers-in-tsql/ for more explanation.
What about $type? How can we make sure that's safe? The other technique is whitelisting. To make $type safe, you would need to check it against a list of allowed values.
switch ($type) {
case "int":
// OK, nothing to change
break;
case "varchar":
$type = "varchar($length)"
break;
// ...add cases for other allowed types...
default:
die("Unrecognized type: $type");
}
You can either die with an error in the default
clause, or you can set $type
to a reasonable default. Depends on how you want to handle it.
You might ask, Why so much code? Why can't this be simpler?
Because you require the software to do something that is dynamic. You're trying to make code do the right thing no matter what some user inputs. If you didn't need to support user input, you could make the column name and type fixed, and then it would be simple.
1
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
add a comment |
As comments above have stated, you can use a parameter placeholder only to substitute for a scalar value — that is, where you would otherwise use a single quoted string, quoted date/time, or numeric literal.
Parameters don't work for identifiers like table names or column names, nor SQL keywords, nor SQL expressions, nor lists of values (you would have to use one placeholder for each scalar value in a list).
For cases where you want to make a column name or SQL keywords dynamic as you are trying to do, you will be vulnerable to SQL injection unless you make sure to restrict the dynamic part to unharmful strings.
For example, you can do this with delimiting and escaping.
$columnname = str_replace("]", "]]", $columnname);
$sql = "ALTER TABLE myTable ADD [$columnname] $type";
MS SQL Server uses square brackets to delimit an identifier that may contain special characters. The str_replace() is just in case the column name itself contains square brackets. Read https://sqlsunday.com/2014/09/21/identifiers-in-tsql/ for more explanation.
What about $type? How can we make sure that's safe? The other technique is whitelisting. To make $type safe, you would need to check it against a list of allowed values.
switch ($type) {
case "int":
// OK, nothing to change
break;
case "varchar":
$type = "varchar($length)"
break;
// ...add cases for other allowed types...
default:
die("Unrecognized type: $type");
}
You can either die with an error in the default
clause, or you can set $type
to a reasonable default. Depends on how you want to handle it.
You might ask, Why so much code? Why can't this be simpler?
Because you require the software to do something that is dynamic. You're trying to make code do the right thing no matter what some user inputs. If you didn't need to support user input, you could make the column name and type fixed, and then it would be simple.
1
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
add a comment |
As comments above have stated, you can use a parameter placeholder only to substitute for a scalar value — that is, where you would otherwise use a single quoted string, quoted date/time, or numeric literal.
Parameters don't work for identifiers like table names or column names, nor SQL keywords, nor SQL expressions, nor lists of values (you would have to use one placeholder for each scalar value in a list).
For cases where you want to make a column name or SQL keywords dynamic as you are trying to do, you will be vulnerable to SQL injection unless you make sure to restrict the dynamic part to unharmful strings.
For example, you can do this with delimiting and escaping.
$columnname = str_replace("]", "]]", $columnname);
$sql = "ALTER TABLE myTable ADD [$columnname] $type";
MS SQL Server uses square brackets to delimit an identifier that may contain special characters. The str_replace() is just in case the column name itself contains square brackets. Read https://sqlsunday.com/2014/09/21/identifiers-in-tsql/ for more explanation.
What about $type? How can we make sure that's safe? The other technique is whitelisting. To make $type safe, you would need to check it against a list of allowed values.
switch ($type) {
case "int":
// OK, nothing to change
break;
case "varchar":
$type = "varchar($length)"
break;
// ...add cases for other allowed types...
default:
die("Unrecognized type: $type");
}
You can either die with an error in the default
clause, or you can set $type
to a reasonable default. Depends on how you want to handle it.
You might ask, Why so much code? Why can't this be simpler?
Because you require the software to do something that is dynamic. You're trying to make code do the right thing no matter what some user inputs. If you didn't need to support user input, you could make the column name and type fixed, and then it would be simple.
As comments above have stated, you can use a parameter placeholder only to substitute for a scalar value — that is, where you would otherwise use a single quoted string, quoted date/time, or numeric literal.
Parameters don't work for identifiers like table names or column names, nor SQL keywords, nor SQL expressions, nor lists of values (you would have to use one placeholder for each scalar value in a list).
For cases where you want to make a column name or SQL keywords dynamic as you are trying to do, you will be vulnerable to SQL injection unless you make sure to restrict the dynamic part to unharmful strings.
For example, you can do this with delimiting and escaping.
$columnname = str_replace("]", "]]", $columnname);
$sql = "ALTER TABLE myTable ADD [$columnname] $type";
MS SQL Server uses square brackets to delimit an identifier that may contain special characters. The str_replace() is just in case the column name itself contains square brackets. Read https://sqlsunday.com/2014/09/21/identifiers-in-tsql/ for more explanation.
What about $type? How can we make sure that's safe? The other technique is whitelisting. To make $type safe, you would need to check it against a list of allowed values.
switch ($type) {
case "int":
// OK, nothing to change
break;
case "varchar":
$type = "varchar($length)"
break;
// ...add cases for other allowed types...
default:
die("Unrecognized type: $type");
}
You can either die with an error in the default
clause, or you can set $type
to a reasonable default. Depends on how you want to handle it.
You might ask, Why so much code? Why can't this be simpler?
Because you require the software to do something that is dynamic. You're trying to make code do the right thing no matter what some user inputs. If you didn't need to support user input, you could make the column name and type fixed, and then it would be simple.
answered Nov 24 '18 at 17:35
Bill Karwin
372k61510667
372k61510667
1
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
add a comment |
1
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
1
1
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
Well stated. And I would add to this for OP - perhaps the issue is the design of a system that allows (encourages?) a user to alter the schema. That ability alone requires permissions that users are not typically given.
– SMor
Nov 25 '18 at 13:19
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53442175%2fphp-add-new-column-with-placeholder-ms-sql-preventing-sql-injection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Possible duplicate of How can I prevent SQL injection in PHP?
– Sanu0786
Nov 23 '18 at 7:17
You probably cannot use parameters to specify identifier names (table names, column names, etc).
– Salman A
Nov 23 '18 at 7:23
@SalmanA Yes, I suspected that as well, but I'm not sure how else to do it without exposing myself to SQL injection.
– pttg
Nov 23 '18 at 7:25