web应用程序安全性测试_保护Web应用程序安全的8种做法

web应用程序安全性测试

When it comes to application security, in addition to securing your hardware and platform, you also need to write your code securely. This article will explain how to keep your application secure and less vulnerable to hacking. The following are the best habits that a programmer can develop in order to protect his or her application from attack:

关于应用程序安全性,除了保护硬件和平台之外,还需要安全地编写代码。 本文将说明如何确保您的应用程序安全并减少黑客攻击的可能性。 以下是程序员可以养成的最佳习惯,以保护其应用程序免受攻击:

  • Input data validation

    输入数据验证
  • Guarding against XSS attacks

    防范XSS攻击
  • Guarding against CSRF attacks

    防范CSRF攻击
  • Preventing SQL Injection attacks

    防止SQL注入攻击
  • Protecting the file system

    保护文件系统
  • Protecting session data

    保护会话数据
  • Proper error handling

    正确的错误处理
  • Guarding included files

    保护包含的文件

输入数据验证 (Input Data Validation)

While designing your application, you should be striving to guard your app against bad input. The rule of thumb to follow is this: don’t trust user input. Although your app is intended for good people, there is always a chance that some bad user will try to attack your app by entering bad input. If you always validate and filter the incoming data, you can build a secure application.

在设计应用程序时,您应该努力防止应用程序输入错误。 遵循的经验法则是:不信任用户输入。 尽管您的应用程序是供好人使用的,但总有一些不良用户有可能通过输入错误的输入来攻击您的应用程序。 如果您始终验证和过滤传入的数据,则可以构建安全的应用程序。

Always validate data in your PHP code. If you are using JavaScript to validate user input, there is always a chance that the user might have turned off JavaScript in her browser. In this case your app will not be able to validate the input. Validating in JavaScript is okay, but to guard against these types of problems then you should re-validate the data in PHP as well too.

始终验证PHP代码中的数据。 如果您使用JavaScript验证用户输入,则总是有可能用户已关闭浏览器中JavaScript。 在这种情况下,您的应用将无法验证输入。 用JavaScript进行验证是可以的,但是要防止这些类型的问题,那么您也应该使用PHP重新验证数据。

防范XSS攻击 (Guarding Against XSS Attacks)

Cross-site scripting attack (XSS attack) is an attack based on code injection into vulnerable web pages. The danger is a result of accepting unchecked input data and showing it in the browser.

跨站点脚本攻击(XSS攻击)是一种基于将代码注入易受攻击的网页的攻击。 危险是接受未经检查的输入数据并将其显示在浏览器中的结果。

Suppose you have a comment form in your application that allows users to enter data, and on successful submission it shows all the comments. The user could possibly enter a comment that contains malicious JavaScript code in it. When the form is submitted, the data is sent to the server and stored into the database. Afterward, the comment is fetched from database and shown in the HTML page and the JavaScript code will run. The malicious JavaScript might redirect the user to a bad web page or a phishing website.

假设您的应用程序中有一个注释表单,该表单允许用户输入数据,并在成功提交后显示所有注释。 用户可能会输入其中包含恶意JavaScript代码的注释。 提交表单后,数据将发送到服务器并存储到数据库中。 然后,从数据库中获取注释并显示在HTML页面中,然后将运行JavaScript代码。 恶意JavaScript可能会将用户重定向到错误的网页或网络钓鱼网站。

To protect your application from these kinds of attacks, run the input data through strip_tags() to remove any tags present in it. When showing data in the browser, apply htmlentities()function on the data.

为了保护您的应用程序免受此类攻击,请通过strip_tags()运行输入数据以删除其中存在的所有标签。 在浏览器中显示数据时,对数据应用htmlentities()函数。

防范CSRF攻击 (Guarding Against CSRF Attacks)

In a Cross Site Request Forgery (CSRF) attack, the attacker tricks the victim into loading sensitive information or making a transaction without their knowledge. This mainly occurs in web applications that are badly coded to trigger business logic using GET requests.

在跨站点请求伪造(CSRF)攻击中,攻击者诱骗受害者加载敏感信息或在他们不知情的情况下进行交易。 这主要发生在Web应用程序中,这些Web应用程序被错误地编码以使用GET请求触发业务逻辑。

Ideally, GET requests are Idempotent in nature. Idempotency means the same page can be accessed multiple times without causing any side effects. Therefore, GET requests should be used only for accessing information and not for performing transactions.

理想情况下,GET请求本质上是幂等的。 幂等意味着同一页面可以多次访问而不会引起任何副作用。 因此,GET请求应仅用于访问信息,而不用于执行事务。

The following example shows a how a poorly coded application unknowingly supports CSRF attacks:

