有没有办法用mysqli演示SQL注入?

时间:2019-01-20 17:17:36

标签: php sql mysqli sql-injection code-injection

我想简单快速地演示一下SQL注入的工作原理。我已经解决了一些问题。我有一个包含随机用户名,密码和电子邮件的表,并且能够“注入” SQL代码以查看与此注入相关的所有用户:

' OR '1'='1

这是我的PHP代码寻找“成员”的样子:

if (isset($_POST['search'])) {
    $searchterm = $_POST['searchterm'];
    echo $searchterm . '<br>';

    /*sql query for searching in database*/
    $sql = "SELECT username, email FROM Members where username = '$searchterm'";
    if ($stmt = $conn->prepare($sql)) {
        /* execute statement */
        $stmt->execute();

        /* bind result variables */
        $stmt->bind_result($name, $email);

        /* fetch values */
        while ($stmt->fetch()) {
            echo "Username: " . $name . " E-mail: " . $email . "<br>";
        }
    } else {
        die($conn->error);
    }
}

现在,我想演示一些更致命的问题,例如有人将您的整个桌子截断。因此,我在搜索栏中尝试了以下代码:

'; TRUNCATE TABLE Members; -- 

但是我收到此错误消息:

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'TRUNCATE TABLE Members; -- '' at line 1

似乎我得到了一个额外的',但是我不知道如何摆脱它,以为-会把它注释掉。首先,我认为问题在于我在-后面没有空格,但是添加空格没有任何作用。

我曾尝试切换到PDO,因为我认为mysqli无法接受多个查询存在问题,但是后来我在某处读到PDO也不支持,但我也不知道。

有什么办法可以使它工作?

编辑:我知道默认情况下PDO支持多重查询,但是当我尝试它不起作用时,也许我绑定了错误的参数。但是我什至无法进行简单的选择查询。

2 个答案:

答案 0 :(得分:1)

mysqli_query()默认情况下不支持多查询。为此,它具有单独的功能:mysqli_multi_query()

SQL注入不仅与运行多个语句有关,尽管著名的XKCD cartoon也是如此。

您的代码有一个严重的SQL注入漏洞。即使您将$ _POST请求数据中的内容直接插值到SQL字符串中,您是否认为使用prepare()可以使查询安全?

您的代码是这样的:

$searchterm = $_POST['searchterm'];

$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
    /* execute statement */
    $stmt->execute();
    ...

不安全的输入很容易以这种方式使SQL注入恶作剧。它甚至可能是无辜的,但仍然会导致问题。例如,假设搜索为:O'Reilly。直接将该值复制到您的SQL中将导致如下查询:

SELECT username, email FROM Members where username = 'O'Reilly'

看到不匹配的'引用吗?这不会带来任何恶意,但只会导致查询失败,因为不平衡的引号会导致语法错误。

使用prepare()不能解决意外的语法错误,也不能防止复制修改查询语法的恶意内容。

为防止意外SQL和恶意SQL注入,您应使用如下绑定参数:

$searchterm = $_POST['searchterm'];

$sql = "SELECT username, email FROM Members where username = ?";
if ($stmt = $conn->prepare($sql)) {
    $stmt->bind_param('s', $searchterm);
    /* execute statement */
    $stmt->execute();
    ...

绑定参数不会复制到SQL查询中。它们将分别发送到数据库服务器,并且在解析后 之后才与查询组合,因此不会引起语法问题。

关于您对mysqli::query()的问题,如果您的SQL查询不需要绑定参数,则可以使用它。


发表评论:

  

...容易被注射,因此我可以向学生展示恶意攻击可能会造成多大危害。

这是一个例子:

几年前,我是一名SQL培训师,在一家公司的一次培训中,我谈论的是SQL注入。一位与会者说:“好的,请向我展示SQL注入攻击。”他递给我他的笔记本电脑。浏览器已打开他网站的登录屏幕(这只是他的测试网站,而不是实际的生产网站)。登录表单很简单,只有用户名和密码字段。

enter image description here

我从未见过他处理登录表单的代码,但是我认为表单是由某些代码处理的,例如大多数不安全的网站是:

$user = $_POST['user'];
$password = $_POST['password'];

$sql = "SELECT * FROM accounts WHERE user = '$user' AND password = '$password'";
// execute this query.
// if it returns more than zero rows, then the user and password
// entered into the form match an account's credentials, and the
// client should be logged in.

(这是我对他的代码的有根据的猜测,但我仍然没有看到代码。)

我花了五秒钟的时间来思考逻辑,然后我在登录表单中输入了一个布尔表达式来表示用户名,并为密码输入了随机垃圾字符。

然后,我登录到他的帐户-,甚至不知道甚至试图猜测他的密码。

我不会提供我使用的确切布尔表达式,但是如果您了解任何离散数学类中涵盖的基本布尔运算符优先级,那么您应该可以弄清楚。

答案 1 :(得分:0)

您尝试过这样的事情吗?

'(here put something);

这样,您将使用'关闭查询,并在添加时向其中添加其他内容。其他所有东西都将被丢弃