<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>0x50sec.org &#187; nginx</title>
	<atom:link href="http://www.0x50sec.org/tag/nginx/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.0x50sec.org</link>
	<description>Focus on web security!</description>
	<lastBuildDate>Fri, 13 Jan 2012 09:23:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Possible Arbitrary Code Execution with Null Bytes, PHP, and Old Versions of nginx</title>
		<link>http://www.0x50sec.org/possible-arbitrary-code-execution-with-null-bytes-php-and-old-versions-of-nginx/</link>
		<comments>http://www.0x50sec.org/possible-arbitrary-code-execution-with-null-bytes-php-and-old-versions-of-nginx/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 13:27:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[漏洞代码]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Code Execution]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[Null Bytes]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.0x50sec.org/?p=1160</guid>
		<description><![CDATA[from：https://nealpoole.com/blog/2011/07/possible-arbitrary-code-execution-with-null-bytes-php-and-old-versions-of-nginx/ After publishing my previous blog post on PHP, nginx configuration, and potential arbitrary code execution, I came across a separate null-byte injection vulnerability in older versions of nginx (0.5.*, 0.6.*, 0.7 &#60;= 0.7.65, 0.8 &#60;= 0.8.37). By taking advantage of this vulnerability, an attacker can cause a server that uses PHP-FastCGI to execute any [...]]]></description>
			<content:encoded><![CDATA[<p>from：https://nealpoole.com/blog/2011/07/possible-arbitrary-code-execution-with-null-bytes-php-and-old-versions-of-nginx/</p>
<p>After publishing my previous blog post on PHP, nginx configuration, and potential arbitrary code execution,  I came across a separate null-byte injection vulnerability in older  versions of nginx (0.5.*, 0.6.*, 0.7 &lt;= 0.7.65, 0.8 &lt;= 0.8.37). By  taking advantage of this vulnerability, an attacker can cause a server  that uses PHP-FastCGI to execute any publicly accessible file on the  server as PHP.</p>
<p>In vulnerable versions of nginx, null bytes are allowed in URIs by default (their presence is indicated via a variable named <tt>zero_in_uri</tt> defined in <tt>ngx_http_request.h</tt>).  Individual modules have the ability to opt-out of handling URIs with  null bytes. However, not all of them do; in particular, the FastCGI  module does not.</p>
<p>The attack itself is simple: a malicious user who makes a request to http://example.com/file.ext%00.php causes <tt>file.ext</tt> to be parsed as PHP. If an attacker can control the contents of a file  served up by nginx (ie: using an avatar upload form) the result is  arbitrary code execution. This vulnerability <strong><em>can not</em></strong> be mitigated by nginx configuration settings like <tt>try_files</tt> or PHP configuration settings like <tt>cgi.fix_pathinfo</tt>:  the only defense is to upgrade to a newer version of nginx or to  explicitly block potentially malicious requests to directories  containing user-controlled content.<span id="more-1160"></span></p>
<div>
<div id="highlighter_467010">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</td>
<td>
<div>
<div><code># This location block will prevent an attacker from exploiting</code></div>
<div><code># this vulnerability using files in the 'uploads' or 'other_uploads' directory</code></div>
<div><code>location ~ ^/(uploads|other_uploads)/.*.php$</code></div>
<div><code>{</code></div>
<div><code> </code><code>deny all;</code></div>
<div><code>}</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Although the affected versions of nginx are relatively old (0.7.66  was released June 7th, 2010, 0.8.38 was released May 24th 2010), no  mention of the change appears in the release notes. As a result,  administrators may be running vulnerable servers without realizing their  risk. I discovered a couple places where vulnerable packages were being  distributed:</p>
<ol>
<li>Ubuntu Lucid Lynx (Ubuntu&#8217;s current LTS offering) and Hardy Heron  (via both the hardy and hardy-backports repositories) provided  vulnerable versions of nginx via apt-get. The lucid and hardy packages  have been updated: hardy-backports is awaiting approval. <sup><a href="https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/783508">[1]</a> <a href="https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/803720">[2]</a></sup></li>
<li>Fedora provides a vulnerable version in its EPEL-4 repository. At this time, an updated package has not been released.</li>
</ol>
<p>I sent several emails to igor@sysoev.ru regarding the vulnerability. I  sent the first on June 24th and I sent followups on July 4th, July  20th, and August 2nd. I received the following reply to my August 2nd  email:</p>
<blockquote><p>Thank you for report.</p>
<p>I do not consider this as nginx security issue since every application<br />
should validate its input data, so nginx passed the data to application.<br />
Also this is PHP installation issue where scripts and user uploaded<br />
data are not separated. This issue was discussed several times on mailing<br />
list.</p>
<p>At some point I&#8217;ve decided that zero byte in URI should not appear<br />
in any encoding, operating system, etc., and just makes more problems<br />
than helps. So I have remove zero byte test.</p></blockquote>
<p>For anyone who&#8217;s curious, the changes can be found at r3528 from svn://svn.nginx.org.  At that time, it appears trunk corresponded to nginx 0.8: r3599 merged  r3528 into the nginx 0.7 branch. The corresponding commit message is  &#8220;remove r-&gt;zero_in_uri.&#8221; I&#8217;ve reproduced the output of <tt>svn diff</tt> below:</p>
<div>
<div><code>Index: src/http/ngx_http_request.h</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/ngx_http_request.h (revision 3527)</code></div>
<div><code>+++ src/http/ngx_http_request.h (revision 3528)</code></div>
<div><code>@@ -56,7 +56,7 @@</code></div>
<div><code> </code><code>#define NGX_HTTP_PARSE_INVALID_HEADER      13</code></div>
<div><code>-#define NGX_HTTP_ZERO_IN_URI               1</code></div>
<div><code>+/* unused                                  1 */</code></div>
<div><code> </code><code>#define NGX_HTTP_SUBREQUEST_IN_MEMORY      2</code></div>
<div><code> </code><code>#define NGX_HTTP_SUBREQUEST_WAITED         4</code></div>
<div><code> </code><code>#define NGX_HTTP_LOG_UNSAFE                8</code></div>
<div><code>@@ -435,9 +435,6 @@</code></div>
<div><code> </code><code>/* URI with "+" */</code></div>
<div><code> </code><code>unsigned                          plus_in_uri:1;</code></div>
<div><code>-    /* URI with "\0" or "%00" */</code></div>
<div><code>-    unsigned                          zero_in_uri:1;</code></div>
<div><code>-</code></div>
<div><code> </code><code>unsigned                          invalid_header:1;</code></div>
<div><code> </code><code>unsigned                          valid_location:1;</code></div>
<div><code>Index: src/http/ngx_http_core_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/ngx_http_core_module.c (revision 3527)</code></div>
<div><code>+++ src/http/ngx_http_core_module.c (revision 3528)</code></div>
<div><code>@@ -1341,7 +1341,7 @@</code></div>
<div><code> </code><code>/* no content handler was found */</code></div>
<div><code>-    if (r-&gt;uri.data[r-&gt;uri.len - 1] == '/' &amp;&amp; !r-&gt;zero_in_uri) {</code></div>
<div><code>+    if (r-&gt;uri.data[r-&gt;uri.len - 1] == '/') {</code></div>
<div><code> </code><code>if (ngx_http_map_uri_to_path(r, &amp;path, &amp;root, 0) != NULL) {</code></div>
<div><code> </code><code>ngx_log_error(NGX_LOG_ERR, r-&gt;connection-&gt;log, 0,</code></div>
<div><code>@@ -2104,7 +2104,6 @@</code></div>
<div><code> </code><code>ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c-&gt;log, 0,</code></div>
<div><code> </code><code>"http subrequest \"%V?%V\"", uri, &amp;sr-&gt;args);</code></div>
<div><code>-    sr-&gt;zero_in_uri = (flags &amp; NGX_HTTP_ZERO_IN_URI) != 0;</code></div>
<div><code> </code><code>sr-&gt;subrequest_in_memory = (flags &amp; NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;</code></div>
<div><code> </code><code>sr-&gt;waited = (flags &amp; NGX_HTTP_SUBREQUEST_WAITED) != 0;</code></div>
<div><code>Index: src/http/ngx_http_special_response.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/ngx_http_special_response.c    (revision 3527)</code></div>
<div><code>+++ src/http/ngx_http_special_response.c    (revision 3528)</code></div>
<div><code>@@ -517,8 +517,6 @@</code></div>
<div><code> </code><code>r-&gt;err_status = overwrite;</code></div>
<div><code>-    r-&gt;zero_in_uri = 0;</code></div>
<div><code>-</code></div>
<div><code> </code><code>if (ngx_http_complex_value(r, &amp;err_page-&gt;value, &amp;uri) != NGX_OK) {</code></div>
<div><code> </code><code>return NGX_ERROR;</code></div>
<div><code> </code><code>}</code></div>
<div><code>Index: src/http/ngx_http_upstream.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/ngx_http_upstream.c    (revision 3527)</code></div>
<div><code>+++ src/http/ngx_http_upstream.c    (revision 3528)</code></div>
<div><code>@@ -1815,10 +1815,6 @@</code></div>
<div><code> </code><code>return NGX_DONE;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-        if (flags &amp; NGX_HTTP_ZERO_IN_URI) {</code></div>
<div><code>-            r-&gt;zero_in_uri = 1;</code></div>
<div><code>-        }</code></div>
<div><code>-</code></div>
<div><code> </code><code>if (r-&gt;method != NGX_HTTP_HEAD) {</code></div>
<div><code> </code><code>r-&gt;method = NGX_HTTP_GET;</code></div>
<div><code> </code><code>}</code></div>
<div><code>Index: src/http/ngx_http_parse.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/ngx_http_parse.c   (revision 3527)</code></div>
<div><code>+++ src/http/ngx_http_parse.c   (revision 3528)</code></div>
<div><code>@@ -438,8 +438,7 @@</code></div>
<div><code> </code><code>r-&gt;plus_in_uri = 1;</code></div>
<div><code> </code><code>break;</code></div>
<div><code> </code><code>case '\0':</code></div>
<div><code>-                r-&gt;zero_in_uri = 1;</code></div>
<div><code>-                break;</code></div>
<div><code>+                return NGX_HTTP_PARSE_INVALID_REQUEST;</code></div>
<div><code> </code><code>default:</code></div>
<div><code> </code><code>state = sw_check_uri;</code></div>
<div><code> </code><code>break;</code></div>
<div><code>@@ -496,8 +495,7 @@</code></div>
<div><code> </code><code>r-&gt;plus_in_uri = 1;</code></div>
<div><code> </code><code>break;</code></div>
<div><code> </code><code>case '\0':</code></div>
<div><code>-                r-&gt;zero_in_uri = 1;</code></div>
<div><code>-                break;</code></div>
<div><code>+                return NGX_HTTP_PARSE_INVALID_REQUEST;</code></div>
<div><code> </code><code>}</code></div>
<div><code> </code><code>break;</code></div>
<div><code>@@ -526,8 +524,7 @@</code></div>
<div><code> </code><code>r-&gt;complex_uri = 1;</code></div>
<div><code> </code><code>break;</code></div>
<div><code> </code><code>case '\0':</code></div>
<div><code>-                r-&gt;zero_in_uri = 1;</code></div>
<div><code>-                break;</code></div>
<div><code>+                return NGX_HTTP_PARSE_INVALID_REQUEST;</code></div>
<div><code> </code><code>}</code></div>
<div><code> </code><code>break;</code></div>
<div><code>@@ -1202,7 +1199,7 @@</code></div>
<div><code> </code><code>ch = *p++;</code></div>
<div><code> </code><code>} else if (ch == '\0') {</code></div>
<div><code>-                    r-&gt;zero_in_uri = 1;</code></div>
<div><code>+                    return NGX_HTTP_PARSE_INVALID_REQUEST;</code></div>
<div><code> </code><code>}</code></div>
<div><code> </code><code>state = quoted_state;</code></div>
<div><code>@@ -1304,8 +1301,7 @@</code></div>
<div><code> </code><code>}</code></div>
<div><code> </code><code>if (ch == '\0') {</code></div>
<div><code>-            *flags |= NGX_HTTP_ZERO_IN_URI;</code></div>
<div><code>-            continue;</code></div>
<div><code>+            goto unsafe;</code></div>
<div><code> </code><code>}</code></div>
<div><code> </code><code>if (ngx_path_separator(ch) &amp;&amp; len &gt; 2) {</code></div>
<div><code>@@ -1449,34 +1445,19 @@</code></div>
<div><code> </code><code>void</code></div>
<div><code> </code><code>ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args)</code></div>
<div><code> </code><code>{</code></div>
<div><code>-    u_char  ch, *p, *last;</code></div>
<div><code>+    u_char  *p, *last;</code></div>
<div><code>-    p = uri-&gt;data;</code></div>
<div><code>+    last = uri-&gt;data + uri-&gt;len;</code></div>
<div><code>-    last = p + uri-&gt;len;</code></div>
<div><code>+    p = ngx_strlchr(uri-&gt;data, last, '?');</code></div>
<div><code>-    args-&gt;len = 0;</code></div>
<div><code>+    if (p) {</code></div>
<div><code>+        uri-&gt;len = p - uri-&gt;data;</code></div>
<div><code>+        p++;</code></div>
<div><code>+        args-&gt;len = last - p;</code></div>
<div><code>+        args-&gt;data = p;</code></div>
<div><code>-    while (p &lt; last) {</code></div>
<div><code>-</code></div>
<div><code>-        ch = *p++;</code></div>
<div><code>-</code></div>
<div><code>-        if (ch == '?') {</code></div>
<div><code>-            args-&gt;len = last - p;</code></div>
<div><code>-            args-&gt;data = p;</code></div>
<div><code>-</code></div>
<div><code>-            uri-&gt;len = p - 1 - uri-&gt;data;</code></div>
<div><code>-</code></div>
<div><code>-            if (ngx_strlchr(p, last, '\0') != NULL) {</code></div>
<div><code>-                r-&gt;zero_in_uri = 1;</code></div>
<div><code>-            }</code></div>
<div><code>-</code></div>
<div><code>-            return;</code></div>
<div><code>-        }</code></div>
<div><code>-</code></div>
<div><code>-        if (ch == '\0') {</code></div>
<div><code>-            r-&gt;zero_in_uri = 1;</code></div>
<div><code>-            continue;</code></div>
<div><code>-        }</code></div>
<div><code>+    } else {</code></div>
<div><code>+        args-&gt;len = 0;</code></div>
<div><code> </code><code>}</code></div>
<div><code> </code><code>}</code></div>
<div><code>Index: src/http/modules/ngx_http_gzip_static_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_gzip_static_module.c  (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_gzip_static_module.c  (revision 3528)</code></div>
<div><code>@@ -89,10 +89,6 @@</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);</code></div>
<div><code> </code><code>if (!gzcf-&gt;enable) {</code></div>
<div><code>Index: src/http/modules/ngx_http_index_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_index_module.c    (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_index_module.c    (revision 3528)</code></div>
<div><code>@@ -116,10 +116,6 @@</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);</code></div>
<div><code> </code><code>clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);</code></div>
<div><code>Index: src/http/modules/ngx_http_random_index_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_random_index_module.c (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_random_index_module.c (revision 3528)</code></div>
<div><code>@@ -86,10 +86,6 @@</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>if (!(r-&gt;method &amp; (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>Index: src/http/modules/ngx_http_dav_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_dav_module.c  (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_dav_module.c  (revision 3528)</code></div>
<div><code>@@ -146,10 +146,6 @@</code></div>
<div><code> </code><code>ngx_int_t                 rc;</code></div>
<div><code> </code><code>ngx_http_dav_loc_conf_t  *dlcf;</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);</code></div>
<div><code> </code><code>if (!(r-&gt;method &amp; dlcf-&gt;methods)) {</code></div>
<div><code>Index: src/http/modules/ngx_http_flv_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_flv_module.c  (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_flv_module.c  (revision 3528)</code></div>
<div><code>@@ -80,10 +80,6 @@</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>rc = ngx_http_discard_request_body(r);</code></div>
<div><code> </code><code>if (rc != NGX_OK) {</code></div>
<div><code>Index: src/http/modules/ngx_http_static_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_static_module.c   (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_static_module.c   (revision 3528)</code></div>
<div><code>@@ -66,10 +66,6 @@</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>log = r-&gt;connection-&gt;log;</code></div>
<div><code> </code><code>/*</code></div>
<div><code>Index: src/http/modules/ngx_http_autoindex_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/ngx_http_autoindex_module.c    (revision 3527)</code></div>
<div><code>+++ src/http/modules/ngx_http_autoindex_module.c    (revision 3528)</code></div>
<div><code>@@ -160,10 +160,6 @@</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_DECLINED;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>if (!(r-&gt;method &amp; (NGX_HTTP_GET|NGX_HTTP_HEAD))) {</code></div>
<div><code> </code><code>return NGX_DECLINED;</code></div>
<div><code> </code><code>}</code></div>
<div><code>Index: src/http/modules/perl/ngx_http_perl_module.c</code></div>
<div><code>===================================================================</code></div>
<div><code>--- src/http/modules/perl/ngx_http_perl_module.c    (revision 3527)</code></div>
<div><code>+++ src/http/modules/perl/ngx_http_perl_module.c    (revision 3528)</code></div>
<div><code>@@ -168,10 +168,6 @@</code></div>
<div><code> </code><code>static ngx_int_t</code></div>
<div><code> </code><code>ngx_http_perl_handler(ngx_http_request_t *r)</code></div>
<div><code> </code><code>{</code></div>
<div><code>-    if (r-&gt;zero_in_uri) {</code></div>
<div><code>-        return NGX_HTTP_NOT_FOUND;</code></div>
<div><code>-    }</code></div>
<div><code>-</code></div>
<div><code> </code><code>r-&gt;main-&gt;count++;</code></div>
<div><code> </code><code>ngx_http_perl_handle_request(r);</code></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.0x50sec.org/possible-arbitrary-code-execution-with-null-bytes-php-and-old-versions-of-nginx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nginx文件类型错误解析漏洞</title>
		<link>http://www.0x50sec.org/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e/</link>
		<comments>http://www.0x50sec.org/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e/#comments</comments>
		<pubDate>Mon, 24 May 2010 03:46:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[漏洞代码]]></category>
		<category><![CDATA[80sec]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[解析漏洞]]></category>

		<guid isPermaLink="false">http://www.0x50sec.org/?p=901</guid>
		<description><![CDATA[nginx文件类型错误解析漏洞 来源:80sec.com 原文链接:http://www.80sec.com/nginx-securit.html 漏洞介绍：nginx是一款高性能的web服务器，使用非常广泛，其不仅经常被用作反向代理，也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题，默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析，这将导致严重的安全问题，使得恶意的攻击者可能攻陷支持php的nginx服务器。 漏洞分析：nginx默认以cgi的方式支持php的运行，譬如在配置文件当中可以以 location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; } 的方式支持对php的解析，location对请求进行选择的时候会使用URI环境变量进行选择，其中传递到后端Fastcgi的关键变量 SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定，而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的，这里就是产生问题的点。而为了较好的支持PATH_INFO的提取，在PHP 的配置选项里存在cgi.fix_pathinfo选项，其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。 那么假设存在一个http://www.80sec.com/80sec.jpg，我们以如下的方式去访问 http://www.80sec.com/80sec.jpg/80sec.php 将会得到一个URI /80sec.jpg/80sec.php 经过location指令，该请求将会交给后端的fastcgi处理，nginx为其设置环境变量SCRIPT_FILENAME，内容为 /scripts/80sec.jpg/80sec.php 而在其他的webserver如lighttpd当中，我们发现其中的SCRIPT_FILENAME被正确的设置为 /scripts/80sec.jpg 所以不存在此问题。 后端的fastcgi在接受到该选项时，会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理，一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用，所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字，查找的方式也是查看文件是否存在，这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为 /scripts/80sec.jpg和80sec.php 最后，以/scripts/80sec.jpg作为此次请求需要执行的脚本，攻击者就可以实现让nginx以php来解析任何类型的文件了。 POC： 访问一个nginx来支持php的站点，在一个任何资源的文件如robots.txt后面加上/80sec.php，这个时候你可以看到如下的区别： 访问http://www.80sec.com/robots.txt HTTP/1.1 200 OK Server: nginx/0.6.32 Date: Thu, 20 May 2010 10:05:30 GMT Content-Type: text/plain Content-Length: 18 [...]]]></description>
			<content:encoded><![CDATA[<p>nginx文件类型错误解析漏洞<br />
来源:80sec.com<br />
原文链接:<a href="http://www.80sec.com/nginx-securit.html">http://www.80sec.com/nginx-securit.html</a></p>
<p>漏洞介绍：nginx是一款高性能的web服务器，使用非常广泛，其不仅经常被用作反向代理，也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题，默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析，这将导致严重的安全问题，使得恶意的攻击者可能攻陷支持php的nginx服务器。</p>
<p>漏洞分析：nginx默认以cgi的方式支持php的运行，譬如在配置文件当中可以以<br />
<span id="more-901"></span><br />
location ~ \.php$ {<br />
root html;<br />
fastcgi_pass 127.0.0.1:9000;<br />
fastcgi_index index.php;<br />
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;<br />
include fastcgi_params;<br />
}</p>
<p>的方式支持对php的解析，location对请求进行选择的时候会使用URI环境变量进行选择，其中传递到后端Fastcgi的关键变量 SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定，而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的，这里就是产生问题的点。而为了较好的支持PATH_INFO的提取，在PHP 的配置选项里存在cgi.fix_pathinfo选项，其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。<br />
那么假设存在一个http://www.80sec.com/80sec.jpg，我们以如下的方式去访问</p>
<p>http://www.80sec.com/80sec.jpg/80sec.php</p>
<p>将会得到一个URI</p>
<p>/80sec.jpg/80sec.php</p>
<p>经过location指令，该请求将会交给后端的fastcgi处理，nginx为其设置环境变量SCRIPT_FILENAME，内容为</p>
<p>/scripts/80sec.jpg/80sec.php</p>
<p>而在其他的webserver如lighttpd当中，我们发现其中的SCRIPT_FILENAME被正确的设置为</p>
<p>/scripts/80sec.jpg</p>
<p>所以不存在此问题。<br />
后端的fastcgi在接受到该选项时，会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理，一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用，所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字，查找的方式也是查看文件是否存在，这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为</p>
<p>/scripts/80sec.jpg和80sec.php</p>
<p>最后，以/scripts/80sec.jpg作为此次请求需要执行的脚本，攻击者就可以实现让nginx以php来解析任何类型的文件了。</p>
<p>POC： 访问一个nginx来支持php的站点，在一个任何资源的文件如robots.txt后面加上/80sec.php，这个时候你可以看到如下的区别：</p>
<p>访问http://www.80sec.com/robots.txt</p>
<p>HTTP/1.1 200 OK<br />
Server: nginx/0.6.32<br />
Date: Thu, 20 May 2010 10:05:30 GMT<br />
Content-Type: text/plain<br />
Content-Length: 18<br />
Last-Modified: Thu, 20 May 2010 06:26:34 GMT<br />
Connection: keep-alive<br />
Keep-Alive: timeout=20<br />
Accept-Ranges: bytes</p>
<p>访问访问http://www.80sec.com/robots.txt/80sec.php</p>
<p>HTTP/1.1 200 OK<br />
Server: nginx/0.6.32<br />
Date: Thu, 20 May 2010 10:06:49 GMT<br />
Content-Type: text/html<br />
Transfer-Encoding: chunked<br />
Connection: keep-alive<br />
Keep-Alive: timeout=20<br />
X-Powered-By: PHP/5.2.6</p>
<p>其中的Content-Type的变化说明了后端负责解析的变化，该站点就可能存在漏洞。</p>
<p>漏洞厂商：http://www.nginx.org</p>
<p>解决方案：</p>
<p>我们已经尝试联系官方，但是此前你可以通过以下的方式来减少损失</p>
<p>关闭cgi.fix_pathinfo为0</p>
<p>或者</p>
<p>if ( $fastcgi_script_name ~ \..*\/.*php ) {<br />
return 403;<br />
}</p>
<p>PS: 鸣谢laruence大牛在分析过程中给的帮助</p>
]]></content:encoded>
			<wfw:commentRss>http://www.0x50sec.org/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

