网站安全基础知识

哈Ha!

安全是一个严重的问题。 通常,这方面的问题出乎意料,并带来极其不愉快的后果。 因此,对于每个Web开发人员,此主题的知识都极为重要。

我将立即预订-我距离专业人士还很远,但我为此努力。 因此,我很乐意批评,但只能是客观的。 本材料适用于希望提高专业水平和专家价值的初学者。

但是,我展示了最简单的代码实现。 我了解异常,了解ORM,了解框架中提供的保护。 我的目标是清楚地显示它,以便每个人都可以理解。

因此,是时候完成介绍并开始练习了。

从新手实施到任何理智结果的路径


我不习惯理论。 我的灵魂渴望练习。 因此,在谈到安全主题时,我们将从实用的角度考虑几乎所有类型的攻击-如何实施和如何保护自己。 是的,您可以说教黑客不是一件好事,但是,不知道攻击是如何发生的,我们就无法建立起有效的防御体系。

s


好的,第一类攻击是XSS。 是的,每个人都听说过的老式XSS。 XSS(跨站点脚本)是一种针对站点访问者的攻击。 这是怎么发生的:攻击者通过输入字段编写恶意代码,该恶意代码进入数据库并完成其工作。 通常,通过这种方式,cookie被用户窃取,这使他们无需密码和登录即可登录其帐户。

我们正在实施一个更无害的示例。

我们的开发人员制作了一个简单的表单来添加评论:

Index.php文件
<?php $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); $query = $pdo->prepare("SELECT * FROM `comments`"); $query->execute(); $comments = $query->fetchAll(); if ($_POST) { $username = trim($_POST['name']); $comment = trim($_POST['comment']); $query = $pdo->prepare("INSERT INTO `comments` (`username`,`message`) VALUES ('$username', '$comment')"); $query->execute(); if ($query) { echo ' !'; header("Location: index.php"); } else { echo ' !'; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>XSS</title> </head> <body> <form method="POST" class="addComment"> <input type="text" name="name" placeholder="Username"> <textarea name="comment"></textarea> <input type="submit" value=" "> </form> <div class="h2"></div> <div class="comments"> <?php if ($comments): foreach ($comments as $comment):?> <div class="comment"> <div class="comment_username"><?php echo $comment['username'];?></div> <div lass="comment_comment"><?php echo $comment['message'];?></div> </div> <?php endforeach;?> <?php else:?> <div class="no_comments"> </div> <?php endif;?> </div> </body> </html> 

代码非常简单,不需要解释。

有一个入侵者-约翰。 约翰无聊了,偶然发现了我们开发人员的所在地。
John在表单上写了以下消息:

 <script>document.body.style.backgroundColor = "#000";</script> 

现在,该网站的所有用户都有黑色背景。 John感到满意,并且开发人员获得了经验和谴责。

发生了什么事?

John用JavaScript代码添加了注释。 将数据输出到页面时,文本注释将转换为html代码。 看到script标记的用法的html代码将其添加到标记中,并且解释器已经执行了JavaScript代码。 也就是说,John只是将他的js代码添加到了现有站点代码中。

我们将如何解决?

为了纠正这种误解,创建了htmlspecialcars函数。 她的工作实质是用特殊字符替换引号和方括号等字符。 例如,字符“ <”将替换为其相应的字符代码。 使用此功能,我们可以处理表单中的数据,现在John的js代码不再会损害我们的网站。 当然,如果这是网站上的唯一表格。

代码中的更改如下所示:

Index.php文件
 <?php if ($_POST) { $username = htmlspecialchars(trim($_POST['name'])); $comment = htmlspecialchars(trim($_POST['comment'])); /// } 


SQL注入


另一种最常见的攻击类型已经开始被人们所遗忘。 他们忘记了它,因为有准备好的查询和框架。

我们将讨论准备好的请求。

攻击的本质是什么:攻击者将SQL查询的一部分输入到输入字段中并提交表单。 在查询执行期间,将接收到的数据添加到数据库中。 但是由于代码包含代码,因此在添加记录时,它会修改脚本的逻辑。

好吧,模拟一个情况。 我们的开发人员已保护表单不受XSS攻击。 John继续利用他的知识,指出不幸的开发人员的缺陷。

也就是说,我们将继续使用相同的表单来添加评论。
让我们进行一些更改:

1)预审意见。

最重要的是,只有主持人批准的那些评论将显示在页面上。 我们以最简单的形式实施预审核,以免分散本文的主要内容。

要实现该想法,请在带有注释的表中添加字段“ is_moderate”,该字段将带有两个值-“ 1”(显示注释)或“ 0”(不显示)。 默认情况下,当然是“ 0”。

2)更改请求。

这是为了清楚起见。 让添加注释的请求如下所示:

 "INSERT INTO `comments` SET `username`='$username', `message`='$comment'" 

现在的表单代码如下:

Index.php文件
 <?php $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); $query = $pdo->prepare("SELECT * FROM `comments` WHERE `is_moderate`='1'"); $query->execute(); $comments = $query->fetchAll(); if ($_POST) { $username = htmlspecialchars(trim($_POST['name'])); $comment = htmlspecialchars(trim($_POST['comment'])); $query = $pdo->prepare("INSERT INTO `comments` SET `username`='$username', `message`='$comment'"); $query->execute(); if ($query) { echo ' !'; } else { echo ' !'; } } ?> 


