可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I know it's a simple question, but in everything I've read, I've never seen this spelled out specifically.
If you do a query on a page, do you need to worry about SQL injection attacks? Or is it only a problem when you ask the user for input?
Thanks!
回答1:
You don't have to have user input to suffer a SQL injection attack.
Let's say you have a product page that is called using a URL such as this:
product.aspx?ID=123
And in your code you have a query constructed such as this:
string sql = "SELECT * FROM Products WHERE ID = " + Request.Querystring["ID"];
Someone could call your page with this url:
product.aspx?ID=123;DROP Table Students;
And bam, you've just been had.
In addition to ANYTHING that can be passed in via a user, querystring, post, cookie, browser variable, etc. I think it is just good practice to always use parameters, even if you have the literals in your code. For example:
if(SomeCondition)
{
sql = "Select * from myTable where someCol = 'foo'";
}
else
{
sql = "Select * from myTable where someCol = 'bar'";
}
this may be injection safe, but your RDBMS will cache them as two different queries.
if you modiy it to this:
sql = "Select * from myTable where someCol = @myParam";
if(SomeCondition)
{
myCommand.Parameters.Add("@myParam").value = "foo";
}
else
{
myCommand.Parameters.Add("@myParam").value = "bar";
}
You achieve the same result but the RDBMS will only cache it as one query, substituting the parameter at runtime. I use it as a rule of thumb to ALWAYS use parameterized queries, just to keep things consistent, not to mention a slight cache improvement.
回答2:
SQL injection is caused by unsanitized data. You should always always always sanitize data going into a database. Not just for SQL injection, but also for making your app just work.
For example, some systems won't use my name because it has a ' character in it, and their database is not sanitized. I did not enter my name, my name was taken from another database. Doesn't matter -- the data should be sanitized.
回答3:
SQL Injection snippets can also come in from the QueryString (aka "URL arguments") passed in with the GET method instead.
As hinted by Billy O'Neal [single quote intended ;-) ], any piece of data that is not intrinsic to the program (or to its very trusted back-end), should be "sanitized". The Sanitizing term seems to imply to be a sophisticated process, but in effect it typically means little more than:
[may vary with your specific SQL server make]
- remove (or escape) single quotes characters embedded within a string
- watch from strings exceeded the length of the underlying SQL column (in particular if such length is readily long)
A possible reason for the idea that HTTP Forms would be the only source of SQL injection snippets is that a -valid- recommendation is to ensure that one gets the user-supplied submitted text from the Request's form exclusively. Several Web Application frameworks expose the HTTP request as an object which exposes, by default, all key-values pairs from either the QueryString, from a Form, or even from cookies, accessible as from a single hash. While this can be practical for applications that sometimes get the info from a form an sometimes from the querystring, this can facilitate the work of would-be-injectors, because it is easier to craft a URL than a Form. (But with the proper tool, one can also fake a POST request as well...)
回答4:
No, there are several other cases. For example, you may have some of the variables as a querystring passed into a php page. The 'user' could modify that string to include some dodgy scripting.
http://en.wikipedia.org/wiki/SQL_injection includes a large section on the types of vulnerabilities and how to combat them effectively.
回答5:
To summarize - any type of input from the user that is used in SQL queries is a potential target of sql injection
回答6:
Also consider preventing against cross-site-scripting ("XSS").
回答7:
SQL Injections is possible if you use any kind of data that comes from the browser. It could be form data, querystring data, cookie values, or even data from the request header.
The obvious and easy ways in is the form data and querystring data, but anything that comes from the browser could be spoofed.
回答8:
Anything that the code takes as input from the HTTP request can be a SQL injection vector:
- POST/PUT content
- GET URL parameters
- Cookies
At a higher level these show up as $_REQUEST or Page.Request values, session variable, it all depends on a miriad of factors. but ultimately, is not just POST forms. Although probably the most prvalent vector is form POST content and GET URL variables.
回答9:
When the user can modify the values of the parameters of a query, then it can become a threat.
回答10:
You need to worry about cross site scripting (XSS) attacks in this case if the data you are displaying on the page came from user submitted data.
ESCAPE INPUT, FILTER OUTPUT
回答11:
As I concern you should never trust this variables: $_POST, $_GET, $_REQUEST, $_COOKIE even $_SERVER can contain malicious code. So ALWAYS make sure that inserted data match your expectation.
For example as an extra paranoid measure on validation email address you can encrypt email address with md5 like this:
"SELECT username FROM users WHERE MD5(email)='" . md5($_POST['email']) . "' AND active=1"
回答12:
As a general rule parameterized queries should always be used.
- It prevents malicious user input from being executed against your database (SQL injection attacks). [You should do user input validation as well to ensure that malicious code isn't rendered on the page and that JavaScript can be run against your server.]
- It enables you to re-use your queries.
- You can precompile your queries.
- It organizes your input and makes it more readable. You might want to use the same parameter in more than one location.
- It has better support for different data type such as dates, strings and the like. You won't run into problems with weird characters when you use parameterized queries.
In my use case I always generate parameter based queries. I have a wrapper that will always compile them so that if a second query gets executed in the same request path, it will run that much faster on the same connection. This takes a fair bit of work to setup, but is worth the performance gain in any medium to enterprise level system.
回答13:
I agree that parameterisation is the best approach.
As an alternative (which might be easier to retro fit into your code, at least initially) doubling the single quotes in a string will prevent SQL Injection.
To take Neil N's example:
sql = "Select * From Products Where ID = " + Request.Querystring["ID"];
wrap the variable in a function that doubles the quotes, and wrap the varible with single quotes too.
sql = "Select * From Products Where ID = "
+ fnSQLSafeParam(Request.Querystring["ID"]);
The function would be something like (VBscript example):
Function fnSQLSafeParam(ByVal strStr)
If IsNull(strStr) or IsEmpty(strStr) then strStr = ""
fnSQLSafeParam = "'" & replace(Trim(CStr(strStr)), "'", "''") & "'"
End Function