我刚开始在网上开发东西.到目前为止,我花了很多时间(50%左右)来尝试阻止坏人将sql注入等内容放入我的输入表单并验证服务器端.这是正常的吗?
问题
我们需要在我们的java应用程序中防御'WAITFOR DELAY'sql注入攻击.
背景
[这很长.跳到'解决方案?' 以下部分,如果你匆忙]
我们的应用程序主要使用预准备语句和可调用语句(存储过程)来访问数据库.
在一些地方,我们动态构建并执行查询以供选择.在此范例中,我们使用条件对象根据用户输入条件构建查询.例如,如果用户为first_name和last_name指定了值,则查询结果总是如下所示:
SELECT first_name,last_name FROM MEMBER WHERE first_name ='joe' AND last_name='frazier'
Run Code Online (Sandbox Code Playgroud)
(在这个例子中,用户会指定"joe"和"frazier"作为他/她的输入值.如果用户有更多或更少的批评,我们会有更长或更短的查询.我们发现这种方法比使用准备更容易声明,比存储过程更快/更高效.
攻击
漏洞审计报告了sql注入失败.攻击者为'last_name'参数注入'frazier WAITFOR DELAY '00:00:20'值,导致这个sql:
SELECT first_name,last_name FROM MEMBER WHERE first_name ='joe' AND last_name='frazier' WAITFOR DELAY '00:00:20'
Run Code Online (Sandbox Code Playgroud)
结果:查询成功执行,但执行时间为20秒.攻击者可以占用数据库池中的所有数据库连接,并有效地关闭您的站点.
关于这种'WAITFOR DELAY'攻击的一些观察
我曾经想过,因为我们使用了Statement executeQuery(String),所以我们可以安全地从sql注入.executeQuery(String)不会执行DML或DDL(删除或删除).并且在分号上执行Query(String)choke,因此'Bobby Tables'范例将失败(即用户输入'frazier; DROP TABLE成员'作为参数.参见http://xkcd.com/327/)
"WAITFOR"攻击在一个重要方面有所不同:WAITFOR修改现有的"SELECT"命令,而不是单独的命令.
攻击仅适用于生成的查询中的"最后一个参数".即'WAITFOR'必须出现在sql语句的最后
解决方案,廉价黑客还是两者
最明显的解决方案是简单地将"AND 1 = 1"添加到where子句中.
生成的sql立即失败并阻止攻击者:
SELECT first_name,last_name FROM MEMBER WHERE first_name ='joe' AND last_name='frazier' WAITFOR DELAY '00:00:20' AND 1=1
Run Code Online (Sandbox Code Playgroud)
问题
当我开始在我的程序中编写第一个SQL语句时,我觉得很舒服,用同事给我看的一个非常简单的方法来保护自己免受SQL注入.它用两个单引号替换了所有单引号.
例如,有一个搜索字段,您可以在其中输入客户名以在可自定义项中进行搜索.如果你愿意进入
彼得的理发店
SELECT语句看起来像
SELECT *
FROM Customers
WHERE Customername = 'Peter''s Barbershop'
Run Code Online (Sandbox Code Playgroud)
如果现在攻击者会插入此:
';DROP TABLE FOO; --
Run Code Online (Sandbox Code Playgroud)
声明如下:
SELECT *
FROM Customers
WHERE Customername = ''';DROP TABLE FOO;--'
Run Code Online (Sandbox Code Playgroud)
它不会丢弃任何表格,而是搜索客户名称的客户名称; DROP TABLE FOO; - 我想,这将不会被发现;-)
现在经过一段时间编写语句并使用此方法保护自己免受SQL注入后,我读到许多开发人员使用参数化语句,但我从未读过使用"我们的"方法的文章.所以绝对有充分的理由.
参数化语句会覆盖哪些场景,但我们的方法却没有?与我们的方法相比,参数化语句有哪些优点?
谢谢
Philipp
我一直在编码我的网站在PHP最近,我对我的好我的消毒输入之前我在查询中使用它的做法很为自己感到骄傲.这一切都很顺利,直到我的朋友说我需要消毒我的输入.当我试图向他解释它已被消毒时,他告诉我他已经在我的数据库中的"用户"表中找到了所有内容.我不知道怎么样,所以我想我会发布我做错了什么让我的消毒不起作用.这是他正在利用的PHP代码:
start_mysql(); // Starts the databases stuff, etc.
$id = mysql_real_escape_string($_GET['id']);
$game = mysql_query("SELECT * FROM `games` WHERE `id` = $id LIMIT 0, 1");
Run Code Online (Sandbox Code Playgroud)
他所做的只是更改id参数,使他能够在我的数据库上使用SQL注入.我以为mysql_real_escape_string逃脱了所有这样的角色,但显然我错了.我用一个普通的字符串做了一些测试,看看会发生什么,这就是它所说的
网址:/game.php?id ='或''='
echo($_GET['id']); // This echo'd: \' OR \'\' = \'
echo(mysql_real_escape_string($_GET['id'])); // This echo'd: \\\' OR \\\'\\\' = \\\'
Run Code Online (Sandbox Code Playgroud)
所以,我的简单问题是,我做错了什么?
我得到了很多涉及sql注入尝试的点击,涉及越来越长的参数.我限制php中的参数将它们转换为正整数或零,但我不确定是否存在某种涉及真正长参数的技巧可能会导致我出现问题(缓冲区溢出问题?).
我知道php中的suhosin补丁有一些过长的参数补丁,虽然我目前还没有.我应该怎么做才能保护自己免受这样的情况(来自我的日志)?
ProductId=47&ItemId=-1025+UNION+SELECT+0x6d6567613164756d706572,0x6d6567613264756d706572,0x6d6567613364756d706572,0x6d6567613464756d706572,0x6d6567613564756d706572,0x6d6567613664756d706572,0x6d6567613764756d706572,0x6d6567613864756d706572,0x6d6567613964756d706572,0x6d65676131064756d706572,0x6d65676131164756d706572,0x6d65676131264756d706572,0x6d65676131364756d706572,0x6d65676131464756d706572,0x6d65676131564756d706572,0x6d65676131664756d706572,0x6d65676131764756d706572,0x6d65676131864756d706572,0x6d65676131964756d706572,0x6d65676132064756d706572,0x6d65676132164756--
Run Code Online (Sandbox Code Playgroud) 有许多出色的方法来保护应用程序免受SQL注入,例如,此问答显示了一些方法如何防止PHP中的SQL注入?.
这个问题是关于已经编写的应用程序.我们不想修改它以提高其安全性.我们想知道所使用的方法是否容易受到注入攻击.
我们需要知道这部分代码是否泄漏数据的原因?
这是一个PHP函数,以消除一些无用的(对我们来说)和可能有害的字符:
function removeBadCharacters($s)
{
return str_replace(array('&','<','>','/','\\','"',"'",'?','+'), '', $s);
}
Run Code Online (Sandbox Code Playgroud)
它会抛出危险的字符以避免SQL注入攻击(不要担心删除的字符,例如removeBadCharacters应用程序不需要它们):
$x = removeBadCharacters($_POST['data']);
mysql_query("insert into table (x) values ('".$x."');");
// or
mysql_query("select * from into where name = '".$x."';");
Run Code Online (Sandbox Code Playgroud)
是否足以使查询安全?
有没有办法绕过removeBadCharacters?
怎么可以打破?
我想知道在使用QSqlTableModel :: setFilter时是否有办法防止SQL注入,并且没有对WHERE子句条件进行验证.
我不想使用QSqlQueryModel,因为我需要编辑功能.
我目前正在使用以下查询来使用php获取mysql中的值:
代码正在运行,但现在我担心sql注入.
如何防止SQL注入?
<?php include_once("wp-config.php");
@$gameid = $_GET['gameid'];
global $wpdb;
$fivesdrafts = $wpdb->get_results(
"
SELECT ID
FROM $wpdb->posts
WHERE ID = ".$gameid."
"
);
?>
Run Code Online (Sandbox Code Playgroud)
这样安全吗?
<?php include_once("wp-config.php");
@$gameid = mysql_real_escape_string($_GET['gameid']);
global $wpdb;
$fivesdrafts = $wpdb->get_results(
$wpdb->prepare(
"
SELECT ID
FROM $wpdb->posts
WHERE ID = %d", ".$gameid.")
);
?>
Run Code Online (Sandbox Code Playgroud) 通过在LINQPad中输入,我可以得到我期望的结果:
SELECT * FROM WorkTable WHERE WTName LIKE "DSD__20090410014953000%"
Run Code Online (Sandbox Code Playgroud)
(它显示了WTName值为DSD__20090410014953000.xml的记录")
但尝试以编程方式执行此操作正在尝试.我试过了:
const string qry = "SELECT SiteNum FROM WorkTable WHERE WTName LIKE @wtName%";
using (SQLiteConnection con = new SQLiteConnection(HHSUtils.GetDBConnection()))
{
con.Open();
SQLiteCommand cmd = new SQLiteCommand(qry, con);
cmd.Parameters.Add(new SQLiteParameter("wtName", tableName));
siteNum = Convert.ToInt32(cmd.ExecuteScalar());
}
Run Code Online (Sandbox Code Playgroud)
...但它会导致应用程序崩溃,我的日志文件告诉我原因:
Message: From application-wide exception handler: System.Data.SQLite.SQLiteException: SQL logic error or missing database
near "%": syntax error
Run Code Online (Sandbox Code Playgroud)
所以也许它认为查询参数被命名为"wtName%"而不是"wtName"; 但是将参数和"what"opertor("%")与空格分开也不起作用.
我可以通过将查询参数嵌入到字符串中来实现retro/kludgy,如下所示:
const string qry = String.Format("SELECT SiteNum FROM WorkTable WHERE WTName LIKE {0}%", tableName);
Run Code Online (Sandbox Code Playgroud)
...和做没有查询参数完全,但我怕如果我这样做,特洛伊·亨特将在我的房子出现了,与床栏枷我而责骂SQL注入. …
假设Web服务器使用以下PHP代码来处理登录请求:
$username = $_POST[user];
$password = $_POST[pass];
$sql = "SELECT * FROM users WHERE name = '$username' AND password = '$password'";
if(mysql_num_rows($rs) > 0){ //do something
}
Run Code Online (Sandbox Code Playgroud)
我认为该值' OR 1=1将始终导致成功登录,因为查询将是:
"SELECT * FROM users WHERE name = '' OR 1=1 AND password = '$password'"
Run Code Online (Sandbox Code Playgroud)
它是否正确?
0x5c编码\和0x27编码'.字节0xbf27表示两个字符¿',字节0xbf5c是单个中文字符.如果用户名和密码字段添加斜线',",\,和null,什么用户名总是会导致一个成功登录,假设数据库解释字符串作为GBK但添加斜线处理字符串作为ASCII?我不确定句子的最后部分是什么意思(通过解释为GBK但处理为ASCII).有人能说清楚如何解决这个问题吗?
sql-injection ×10
php ×4
security ×3
sql ×3
c# ×1
jdbc ×1
mysql ×1
qt ×1
sql-like ×1
sql-server ×1
sqlite ×1
user-input ×1
wordpress ×1
xss ×1