以下示例显示了一个编码不良的应用程序如何在不知不觉中支持CSRF攻击的情况:

<?php
if (isset($_REQUEST["name"], $_REQUEST["amount"])) {
    // process the request and transfer the amount from
    // from the logged in user to the passed name.
}

Let’s assume Bob wants to perform a CSRF attack on Alice, and constructs a URL like the following and sends it to Alice in an email:

假设Bob想要对Alice进行CSRF攻击,并构造如下所示的URL,然后通过电子邮件将其发送给Alice:

<a href="http://example.com/process.php?name=Bob&amount=1000">Visit My WebSite</a>

If Alice clicks on this link, and is logged into the website already, this request will deduct $1000 from her account and transfer it to Bob’s! Alternatively, Bob can create an image link whose src attribute points to the URL.

如果Alice单击此链接,并且已经登录到该网站,此请求将从她的帐户中扣除$ 1000并将其转移到Bob的帐户中! 另外,Bob可以创建图像链接,其src属性指向URL。

<img src="http://example.com/process.php?name=Bob&amount=1000" width="1" height="1"/>

The browser can’t display any image as expected, but it will still make the request using the URL which will make a transaction without notifying Alice.

浏览器无法显示任何图像,但仍会使用URL发出请求,该URL会在不通知Alice的情况下进行交易。

The solution is to process any function that changes the database state in POST request, and avoid using $_REQUEST. Use $_GET to retrieve GET parameters, and use $_POST to retrieve POST parameters.

解决方案是处理任何在POST请求中更改数据库状态的函数,并避免使用$_REQUEST 。 使用$_GET检索GET参数,并使用$_POST检索POST参数。

In addition, there should be a random token called a CSRF token associated with each POST request. When the user logins into his/her account, the application should generate a random token and store it in the session. Whenever any form is displayed to the user, the token should be present in the page as a hidden input field. Application logic must check for the token and ensure that it matches the token present in the session.

另外,应该有一个与每个POST请求相关联的称为CSRF令牌的随机令牌。 当用户登录其帐户时,应用程序应生成一个随机令牌并将其存储在会话中。 无论何时向用户显示任何形式,令牌都应在页面中显示为隐藏的输入字段。 应用程序逻辑必须检查令牌,并确保它与会话中存在的令牌匹配。

防止SQL注入攻击 (Preventing SQL Injection Attacks)

To perform your database queries, you should be using PDO. With parameterized queries and prepared statements, you can prevent SQL injection.

要执行数据库查询,您应该使用PDO。 使用参数化查询和准备好的语句,可以防止SQL注入。

Take a look at the following example:

看下面的例子:

<?php
$sql = "SELECT * FROM users WHERE name=:name and age=:age";
$stmt = $db->prepare($sql);
$stmt->execute(array(":name" => $name, ":age" => $age));

In the above code we provide the named parameters :name and :age to prepare(), which informs the database engine to pre-compile the query and attach the values to the named parameters later. When the call to execute() is made, the query is executed with the actual values of the named parameters. If you code this way, the attacker can’t inject malicious SQL as the query is already compiled and your database will be secure.

在上面的代码中,我们将命名参数:name:ageprepare() ,它通知数据库引擎预先编译查询,然后将值附加到命名参数。 调用execute() ,将使用命名参数的实际值执行查询。 如果以这种方式编写代码,则攻击者将无法注入恶意SQL,因为查询已被编译,并且数据库将是安全的。

保护文件系统 (Protecting the File System)

As a developer you should always write your code in such a way that none of your operations put your file system at risk. Consider the following PHP that downloads a file according to a user supplied parameter:

作为开发人员,您应该始终以这样一种方式编写代码:没有任何操作会使您的文件系统面临风险。 考虑以下PHP,该PHP根据用户提供的参数下载文件:

