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

Is there a way to demonstrate SQL injection with mysqli?

提问人:Addeuz 提问时间:1/21/2019 最后编辑:Peter MortensenAddeuz 更新时间:7/20/2019 访问量:622

问:

我想快速轻松地演示一下 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默认支持多查询,但是当我尝试它时,它不起作用。也许我绑定了错误的参数。但我什至无法进行简单的选择查询来工作。

php sql mysqli sql 代码注入

评论

0赞 user3783243 1/21/2019
类似的东西应该让你得到管理员的密码......如果有表。我认为如果您在 PDO 上关闭仿真,它将不允许多个查询。$searchterm = "' union select password, username from admins--";admins
0赞 Dharman 1/21/2019
通过添加第二个查询实际上可以进行 SQL 注入吗?
0赞 Dharman 1/21/2019
stackoverflow.com/a/7414582/1839439

答:

2赞 Bill Karwin 1/21/2019 #1

mysqli_query() 默认不支持多查询。它有一个单独的函数:mysqli_multi_query()。

SQL注入不仅仅是运行多个语句,尽管有著名的XKCD卡通

您的代码存在不良的 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 注入恶作剧。它甚至可能是无辜的,但仍然会导致问题。例如,假设搜索是:。将该值直接复制到 SQL 中将导致如下查询:O'Reilly

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

看到不匹配的引号了吗?这不会做任何恶意的事情,但只会导致查询失败,因为不平衡的引号会产生语法错误。'

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

为了防止意外和恶意 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 查询中。它们被单独发送到数据库服务器,并且在解析查询之前永远不会与查询组合,因此它不会导致语法问题。

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


回复您的评论:

...容易受到注入,所以我可以向学生展示恶意攻击可能造成多大的伤害。

下面是一个示例:

几年前,我是一名 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.

(这是我对他的代码的有根据的猜测,我还没有看到代码。

我花了 5 秒钟来思考逻辑,我在用户名的登录表单中输入了一个布尔表达式,对于密码,我输入了随机的垃圾字符。

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

我不会给出我使用的确切布尔表达式,但如果你了解任何离散数学类中涵盖的基本布尔运算符优先级,你应该能够弄清楚。

评论

0赞 Addeuz 1/21/2019
我读过一些关于mysqli::multi_query()的东西,但我认为这违背了我认为的整个目的。我正在为具有PHP基础知识的学生做这个演示,说这样的话会感觉很奇怪:如果你想保护自己免受sql注入的影响,就不要使用multi_query()。此外,我什至没有使用mysqli::query(),我刚刚认识到这是我应该做的事情吗?
0赞 Addeuz 1/21/2019
好的,谢谢你,现在我明白了如何让它更安全。如果我的问题不清楚,我很抱歉,但我想要的是让它容易受到注入,这样我就可以向学生展示恶意攻击可能造成多大的伤害。最不安全的方法是什么?从 searchterm 变量执行多个查询。.
0赞 Jacopo Vendramin 1/21/2019 #2

你试过这样的东西吗?

'(here put something);

这样,您将使用 ' 关闭查询并向其中添加其他内容,当您添加 ;其他一切都将被丢弃