没有堆叠查询的 MySQL SQL 注入 - 在不影响 FS 的情况下实际上有什么可能?

信息安全 sql注入
2021-09-13 09:18:56

我正在探索一个基本上充斥着 SQL 注入的 PHP 网站中的漏洞。使用 SQLMap,我设法转储了所有表并获取了一些基本信息(用户名、数据库名称、主机名,尽管它似乎毫无用处,因为数据库服务器在外部不可用)。我的目标是修改特定表中的数据,在任何可注入的 SQL 查询中都没有提到。我尝试了 SQLmap 的--db-shell开关,但我发现除了 SELECT 之外我不能做任何事情,因为 PHP+MySQL 组合不允许堆叠查询。

因此我的问题。给定以下片段之一:

mysql_query("SELECT * FROM sometable WHERE id=".$_GET['id']);
mysql_query("INSERT INTO sometable (id) VALUES (".$_GET['id'].")");
mysql_query("UPDATE sometable SET id= ".$_GET['id']);
mysql_query("DELETE FROM sometable WHERE id=".$_GET['id']);

我可以从某个表之外修改(删除、插入、更新)数据,而不使用 LOADFILE/INTO OUTFILE(和类似的)技巧吗?在这种情况下,MySQL 语法会让我这样做吗?如果答案是“取决于”,查询语法会如何让我通过?我不是这台主机的 DBA。网站上也没有存储过程,只有一些非常基本的、业余的东西,你可以从一本甚至没有提到安全性的书中学到这些东西。

3个回答

首先:我不确定我是否理解您的查询,但我假设您的意思是:我如何影响外部数据(这些查询所涉及的表)?

最明显的攻击是插入多个查询,即“;从 other_table 中删除”,但在这种情况下,您似乎不能这样做。mysql_query() 发送唯一查询(不支持多个查询)

这意味着您会遇到副作用 - 在原始查询中执行操作。看起来至少你可以用锁破坏: http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html 特别是,你应该能够做出选择的一个'选择...进行更新';

我还看不到另一种方式来影响您的特定查询。

我一直在玩这个,我还没有找到任何方法来做你所说的。比我聪明的人可能会想办法做到这一点,但据我所知,这是不可能的。

使用 PHP 数据对象进行数据访问层查询要好得多。这将完全消除 SQL 注入;更不用说您可能还想与称为 OWASP 的网站组建立友好关系。

例子:

// 声明和设置变量

列表 ($db_dbdriver, $db_hostname, $db_database, $db_username, $db_password) = Connection::dbConnect();
// 设置默认时区

date_default_timezone_set('America/Los_Angeles'); $my_success = 假;$my_message = "";

尝试 {

// 创建和设置连接

$db_options = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'");

$conn = new PDO($db_dbdriver . ":host=" . $db_hostname . ";dbname=" . $db_database, $db_username, $db_password, $db_options);

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//准备一条SQL语句

$my_sql = '插入消息(Message_State,Message_Body,Message_CBy,Message_EBy)值(:Message_State,:Message_Body,:Message_CBy,:Message_EBy)';

$stmt = $conn->prepare($my_sql); // 绑定参数以防止 SQL 注入。

$stmt->bindValue(':Message_State', $message_state);

$stmt->bindValue(':Message_Body', $message_body);

$stmt->bindValue(':Message_CBy', $message_cby);

$stmt->bindValue(':Message_EBy', $message_eby);

// 执行 SQL 语句

$stmt->执行();

// 关闭游标,使语句能够再次执行

$stmt->closeCursor();

// 关闭和取消连接

$conn = 空;未设置($conn);

// 将成功值设置为 TRUE

$my_success = 真;$my_message = "成功";

} 捕捉(PDOException $e){

// 捕捉错误信息

$error_message = $e->getMessage();

// 将错误消息附加到错误日志

file_put_contents('../../log/error/php_errors.log', "\r\n" . date("Ymd h:i:s A") . ": data_access_layer -> my_class.php (class_name) - > Function_Name : " . $e->getMessage(), FILE_APPEND);

// 将成功值设置为 FALSE 并返回错误消息

$my_success = 假;$my_message = $error_message;

}

返回数组($my_success,$my_message);