基本上,在我阅读了互联网上的一些文章之后,我开始使用预备语句,这些文章说这是防止sql注入的简单方法。跳转到我的场景,我有一个logExit函数,它将访问者来自我网站的页面和他离开我网站后的页面插入数据库。
public function logExit($url){
$HTTP_REFERER = ($_SERVER['HTTP_REFERER'] ? $_SERVER['HTTP_REFERER'] : '');
$REMOTE_ADDR = ($_SERVER['REMOTE_ADDR'] ? $_SERVER['REMOTE_ADDR'] : '');
$params = array(
$REMOTE_ADDR,
$HTTP_REFERER,
$url
);
// custom query function ~ prepare/execute
$this->query("
INSERT INTO exits(ip, url_in, url_out) VALUES (?, ?, ?)
", "sss", $params);
}
问题是,今天当我登录管理面板查看我今天有多少访问者以及他们从我的网站离开了哪里时,我收到了大量警报。当我检查我的数据库时,我有13500个从相同的IP退出到不同的页面,但问题来自url_in
字段,这里有一些例子:
ip | url_in | url_out |
-----------+-------------------------------------+---------------|
xx.xx.xx |'"></a><script>alert(11779)</script> | xxxxxxxxxxxxx |
-----------+-------------------------------------+---------------|
xx.xx.xx | ,alert(11774), | xxxxxxxxxxxxx |
-----------|-------------------------------------|---------------|
xx.xx.xx | %c0%a7 | xxxxxxxxxxxxx |
-----------|-------------------------------------|---------------|
xx.xx.xx | %2527 | xxxxxxxxxxxxx |
-----------+-------------------------------------+---------------|
HTTP_REFERER = url_in
$ url = url_out
所以这看起来很奇怪,因为据我所知HTTP_REFERER应该是一个URL。这个混乱怎么进入我的数据库以及如何防止它?
由于
PS。托管公司向我展示了这个日志,这是什么意思?
access-logs/my-example-website.com:xxx.xxx.xxx.xx - - [21/Dec/2017:18:59:59 +0200] "GET /mode.php?admin_mode=1&referer=javascript:alert(16555) HTTP/1.1" 404 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
答案 0 :(得分:7)
这是按设计工作的,您可以免受SQL注入问题的影响。这里的关键是SQL注入攻击只是one vector of many。
为了安全地使用该内容,您必须在其使用的上下文中正确地转义它。如果您将其显示为HTML,则意味着使用htmlspecialchars
之类的函数来阻止XSS攻击,或者如果您使用JSON或JavaScript对其进行编码,则使用json_encode
对该上下文进行正确编码。
如果你在数据库中看到这样的垃圾,可能是因为你被一些自动攻击者探测过。大多数生产站点每天都会看到成千上万的攻击企图,遗憾的是这就是现状。如果你想安静下来,你可以使用像fail2ban这样的东西来禁止屡次犯罪。
答案 1 :(得分:2)
您在表中看到了这些结果,而不是错误日志中的一系列错误抱怨格式错误的SQL表明准备好的语句+绑定变量正在完成其工作。
请注意,它不是保护您免受SQL注入的预准备语句,而是使用绑定变量而不是从脏数据构建SQL语句。
答案 2 :(得分:1)
准备语句是保护您免受sql注入的最佳方法(您应该使用广泛使用的框架,但我想这就是这种情况)
预备语句不会阻止您将垃圾数据导入数据库。甚至攻击向量也可能在以后被插入时成功f.e.因为html(xss)可以进入数据库。但在这种情况下,根本原因是在呈现之前缺少验证/转义而不是数据库框架。
但是,要在数据库中存档干净数据,您必须在插入数据之前验证数据(输入验证)。让我告诉你,没有简单的方法来完成所有数据,因为它取决于您在特定应用程序中的信息的性质。而且没有银弹。
答案 3 :(得分:1)
其他人是对的。您已成功避免SQL注入。
但网络蠕虫正在向你发送恶意制作的引用字符串。
你知道HTTP&#34; referer&#34;标头应该包含一个URL。远程地址字符串应包含IP地址或主机名,并附加端口号。 (不是网址)。
因此,在将referer插入数据库之前,您可以检查它是否是一个格式正确的URL或恶意的东西。如果它是恶意的,您可以将其删除,或将其更改为http://malicious.example.com,或者在插入之前做任何想要清除垃圾的内容。
在您的情况下,请使用php's nice built in filtering capability。第一次设置$HTTP_REFERER
后立即添加这些行。
$HTTP_REFERER = filter_var( $HTTP_REFERER, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE );
if ( is_null( $HTTP_REFERER ) ) {
$HTTP_REFERER = 'http://bogus-referer.example.com/';
}
或其他什么。
使用FILTER_VALIDATE_IP为remote_addr做类似的事情。
记住这一点:你不是偏执狂。聪明且有动力的人实际上正在密谋反对你,并试图打击你的网站。