好的,John登录到该站点,并且看到评论开始受到审核,他决定嘲笑开发人员。 而且,现在XSS攻击的形式已成功体现出来,John已经被剥夺了获得乐趣的机会。 他留下了这样的注释:“ LOL',is_moderate ='1”,并绕过审核。

怎么了

当您在查询中替换John的评论时,引号会中断。 也就是说,如上所述,John能够执行任意SQL代码。

在执行带有John注释的请求时,该请求如下:

 "INSERT INTO `comments` SET `username`='John', `message`='LOL', `is_moderate`='1'" 

此外,不仅可以在提交表单时实施SQL注入。 当通过其标识符接收记录,处理搜索表单以及其他不太明显的情况时,也会发生这种情况。

如何解决?

解决问题的方法已经很长时间了-准备查询。 准备的请求是在执行之前经过特殊处理的请求。 处理包括转义其他引号。 您一定听说过这样的功能。 在PHP中,它是这样实现的:“ \'”。

最受欢迎的解决方案是PDO。 PDO是用于处理数据库的接口。 有一个相当方便的界面。 仅明智地使用它。

PDO提供了使用掩码和占位符来实现准备好的查询的功能。

然后我们在使用遮罩时的请求将如下所示:

Index.php文件
 <?php $query = $pdo->prepare("INSERT INTO `comments` SET `username`=:username, `message`=:comment"); $params = ['username' => $username,'comment' => $comment]; $query->execute($params); 


当使用这样的占位符时:

Index.php文件
 <?php $query = $pdo->prepare("INSERT INTO `comments` SET `username`=?, `message`=?"); $params = [$username,$comment]; $query->execute($params); 


现在,约翰的袭击不再重要。 至少对于这种形式。

顺便说一句,即使采用这种形式,我们的审核也已经可以抵御另一种攻击-SPAM。 我们都听说过他。 SPAM就是发送任何消息,其中攻击者借助社会工程学知识进行攻击。 现在,唯一将受到攻击的是主持人。 然后,如果他不是那么愚蠢,那么他将从数据库中删除垃圾,或者如果他很懒,他将拒绝发布,仅此而已。

CSRF攻击


CSRF-跨站请求伪造。 这很危险,因为很少有人知道。 尽管这样做很简单。

怎么发生的:来自另一个站点的攻击者伪造了一个表格,并迫使受害者遵循此表格。 即,发送POST请求。 因此,HTTP请求是伪造的,并且在受害者的站点上执行了恶意操作。

例如,攻击者可以代表您用VK向您的朋友发送一封信,但您对此一无所知。

听起来有点混乱。 我建议在实践中考虑。

我们的开发人员制作了表格,他做得很好。 她已经知道如何防御XSS,SQL注入并保持Spam的压力。 看起来像这样:

开发人员站点上的index.php文件
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSRF</title> </head> <body> <form action="action.php" method="POST"> <input type="text" name="username"> <textarea name="message"></textarea> <input type="submit" value=" "> </form> </body> </html> 


但是约翰不是那么简单。 他接收表单代码(仅来自浏览器中站点的源代码)并将表单添加到他的站点。