<?php
if (isset($_GET['filename']) {
    $filename = $_GET['filename'];
    header('Content-Type: application/x-octet-stream');
    header('Content-Transfer-Encoding: binary');
    header('Content-Disposition: attachment; filename="' . $filename . '";');
    echo file_get_contents($filename);
}

The script is very dangerous since it can serve files from any directory that is accessible to it, such as the session directory and system directories. The solution is to ensure the script does not try to access files from arbitrary directories.

该脚本非常危险,因为它可以提供任何可访问目录的文件,例如会话目录和系统目录。 解决方案是确保脚本不会尝试访问任意目录中的文件。

保护会话数据 (Protecting Session Data)

By default, session information is written to a temp directory. In the case of a shared hosting server, someone other than you can write a script and read session data easily. Therefore, you should not keep sensitive information like passwords or credit card numbers in a session.

默认情况下,会话信息被写入临时目录。 对于共享托管服务器,除您之外的其他人可以编写脚本并轻松读取会话数据。 因此,您不应在会话中保留敏感信息,例如密码或信用卡号。

A good way to guard your session data is to encrypt the information stored in the session. This does not solve the problem completely since the encrypted data is not completely safe, but at least the information is not readable. You should also consider keeping your session data stored somewhere else, such as a database. PHP provides a method called session_set_save_handler() which can be used to persist data in session in your own way.

保护会话数据的一种好方法是加密存储在会话中的信息。 由于加密的数据不是完全安全的,但是至少不能读取信息,因此不能完全解决问题。 您还应该考虑将会话数据存储在其他位置,例如数据库。 PHP提供了一种称为session_set_save_handler()的方法,该方法可用于以您自己的方式在会话中保留数据。

As of PHP 5.4 you can pass an object of type SessionHandlerInterface to session_set_save_handler(). Check out the PHP documentation to learn about implementing custom session persistence by implementing SessionHandlerInterface.

从PHP 5.4开始,您可以将SessionHandlerInterface类型的对象传递给session_set_save_handler() 。 查看PHP文档,以了解通过实现SessionHandlerInterface实现自定义会话持久性。

正确的错误处理 (Proper Error Handling)

It’s good to know about all the errors that occur while we’re developing an application, but when we make the application accessible to end users we should take care to hide the errors. If errors are shown to users, it may make our application vulnerable. So, the best approach is configuring your server differently for development and production environments.

了解我们在开发应用程序时发生的所有错误是很高兴的,但是当我们使最终用户可以访问该应用程序时,我们应该注意隐藏错误。 如果向用户显示错误,则可能使我们的应用程序容易受到攻击。 因此,最好的方法是针对开发和生产环境对服务器进行不同的配置。

In production mode we need to turn off display_errors and display_start_up_errors settings. error_reporting and log_errors should be on so that we can log errors while hiding those from end users.

在生产模式下,我们需要关闭display_errorsdisplay_start_up_errors设置。 error_reportinglog_errors应该打开,这样我们就可以记录错误,同时向最终用户隐藏错误。

You can use set_error_handler to define custom error handlers. However, it has limitations. The custom error handler bypasses the standard error handling mechanism of PHP. It cannot catch errors like E_CORE_ERROR, E_STRICT or E_COMPILER_ERROR in the same file the error handler is defined in. Furthermore, it will fail to handle errors that might occur within the handler itself.

您可以使用set_error_handler定义自定义错误处理程序。 但是,它有局限性。 自定义错误处理程序会绕过PHP的标准错误处理机制。 它不能在定义错误处理程序的同一文件中捕获诸如E_CORE_ERRORE_STRICTE_COMPILER_ERROR之类的错误。此外,它将无法处理可能在处理程序内部发生的错误。

To handle errors elegantly you should perform exception handling through try/catch blocks. Exceptions are represented by the Exception class and its subclasses. If any error occurs inside the try block you can throw an exception and process it in the catch block.

为了优雅地处理错误,您应该通过try / catch块执行异常处理。 异常由Exception类及其子类表示。 如果try块内发生任何错误,则可以引发异常并在catch块中对其进行处理。

保护包含的文件 (Guarding Included Files)

PHP scripts often include other PHP files that contain code for things like connecting to a database, etc. Some developers give the included files an extension like .inc. Files with this extension are not parsed by PHP by default if called directly and will be served as plain text to the users. If an attacker directly accesses the include file that contains database credentials, he now has access to all of your application’s data. Always use the .php extension for included code files and keep them outside of directories directly accessible to users.

PHP脚本通常包括其他PHP文件,这些文件包含诸如连接数据库等之类的代码。某些开发人员为所包含的文件提供扩展名,例如.inc。 默认情况下,如果直接调用此扩展名的文件,则PHP不会对其进行解析,这些文件将作为纯文本提供给用户。 如果攻击者直接访问包含数据库凭据的包含文件,则他现在可以访问您应用程序的所有数据。 始终对包含的代码文件使用.php扩展名,并将其保留在用户直接访问的目录之外。

摘要 (Summary)

By keeping the above 8 points in mind it’s possible to secure a PHP application to a great extent. The best piece of advice by far is don’t trust user input, but also be sure to guard your file system and database as well.

通过牢记以上8点,可以在很大程度上保护PHP应用程序。 到目前为止,最好的建议是不要信任用户的输入,但也要确保保护您的文件系统和数据库。

Image via Fotolia

图片来自Fotolia

翻译自: https://www.sitepoint.com/8-practices-to-secure-your-web-app/

web应用程序安全性测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值