某客户站点遭遇了大的mysql注入攻击,想学习一下

信息安全 php sql注入 mysql
2021-08-28 07:24:31

我为我的一个朋友创建了一个在线商店。

我创建了一个系统,只要出现数据库错误,它就会向我发送电子邮件,这样,如果它是我的代码中的错误,我可以识别它并修复它。该电子邮件包含有关失败的查询、传递的数据、会话数据等的详细信息。

今天早上 3:05,我在 5 分钟内收到了大约 120 封电子邮件。对于数据库错误并查看正在发生的事情,我可以很快看出这是一次 mysql 注入攻击。在查看了攻击者尝试的一堆东西之后,我有点想知道他们试图传递的一些 sql 命令实际上会做什么。

在查看了整个数据库以及网站上的文件后,我几乎 99% 肯定没有任何损坏、删除或更改。这让我很高兴知道我的 php 知识足够了解如何防止这些事情发生。

我的问题是,在下面的 mysql 命令中,攻击者试图做什么?

 or 1=convert(int,(select cast(Char(114)+Char(51)+Char(100)+Char(109)+Char(48)+Char(118)+Char(51)+Char(95)+Char(104)+Char(118)+Char(106)+Char(95)+Char(105)+Char(110)+Char(106)+Char(101)+Char(99)+Char(116)+Char(105)+Char(111)+Char(110) as nvarchar(4000))))--

; if (1=1) waitfor delay \'00:00:07\'--

union all select null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null--

999999.9 union all select 0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536--

leachiancs\' and \'x\'=\'x

谢谢(你的)信息。

更多信息

为每次攻击运行的查询很简单

SELECT * FROM tableName WHERE $phpVar AND price!='sold' ORDER BY id DESC

$phpVar 的填充基于 $_GET 条目是否与接受术语数组中的术语匹配。

所以正在运行并返回错误的文字查询是

SELECT * FROM tableName WHERE AND price!='sold' ORDER BY id DESC

这就是引发关注的原因

 Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND price!='sold' ORDER BY id DESC' at line 1
4个回答

您的数据库运行引用的查询(向您抛出错误报告)这一事实意味着您在 PHP 代码中确实存在注入漏洞。请注意,检查 DB 表结构的某些方法涉及使用不同参数运行多个查询,直到 DB 抛出错误和 HTML 分页符。这意味着失败的查询只是所有已运行查询的冰山一角。

有5个查询:

1) 通过有效地添加 " or 1=1" 语句使所有以前的限制性 WHERE 语句无效。

2) 通过添加另一个延迟查询来检查针对 SQL Server DB 的 DOS 攻击。

3)检查数据库表中的列数。通过和失败查询之间变化的空值数是攻击者寻找的一个。

4) 用户身份验证表相同:以可能不存在的 ID 结束查询,然后检查列数。null-s 被 HEX 值替换。

5) 通过将精心制作的 $user 注入到查询 PHP 字符串中来误导身份验证检查,例如

“SELECT ... WHERE ... AND 名称 = '” + $user + “'”

(注意单引号和双引号的确切顺序)用户“leachiancs”很可能是通过先前的调查真正获得的。

查询 (1)-(4) 最后带有 SQL 注释,以使最初预期的查询的其余部分无效并击败 LIMIT 或其他验证 WHERE 构造。

这里的主要教训是只使用参数化查询,而不是试图重现所有可能的版本和语法怪癖的正确 DB+PHP 转义的所有脏工作。

我有一些有趣的“解码”两个查询,所以这就是我在 PHP 中的做法:p

1) or 1=convert(int,(select cast(Char(114)+Char(51)+Char(100)+Char(109)+Char(48)+Char(118)+Char(51)+Char(95)+Char(104)+Char(118)+Char(106)+Char(95)+Char(105)+Char(110)+Char(106)+Char(101)+Char(99)+Char(116)+Char(105)+Char(111)+Char(110) as nvarchar(4000))))--

因此,让我们从将这段代码复制到变量中开始:

$str = 'Char(114)+Char(51)+Char(100)+Char(109)+Char(48)+Char(118)+Char(51)+Char(95)+Char(104)+Char(118)+Char(106)+Char(95)+Char(105)+Char(110)+Char(106)+Char(101)+Char(99)+Char(116)+Char(105)+Char(111)+Char(110)';
preg_match_all('/\d+/', $str, $m); // Some regex Fu to get the numbers
$sql = implode('', array_map(function($v){return chr($v);}, $m[0])); // converting the numbers to letters
echo $sql; // output

这给了我r3dm0v3_hvj_injection并且在检查了 mysql 转换和强制转换语法之后,它似乎在这里搞砸了,但我不确定,但基本上这是一种混淆方法,目的是最终以or 1=1.


2) ; if (1=1) waitfor delay \'00:00:07\'--

声明;结束声明,其余的似乎是基于时间的攻击虽然这似乎没用,因为 php 中的 mysql api 不能同时执行 2 个查询。--评论查询的其余部分。


3) union all select null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null--

对我来说似乎没用,但它可以确定您有多少列,因为如果null列数与您拥有的列数不匹配,这将引发错误。


4) 999999.9 union all select 0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536--

好吧,让我们将这些十六进制变量复制到一个变量中并对其执行一些 php-fu:

$str = '0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536,0x31303235343830303536';

$result = implode(',', array_map('hex2str', explode(',', str_replace('0x', '', $str)))); // PHP-Fu
echo $result;// output

// function hex to ascii
function hex2str($v){
    $r = '';$l = strlen($v)-1;
    for($i=0;$i <= $l;$i+=2){
        $r .= chr(hexdec($v[$i].$v[$i+1]));
    }
    return $r;
}

这给了我: 1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056,1025480056

我虽然这很奇怪,因为它都是一样的让我们将它从十六进制重新转换为字符串:

echo hex2str('1025480056');

输出是%HV,使用普通的十六进制编辑器还有 2 个其他晦涩的字符。

好吧,我认为目的可能与攻击#3中的相同,只是被混淆了。


5) leachiancs\' and \'x\'=\'x

简单where a=b and x=x查询。


结论:

Le wild r3dm0v3_hvj_injection%HV出现了,在 500 万封邮件中有 120 封电子邮件,我高度怀疑这是使用自动化 SQLi 工具 Havij执行此攻击的证据。

预防:

PDOMySQLi准备好的语句一起使用。

这让我很高兴知道我的 php 知识足够了解如何防止这些事情发生。

这是一种非常危险的心态,可以从这一事件中解脱出来。

攻击者似乎没有删除数据并不意味着他们没有读取他们不应该拥有的数据。他们能够输入导致数据库错误的输入这一事实证明了您实际上并不知道如何防止这些事情发生,因为准备好的语句和参数化查询甚至可以防止这种情况发生。

至于提供的查询本身,它们似乎主要是首先尝试查找 SQL 注入漏洞。

攻击者似乎正试图对他发现的漏洞进行哪些类型的攻击进行调查。

不管; 教训总是一样的:使用参数化查询。如果您必须记住引用和转义您的数据,那么您做错了。

如果您想了解更多关于典型 SQL 注入攻击如何工作的信息,请查看通常用于此类攻击的自动化工具,例如 burp 套件。