约翰的index.php文件
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSRF</title> <style> form input[type=submit]{ padding: 15px; font-size: 20px; color: #fff; background: #f00; cursor: pointer; } </style> </head> <body> <form action="localhost/note/action.php" method="POST"> <input type="hidden" name="username" value="lol"> <input type="hidden" name="message" value="  !   !"> <input type="submit" value=" !"> </form> </body> </html> 


请注意,在John的网站上,处理表单的位置是我们开发者网站上的文件。 因此,现在单击该按钮的任何用户都将发送不好的评论。

这是CSRF攻击。 当然,在最简单的版本中。

开发人员再次遇到问题...

如何修复漏洞?

某个时候,开发人员将用谷歌搜索csrf是什么,保护逻辑如下:为了进行保护,您需要创建一个csrf令牌(一组字母和数字)并将其挂在表单上。 还必须为用户固定相同的令牌(例如,通过会话)。 然后,在处理表单时,比较这些标记。 如果它们匹配,我们可以添加评论。

我们实现了这一点:

开发人员站点上的index.php文件
 <?php session_start(); $token = ''; if (function_exists('mcrypt_create_iv')) { $token = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); } else { $token = bin2hex(openssl_random_pseudo_bytes(32)); } $_SESSION['token'] = $token; ?> ... <form action="action.php" method="POST"> <input type="text" name="username"> <textarea name="message"></textarea> <input type="hidden" name="csrf_token" value="<?php echo $token;?>"> <input type="submit" value=" "> </form> 


文件action.php
 <?php session_start(); if ($_POST) { if ($_SESSION['token'] == $_POST['csrf_token']) { echo ' !'; } else { echo '!'; } } 


蛮力和Publick密码


也许是最著名的攻击类型。 他几乎每首关于黑客之类的电影都听过。

重点是:网站管理面板中有一个授权表单。 我们需要约翰不知道的用户名和密码。 但是他有一个包含常用用户名和密码的文件。 他很高兴地在我们的网站上尝试使用它们。

开发人员可以反对什么? 例如,对一定时间内授权尝试次数的限制。

让授权表单的初始版本如下所示:

Index.php文件
 <?php $opt = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); if (isset($_POST['autoriz'])) { $username = htmlspecialchars(trim($_POST['login'])); $password = htmlspecialchars(trim($_POST['password'])); $query = $pdo->prepare("SELECT * FROM `users` WHERE `username`=:username AND `password`=:password"); $query->execute(['username' => $username,'password' => $password]); $find_user = $query->fetchAll(); if ($find_user) { echo ' !'; } else { echo '  !'; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Brute Force  Public Passwords</title> </head> <body> <form method="POST"> <input type="text" name="login" placeholder="Login"> <input type="password" name="password" placeholder="Password"> <input type="submit" value="" name="autorize"> </form> </body> </html> 


如何解决:如前所述,最简单的选择是限制每个时间段内的授权尝试次数。

为此,当我们尝试登录时,我们会将当前时间值添加到Cookie中的用户。 现在,当尝试登录时,我们将看到用户在5秒钟内最多可以登录1次。 此外,如果未正确输入密码或登录名,我们会将超时时间延长到下一次尝试5秒。

Index.php文件
 <?php $count_next_minit = $_COOKIE['count_try'] ? $_COOKIE['count_try'] : 1; $seconds_to_new_try = 5; $opt = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); if (isset($_POST['autorize'])) { if ($_COOKIE['last_try']) { if ($_COOKIE['last_try'] < time() - $seconds_to_new_try * $count_next_minit) { $username = htmlspecialchars(trim($_POST['login'])); $password = htmlspecialchars(trim($_POST['password'])); $query = $pdo->prepare("SELECT * FROM `users` WHERE `username`=:username AND `password`=:password"); $query->execute(['username'=>$username,'password'=>$password]); $find_user = $query->fetchAll(); setcookie('last_try', time(), time() + 3600); if ($_COOKIE['count_try']) { $old_value = (int)$_COOKIE['count_try']; setcookie('count_try', $old_value + 1, time() + 3600); } else { setcookie('count_try', 1, time() + 3600); } if ($find_user) { var_dump(' !'); } else { var_dump('  !'); } }else{ var_dump('   !    ' . $seconds_to_new_try * $count_next_minit . ' '); } }else{ setcookie('last_try', time(), time() + 3600); } } ?> 


回溯


回溯是一种通过系统错误消息进行攻击的方法。 这是MySQL和PHP。

例如,John输入了错误的URL,并被提示错误,表明数据库中没有记录具有这样的ID(如果该记录是通过ID从地址栏中接收到的,则为site.ru/article?id=12)。 甚至存在所谓的“笨蛋”-特定的网站地址模式,用户输入时会看到错误。 这使John可以使用漫游器浏览此地址列表,并尝试在您的站点上发现此漏洞。

如何解决? 在这种情况下,我们将不做任何示例,因为只需关闭错误输出即可解决问题。 通常,这是通过托管来实现的,它可以在管理面板中为您提供将日志写入单独文件的功能,但是,它本身并不是限制错误输出的多余方法。

可以使用error_reporting()函数来完成。

它采用的参数包括:E_ERROR,E_WARNING,E_PARSE,E_NOTICE,E_ALL。 名称不言自明。

例如,如果使用error_reporting(E_NOTICE),则所有错误都将被隐藏,除了Notice类型的错误(例如,警告,$ _POST数组中没有数据)。
要禁用所有错误(实际上是我们需要的)的输出,您需要按以下方式使用此函数:error_reporting(0)

逻辑错误


逻辑错误是最严重的错误。 因为这些都是粗心大意的错误。 它们突然弹出,有时我们甚至不知道问题的根源在哪里。 这些是网站逻辑中的错误。

好吧,例如,您可能忘记了检查会话中是否存在授权数据以及管理面板页面之一的cookie。 因此,他们为所有用户打开了对该页面的访问权限。

在这种情况下,只有一件事可以挽救您-编写程序代码时,请考虑如何对其进行破解。

DDOS


DOS是对技术(特别是计算机)的一种攻击。 攻击旨在由于过载而禁用计算机。 DDOS的不同之处仅在于攻击涉及大量计算机。

也就是说,John打电话给他的朋友,他们一起开始向该站点发送请求。 僵尸网络与它有什么关系? 僵尸网络是许多受感染的计算机,其特点是攻击者可以在一定程度上控制其工作(启动进程等)。 它们发送的请求如此之多,以至于服务器无法承受负载,充其量只能开始非常缓慢地工作,或者拒绝了一段不确定的时间。

主机本身或Cloudflare等特殊服务可提供针对此类攻击的保护。

保护的工作原理:Cloudflare服务为您提供了自己的DNS服务器,流量将通过该DNS服务器。 在那里,通过仅对服务的所有者和开发人员已知的算法进行过滤。 之后,用户进入您的站点。 是的,当然,有服务器操作,页面生成以及其他所有功能,但是我们现在不在谈论它。
此外,谈到DDOS,您一定会提到Cloudflare也提供的IP地址阻止。

是的,所有这些都不能提供100%的保护,但是有时会增加您的站点在遭受攻击时保持稳定的机会。

信息技术部


当攻击者拦截您的数据包并对其进行欺骗时,中间人是一种攻击。 我们都听说数据通过网络以数据包的形式传输。 因此,当使用http协议时,数据以通常的而不是加密的形式传输。

例如,您给朋友写“你好”,他收到“给我钱,这是钱包”。

为了解决此问题,创建了https协议。 使用数据时,数据将被加密,John将无法对收到的流量进行任何处理。
为了获得该站点的https协议,您需要获取一个SSL证书。 好吧,还是TLS。 通常,TLS本质上是SSL接收器,因为它基于SSL 3.0。 他们的工作没有显着差异。

SSL证书免费提供相同的Cloudflare。

后门


多一点理论。 对于这种类型的攻击,可以通过多种方式实施,您只需要掌握本质即可。 后门是一种秘密攻击,脚本本身在后台执行某些操作。 大多数情况下,这些是从种子下载的插件或WordPress主题。 插件/主题本身可以很好地工作,但是添加到插件/主题代码中的脚本的某些部分会秘密地执行某些操作。 例如,相同的垃圾邮件。 这是所有不希望从torrent下载文件的警告的原因。

总结


是的,当然,这不是全部攻击范围。 但是,这些知识已经可以提高项目的安全性。

Source: https://habr.com/ru/post/zh-CN451420/


All Articles