PHP Security / Form Processing / Cross-Site Request Forgeries Fri, Jun 8. 2007
Cross-Site Request Forgeries
跨站点请求伪造
Despite the similarities in name, cross-site request forgeries (CSRF) are an almost opposite style of attack. Whereas XSS attacks exploit the trust a user has in a Web site, CSRF attacks exploit the trust a Web site has in a user. CSRF attacks are more dangerous, less popular (which means fewer resources for developers), and more difficult to defend against than XSS attacks.
虽然和跨站点脚本攻击名字很相似,但是跨站点请求伪造是完全不同的攻击方法。 XSS 攻击利用的是用户对网站的信任,CSRF 攻击利用的是网站对用户的信任。 CSRF 攻击更加危险,更加不常见(也意味着对开发着可用的资源更少), 和 XSS 攻击比起来也更加难以防范。
CSRF attacks have the following characteristics:
CSRF 攻击有着如下的特征:
-
Exploit the trust that a site has for a particular user.
Many users may not be trusted, but it is common for Web applications to offer users certain privileges upon logging in to the application. Users with these heightened privileges are potential victims (unknowing accomplices, in fact).
-
利用了站点对特定用户的信任。
对于 Web 程序来说,很常见的一个现象就是大部分用户都不是可信的, 只有通过登陆的用户才有更高级权限。这些有着更高权限的用户都是潜在的受害者 (事实上,他们都不知道自己是同谋)。
-
Generally involve Web sites that rely on the identity of the users.
It is typical for the identity of a user to carry a lot of weight. With a secure session management mechanism, which is a challenge in itself, CSRF attacks can still be successful. In fact, it is in these types of environments where CSRF attacks are most potent.
-
通常都包含那些依赖用户身份的站点。
让用户身份承担重要的作用是很典型的。即使在有安全的 session 管理机制的情况下, CSRF 攻击还是很容易成功的,况且这个机制本身还有疑问呢。事实上, 正是在这种环境下 CSRF 攻击才最有说服力。
-
Perform HTTP requests of the attacker's choosing.
CSRF attacks include all attacks that involve the attacker forging an HTTP request from another user (in essence, tricking a user into sending an HTTP request on the attacker's behalf). There are a few different techniques that can be used to accomplish this, and I will show some examples of one specific technique.
-
执行攻击者所选择的 HTTP 请求。
所有类型的,由攻击者把 HTTP 请求伪装成另外一个用户的,攻击都是 CSRF 攻击 (其实质是,欺骗用户按照攻击者的意愿发送 HTTP 请求)。 要执行这个攻击有几种技术可用,我会用一些例子来说明其中一个特别的技术。
Because CSRF attacks involve the forging of HTTP requests, it is important to first gain a basic level of familiarity with HTTP.
因为 CSRF 攻击包含了 HTTP 请求伪造,所以当务之急是初步熟悉 HTTP。
A Web browser is an HTTP client, and a Web server is an HTTP server. Clients initiate a transaction by sending a request, and the server completes the transaction by sending a response. A typical HTTP request is as follows:
Web 浏览器就是一个 HTTP 客户端,Web 服务器也就是一个 HTTP 服务器。 客户端通过发送请求来发起一个事务,在服务器发送响应结果后事务结束。 下面是一个典型的 HTTP 请求:
- GET / HTTP/1.1
- Host: example.org
- User-Agent: Mozilla/5.0 Gecko
- Accept: text/xml, image/png, image/jpeg, image/gif, /*
The first line is called the request line, and it contains the request method, request URL (a relative URL is used), and HTTP version. The other lines are HTTP headers, and each header name is followed by a colon, a space, and the value.
第一行被称作请求行,这一行包含了请求的方式、请求的 URL(这里使用的是一个相对 URL)和 HTTP 版本号。 其他的行都是 HTTP 头信息,每一个 HTTP 头的名字后面紧跟着一个冒号、一个空格和对应的值。
You might be familiar with accessing this information in PHP. For example, the following code can be used to rebuild this particular HTTP request:
你应该已经熟知如何用 PHP 来访问这些信息了。 例如,下面的代码可以被用来重建上面这个特定的 HTTP 请求:
[geshi lang=php in=y][/geshi]An example response to the previous request is as follows:
如下是一个响应上面的请求的应答的例子:
- HTTP/1.1 200 OK
- Content-Type: text/html
- Content-Length: 57
- <img src="http://example.org/image.png" />
- </html>
The content of a response is what you see when you view source in a browser.
The img tag in this particular response alerts the browser to the fact that another
resource (an image) is necessary to properly render the page. The browser
requests this resource as it would any other, and the following is an example of
such a request:
你在浏览器里面察看源代码的时候所看到的就是响应的内容。
在这个特定的响应里的 img 标签,告诉浏览器要正确的生成这个页面,还需要请求另外一个资源(这个图片)。
浏览器和请求其他资源一样请求这个资源,下面就是这个请求的例子:
- GET /image.png HTTP/1.1
- Host: example.org
- User-Agent: Mozilla/5.0 Gecko
- Accept: text/xml, image/png, image/jpeg, image/gif, /*
This is worthy of attention. The browser requests the URL specified in the src
attribute of the img tag just as if the user had manually navigated there. The
browser has no way to specifically indicate that it expects an image.
这一段值得注意一下。浏览器请求在 img 标签的 src 属性里指定的 URL,
就如同用户手工定向到那里。浏览器无法明确指出请求的是一个图片。
Combine this with what you've learned about forms, and then consider a URL similar to the following:
把这些和你以前学到的关于表单的知识结合起来,然后看一个和下面累死的 URL:
http://stocks.example.org/buy.php?symbol=SCOX&quantity=1000
A form submission that uses the GET method can potentially be indistinguishable
from an image request – both could be requests for the same URL. If
register_globals is enabled, the method of the form isn't even important
(unless the developer still uses $_POST and the like). Hopefully the dangers are
already becoming clear.
很可能无法把一个使用 GET 方式提交的表单和一个图片请求区分开来——因为这两者都可以以同样的 URL 发送请求。
如果启用了 register_globals 选项,标单提交的方法也都不重要了
(除非开发者还在使用 $_POST 或者类似的变量)。看起来危险已经变清晰了。
Another characteristic that makes CSRF so powerful is that any cookies
pertaining to a URL are included in the request for that URL. A user who has an
established relationship with stocks.example.org (such as being logged in)
can potentially buy 1000 shares of SCOX by visiting a page with an img tag that
specifies the URL in the previous example.
很多附属于一个 URL 的 cookie 都被对那个 URL 的请求所包含,这是另外一个让 CSRF 如此危险的特征。
一个和 stocks.example.org 建立了连接的用户(例如登陆后),
可以通过访问一个页面来买 1000 股 SCOX 股票,这个页面需要有一个 img 标签,
而这个标签指定要访问上面例子中的的 URL。
Consider the following form located (hypothetically) at
http://stocks.example.org/form.html:
看下面这个(假设)位于 http://stocks.example.org/form.html 的表单:
If the user enters SCOX for the symbol, 1000 as the quantity, and submits the
form, the request that is sent by the browser is similar to the following:
如果用户在 symbol 框里面输入 SCOX,在 quantity 框输入 1000,然后提交这个表单,
浏览器会发出和下面相似的请求:
- GET /buy.php?symbol=SCOX&quantity=1000 HTTP/1.1
- Host: stocks.example.org
- User-Agent: Mozilla/5.0 Gecko
- Accept: text/xml, image/png, image/jpeg, image/gif, */*
- Cookie: PHPSESSID=1234
I include a
Cookieheader in this example to illustrate the application using a cookie for the session identifier. If animgtag references the same URL, the same cookie will be sent in the request for that URL, and the server processing the request will be unable to distinguish this from an actual order.我在这个例子的头信息里面包含了一个
Cookie,以说明程序用 cookie 作为会话标示符。 如果一个img标签引用了同样的 URL,那么在对那个 URL 的请求中会发送出去同样的 cookie, 因此,处理这个请求的服务器就无法把这个表单和真正的订单区分开了。There are a few things you can do to protect your applications against CSRF:
有一些你能够用来保护你的程序不受 CSRF 攻击的方法:
-
Use
POSTrather thanGETin forms.Specify
POSTin themethodattribute of your forms. Of course, this isn't appropriate for all of your forms, but it is appropriate when a form is performing an action, such as buying stocks. In fact, the HTTP specification requires that GET be considered safe. -
使用
POST而不是GET方法提交表单。在表单的
method属性里面指定使用POST方法。 当然这不一定对所有的表单都适用,但是当表单要完成一个类似买股票的动作的时候就很适用, 事实上,HTTP 协议规范要求 GET 可以被认识是安全的。 -
Use
$_POSTrather than rely onregister_globals.Using the
POSTmethod for form submissions is useless if you rely onregister_globalsand reference form variables like$symboland$quantity. It is also useless if you use$_REQUEST. -
使用
$_POST变量而不要依赖register_globals选项。如果你依赖于
register_globals选项,并且使用类似$symbol和$quantity这样的形式引用表单变量,那么用POST方法提交表单的方法来避免攻击是徒劳的。如果你使用了$_REQUEST变量, 那么同样还是徒劳的。 -
Do not focus on convenience.
While it seems desirable to make a user's experience as convenient as possible, too much convenience can have serious consequences. While "one-click" approaches can be made very secure, a simple implementation is likely to be vulnerable to CSRF.
-
不要把注意力都集中在便利性上。
虽然说让用户体验尽可能的方便看起来好像很不错,但是过分的便利性会导致严重的后果。 尽管“一次点击”能做的很安全,但是简单的实现很可能受到 CSRF 攻击。
-
Force the use of your own forms.
The biggest problem with CSRF is having requests that look like form submissions but aren't. If a user has not requested the page with the form, should you assume a request that looks like a submission of that form to be legitimate and intended?
-
注意表单的使用。
CSRF 最大的文件就是让请求看起来像是一个表单提交,虽然实际上不是。 如果用户没有通过表单请求相应的页面, 那么对于一个好像是从表单提交过来的请求,你还假设它是合法的、预期的吗?
Now we can write an even more secure message board:
现在我们可以写出来一个更安全的公告板了:- <?php
- ?>
- <form method="post">
- <input type="hidden" name="token" value="<?php echo
- $token; ?>" />
- <input type="text" name="message"><br />
- <input type="submit">
- </form>
- <?php
- {
- {
- }
- }
- ?>
This message board still has a few security vulnerabilities. Can you spot them?
这个公告板还有几个安全漏洞。你能找出来吗?
Time is extremely predictable. Using the MD5 digest of a timestamp is a poor excuse for a random number. Better functions include
uniqid()andrand().时间是可以准确预言的。所以使用时间戳的 MD5 散列来做随机数是很糟糕的办法。
uniqid()和rand()是更好的生成随机数的函数。More importantly, it is trivial for an attacker to obtain a valid token. By simply visiting this page, a valid token is generated and included in the source. With a valid token, the attack is as simple as before the token requirement was added.
更重要的,攻击者来可以很容易的获得到一个合法的令牌。 访问这个页面的时候,生成的那个合法的另外就包含在页面源代码里面。 如果有合法和的令牌,进行攻击就和增加令牌需求以前一样简单了。
Here is an improved message board:
这是一个改进版的公告板:
- <?php
- {
- if ($_POST['token'] == $_SESSION['token'])
- {
- }
- }
- $_SESSION['token'] = $token;
- ?>
- <form method="post">
- <input type="hidden" name="token" value="<?php echo
- $token; ?>" />
- <input type="text" name="message"><br />
- <input type="submit">
- </form>
Is this one completely secure?
这个版本是不是绝对安全了呢?
-
About Myself
职业:无业游民,兼职代码工人,有资格申请南京低保
流窜:石家庄 » 南京
信箱:nulltao@gmail.com
兴趣:C、PHP、Java、美食、睡懒觉、胡思乱想
Quicksearch
Calendar
|
|
November '08 |
|
||||
| Su | Mo | Tu | We | Th | Fr | Sa |
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | ||||||
Syndicate This Blog
Categories
Link List
My del.icio.us
- 在 PHP 中养成 7 个面向对象的好习惯
- 简易目标设定:让你更有效率 - 译言翻译
- 兵王 ,兵王 全集,漠北狼兵王
- Seven habits for writing secure PHP applications
- 成为一个不折不扣的时间管理专家 - 中国成功网 - SupeSite/X-Space官方站 - Powered by X-Space
- alphaWorks : IBM Page Detailer : Download
- 校内网 - 浏览日志 - 献给不会炒菜的80后们!!!呵呵
- 三步稳固好习惯 - 译言翻译
- 关于犬科动物的一切
- deviantART: where ART meets application!
Show tagged entries
© 2007 nullTao - 净空无道 - Blog | Main site | Contact me | RSS | Back to top
Powered by Serendipity | Design by Andreas Viklund | Serendipity Template by Carl
