输入这个查询,显示了用户表中存在的USERNAME和PASSWORD,像下面显示的 FIGURE .3的示
Figure 3 Querying the Users Table
SQL注入攻击还可以被用来改变数据或损坏数据库。SQL注入的黑客可能输入下面的txtFilter 去改变第一个产品的价格从18美元到0.01美元,并且在别人察觉到他的行为之前,迅速的购买这些产品。
'; UPDATE Products SET UnitPrice = 0.01 WHERE ProductId = 1--
黑客能够得成是因为SQL SERVER充许你把多个SQL语句通过一个分号或空格连成一个。在这个例子中DataGrid什么也不显示,但是更新语句却正常的被执行了。利用相同的技术,可能被用来执行一条删除表的语句,或是执行一条系统存储扩展,用来创建一个用户,并加入系统管理员权限组中。这些黑客们都可能用例2中的BadProductList.aspx页面。
别给黑客机会
我们要了解SQL攻击不仅仅是局限在SQL SERVER上面,这一点很重要。其它的数据库,包括Oracle, MySQL, DB2, Sybase等都容易受到这种注入攻击。SQL注入攻击能够得逞是因为SQL语言包含强大的灵活性和有它的的一些特征: 连字符(--),在SQL中表示注释 能够把多语句拼起来执行 能够从标准配置的系统表中进行进数据查询
通常,数据库都支持一些更为有力的SQL查询语言,所以SQL SERVER数据库数据器经常被攻击,没必要大惊小怪的。 SQL 注入攻击不仅是发生在asp.net程序中,其它的如ASP ,JAVA,JSP和PHP中照样很容易引起攻击。实际上注入攻击。实际上,桌面程序也会受到SQL注入攻击,这一点上它并不见得能好到哪里去。举例,我已经在下载文件中打包了一个WINDOWS FORMS应用程序,名字为SQLINJECTWINFORM,它同样可以被SQL注入(在文章顶头的下载中可以下载到) 虽然可以很容易的指出一个或两个关键的SQL注入防范措施,可是最好我们还是采取分层的方式来解决。如果即便是你的一种方法因为漏洞被黑客绕过了,但是它还是守保护的。建议的总结层,如图4。
|
用最小的权限执行
使用参数化SQL,大大降低了黑客注入你代码的能力,在Badlogin.aspx 和 BadProductList.aspx中有一个不好的做法就是连接字符串中使用了SA帐户。下面是连接字符串,你可以在WEB.CONFIG文件中找到它:
<add key="cnxNWindBad" value="server=localhost;uid=sa;pwd=;database=northwind;" /> |
此帐户运行于系统管理员的角色,这意思着它将会允许胡作非为,如创建一个登录,删除删除库这些操作都是小菜一碟。我只是想说明,数据库应用程序中用SA的方法是一个糟透了的做法。有一个更好的方法就是创建一个受限的用户来代替SA用户。GoodLogin.aspx中使用了下面的连接字符串:
<add key="cnxNWindGood" value="server=localhost;uid=NWindReader;pwd=utbbeesozg4d; database=northwind;" /> |
NWindReader帐户运行于db_datareader角色之下,这个角色被限定于只能读取数据库中的表。BetterLogin.aspx利用存储过程和一个登录改善了效率,WebLimitedUser只拥有执行该存储过程的权限,而无底层表的权利。
保存密码的安全
在表3所示的注入攻击中,导致USERS表中的用户名和密码显示出来。这类表经常被用在窗体身份验证中,并且许多程序中,用户名和密码以明文保存。一个更好的方法是把它们进行加密或哈希存储在数据库中。哈希密码比起加密密码更安全,因为他们不能被解密。你可以通过添加一个salt(盐?)(一个加密随机值)给哈希来强化一个哈希密码
BestLogin.aspx包含了把用户输入和存储在SecureUsers表(见表7)中被盐化(salted)哈希版本密码相比较的代码。哈希密的另一个是AddSecureUser.aspx页面。这个页面是用来得到被盐化的密码,把它们存到secureUsers表中。
表7 BestLogin.aspx.cs
private void cmdLogin_Click(object sender, System.EventArgs e) {
try {
// Grab the encrypted connection string and decrypt it
string strCnx = SecureConnection.GetCnxString("cnxNWindBest");
// Establish connection to database
using (SqlConnection cnx = new SqlConnection(strCnx))
{
SqlParameter prm;
cnx.Open();
// Execute sproc to retrieved hashed password for this user
string strHashedDbPwd;
SqlCommand cmd = new SqlCommand("procGetHashedPassword", cnx);
cmd.CommandType = CommandType.StoredProcedure;
prm = new SqlParameter("@username", SqlDbType.VarChar,50);
prm.Direction = ParameterDirection.Input;
prm.Value = txtUser.Text;
cmd.Parameters.Add(prm);
strHashedDbPwd = (string) cmd.ExecuteScalar();
if (strHashedDbPwd.Length>0) {
// Verify that hashed user-entered password is the same
// as the hashed password from the database
if (SaltedHash.ValidatePassword(txtPassword.Text,
strHashedDbPwd)) {
FormsAuthentication.RedirectFromLoginPage(
txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
}
else {
lblMsg.Text = "Login attempt failed.";
}
}
}
catch {
lblMsg.Text = "Login attempt failed.";
}
}
BestLogin.aspx和AddSecureUser.aspx都使用了SaltedHash类库,如表8所示。这些代码都是使由JEFF PROSISE使用用