var-201503-0424
Vulnerability from variot

EmbedThis GoAhead 3.0.0 through 3.4.1 does not properly handle path segments starting with a . (dot), which allows remote attackers to conduct directory traversal attacks, cause a denial of service (heap-based buffer overflow and crash), or possibly execute arbitrary code via a crafted URI. EmbedThis GoAhead Is . Supplementary information : CWE Vulnerability type by CWE-17: Code ( code ) Has been identified. GoAhead WebServer is prone to a directory-traversal vulnerability because it fails to sufficiently sanitize user-supplied input. Attackers can exploit this issue to obtain sensitive information or crash the application resulting in a denial-of-service condition. Successful exploits will lead to other attacks. GoAhead WebServer versions 3.0.0 through 3.4.1 are vulnerable. Embedthis Software GoAhead is an embedded Web server of American Embedthis Software company. Embedthis Software GoAhead version 3.0.0 to 3.4.1 has a security hole, the hole is due to the program does not correctly handle the part of the path starting with the '.' character. Affected software: GoAhead Web Server Affected versions: 3.0.0 - 3.4.1 (3.x.x series before 3.4.2) CVE ID: CVE-2014-9707

Description: The server incorrectly normalizes HTTP request URIs that contain path segments that start with a "." but are not entirely equal to "." or ".." (eg. ".x").

Fixed version: 3.4.2 Bug entry: https://github.com/embedthis/goahead/issues/106 Fix: https://github.com/embedthis/goahead/commit/eed4a7d177bf94a54c7b06ccce88507fbd76fb77 Reported by: Matthew Daley

Detail:

The vulnerability lies in the websNormalizeUriPath function.

A quick runthrough of the important parts of this function:

The function starts by splitting up the URI into segments (at forward slashes) into an array. At the same time, it calculates the total length of these segments.

The function then iterates through the resulting array in order to perform an in-place normalization (both the input and output pointers point to the same array):

  • If a given segment does not start with a '.', it is simply copied from the current input pointer to the current output pointer. The for loop's increment code will then advance both the input and output pointers.

  • Otherwise, if the segment is "." or "..", the input and output pointers are adjusted appropriately (taking into account the for loop's increment code) but (correctly) no segment is copied.

  • Otherwise the segment starts with a '.' but is not "." nor ".."; in this case the function incorrectly does nothing and both the input and output pointers are simply advanced by the for loop's increment code. This effectively skips over a segment in the segment array without any modification by the function.

After this iteration has completed, a string buffer for the final output is allocated. The size used for this allocation comes from the previously-calculated total segment length, with the addition of space for forward slashes to join the segments back together again and a null terminator. The segments in the array up to the final output pointer are joined together in this buffer with forward slashes separating them.

There are two ways to exploit this incorrect handling of certain segments:

1) Heap overflow

The heap overflow exploitation lies in the possibility to create a disconnect between the lengths of the segments left in the segment array after the iteration has completed and the previously-calculated total segment length. The previously-calculated length should, in theory, be the worst-case (longest) final output string buffer size required (when all segments are left and none are removed by the normalization iteration). However, since we can force the iteration to skip over certain segments in the array, it is possible to effectively duplicate segments in the resulting array; this is done by having the segment copied from one location to another but then also having the original copy skipped over, making it appear in the resulting array twice. When this is done, the previously-calculated length is no longer long enough for the final output's string buffer, and a heap overflow occurs while joining together the final result.

As an example, take the following URI as input to the function: "/./AAAAAAAA/.x".

The URI is first split into the segments "", ".", "AAAAAAAA" and ".", with the total segment length calculated as 0 + 1 + 8 + 2 = 11 bytes.

The normalization iteration proceeds as follows:

  • The "" segment is simply copied from input to output, and hence remains unchanged. Both the input and output pointers are then advanced.

  • The "." segment causes the output pointer to stay in place while the input pointer advances forward.

  • The "AAAAAAAA" segment is simply copied from input to output, and hence overwrites the previous "." segment. Both the input and output pointers are then advanced.

  • Finally, the ".x" segment is incorrectly handled: no modification of segments is performed but both the input and output pointers are still advanced, moving the output pointer over the original "AAAAAAAA" segment.

Hence, the resulting segments in the array that are left up to the final output pointer are "", "AAAAAAAA" and "AAAAAAAA". Note that the "AAAAAAAA" segment has been duplicated. These segments, including space for forward slashes to join them together with and a null terminator, have a total length of 0 + 8 + 8 + 2 + 1 = 19 bytes.

A string buffer is then allocated for the final output, which uses the previously-calculated total segment length of 11 bytes plus 3 bytes for forward slashes and 1 byte for a null terminator, giving a total size of 11 + 3 + 1 = 15 bytes.

The resulting segments are finally joined together into this final output string buffer. In doing so in this case, however, the buffer is overflowed by 19 - 15 = 4 bytes.

So, a remote attacker can make (ie.) a simple HTTP GET request for the URI in question and cause a heap overflow. ASAN gives the following output in this case, which shows the exact moment that the heap overflow occurs:

================================================================= ==2613==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000d47f at pc 0x7ffff6f34020 bp 0x7fffffffd410 sp 0x7fffffffcbd0 WRITE of size 9 at 0x60200000d47f thread T0 #0 0x7ffff6f3401f in __interceptor_strcpy (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x2f01f) #1 0x7ffff63a7d6d in websNormalizeUriPath src/http.c:3320 #2 0x7ffff639b4de in parseFirstLine src/http.c:969 #3 0x7ffff639a905 in parseIncoming src/http.c:880 #4 0x7ffff639a4c9 in websPump src/http.c:829 #5 0x7ffff639a19c in readEvent src/http.c:802 #6 0x7ffff6399de7 in socketEvent src/http.c:740 #7 0x7ffff6399cbc in websAccept src/http.c:719 #8 0x7ffff63ac8ed in socketAccept src/socket.c:327 #9 0x7ffff63ade95 in socketDoEvent src/socket.c:638 #10 0x7ffff63add5f in socketProcess src/socket.c:622 #11 0x7ffff639daf8 in websServiceEvents src/http.c:1307 #12 0x401b5c in main src/goahead.c:153 #13 0x7ffff597ab44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44) #14 0x4011d8 (/home/matthew/goahead-3.4.1/build/linux-x64-debug/bin/goahead+0x4011d8)

0x60200000d47f is located 0 bytes to the right of 15-byte region [0x60200000d470,0x60200000d47f) allocated by thread T0 here: #0 0x7ffff6f5973f in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5473f) #1 0x7ffff63a7d04 in websNormalizeUriPath src/http.c:3318 #2 0x7ffff639b4de in parseFirstLine src/http.c:969 #3 0x7ffff639a905 in parseIncoming src/http.c:880 #4 0x7ffff639a4c9 in websPump src/http.c:829 #5 0x7ffff639a19c in readEvent src/http.c:802 #6 0x7ffff6399de7 in socketEvent src/http.c:740 #7 0x7ffff6399cbc in websAccept src/http.c:719 #8 0x7ffff63ac8ed in socketAccept src/socket.c:327 #9 0x7ffff63ade95 in socketDoEvent src/socket.c:638 #10 0x7ffff63add5f in socketProcess src/socket.c:622 #11 0x7ffff639daf8 in websServiceEvents src/http.c:1307 #12 0x401b5c in main src/goahead.c:153 #13 0x7ffff597ab44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44) (... snip ...)

As with all heap overflows, it's likely that this can then go on to be exploited in order to gain full remote code execution, especially in embedded systems which are less likely to have heap allocators with modern hardening techniques.

2) Directory traversal

The directory traversal exploitation lies in the fact that we can force the normalization iteration to skip over certain segments in the array; namely, we can force it to skip over a ".." segment. The ".." segment will pass through unchanged into the final output string buffer, where it is treated by the rest of the server as an actual parent-directory relative segment.

As an example, take the following URI as input to the function: "/../../../../../.x/.x/.x/.x/.x/.x/etc/passwd".

The URI is first split into the segments "", "..", "..", "..", "..", "..", ".x", ".x", ".x", ".x", ".x", ".x", "etc", and "passwd". (The total segment length that is calculated during this operation is irrelevant for this mode of exploitation.)

When the normalization iteration reaches the ".x" segments, the contents of the segment array are still untouched (as all the previous segments are either empty or are "..") and the output pointer is still pointing back at the "" segment. The incorrect handling of the ".x" segments only causes the output (and input) pointers to be advanced forward over the "" and ".." segments.

When the iteration reaches the "etc" segment, all the "" and ".." segments have been skipped over; the output pointer is now pointing at the first ".x" segment. The "etc" is copied over the first ".x" segment, and the "passwd" segment is copied over the second ".x" segment.

Hence, the resulting segments in the array that are left up to the final output pointer are "", "..", "..", "..", "..", "..", "etc" and "passwd"; note that the ".." segments are still present.

The final output string buffer is created and the resulting segments are joined together to give a string of "/../../../../../etc/passwd".

The rest of the server is expecting that the result from the function is normalized and that it contains no relative segments. Hence, the ".." segments go unnoticed when opening the content file while handling the HTTP request. The end result is that the local filesystem is traversed up from the administrator-configured web root until reaching the filesystem's root directory and back down again into the "/etc/passwd" file. Hence, the file "/etc/passwd" is given in response to the HTTP request, regardless of the configured web root.

So, a remote attacker can make (ie.) a simple HTTP GET request for the URI in question and get the contents of the "/etc/passwd" file:

$ echo -ne 'GET /../../../../../.x/.x/.x/.x/.x/.x/etc/passwd HTTP/1.0\r\n\r\n' | nc localhost 4700 HTTP/1.0 200 OK Server: GoAhead-http Date: Sun Nov 16 17:21:01 2014 Content-Length: 1346 Connection: close Last-Modified: Sat Oct 25 17:07:25 2014

root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin (... snip ...)

Of course, 5 ".." segments may not be enough to reach the filesystem's root directory in all cases and so the crafted URI may have to be extended with more ".." and ".x" segments.

  • Matthew Daley

Show details on source website


{
  "@context": {
    "@vocab": "https://www.variotdbs.pl/ref/VARIoTentry#",
    "affected_products": {
      "@id": "https://www.variotdbs.pl/ref/affected_products"
    },
    "configurations": {
      "@id": "https://www.variotdbs.pl/ref/configurations"
    },
    "credits": {
      "@id": "https://www.variotdbs.pl/ref/credits"
    },
    "cvss": {
      "@id": "https://www.variotdbs.pl/ref/cvss/"
    },
    "description": {
      "@id": "https://www.variotdbs.pl/ref/description/"
    },
    "exploit_availability": {
      "@id": "https://www.variotdbs.pl/ref/exploit_availability/"
    },
    "external_ids": {
      "@id": "https://www.variotdbs.pl/ref/external_ids/"
    },
    "iot": {
      "@id": "https://www.variotdbs.pl/ref/iot/"
    },
    "iot_taxonomy": {
      "@id": "https://www.variotdbs.pl/ref/iot_taxonomy/"
    },
    "patch": {
      "@id": "https://www.variotdbs.pl/ref/patch/"
    },
    "problemtype_data": {
      "@id": "https://www.variotdbs.pl/ref/problemtype_data/"
    },
    "references": {
      "@id": "https://www.variotdbs.pl/ref/references/"
    },
    "sources": {
      "@id": "https://www.variotdbs.pl/ref/sources/"
    },
    "sources_release_date": {
      "@id": "https://www.variotdbs.pl/ref/sources_release_date/"
    },
    "sources_update_date": {
      "@id": "https://www.variotdbs.pl/ref/sources_update_date/"
    },
    "threat_type": {
      "@id": "https://www.variotdbs.pl/ref/threat_type/"
    },
    "title": {
      "@id": "https://www.variotdbs.pl/ref/title/"
    },
    "type": {
      "@id": "https://www.variotdbs.pl/ref/type/"
    }
  },
  "@id": "https://www.variotdbs.pl/vuln/VAR-201503-0424",
  "affected_products": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/affected_products#",
      "data": {
        "@container": "@list"
      },
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        },
        "@id": "https://www.variotdbs.pl/ref/sources"
      }
    },
    "data": [
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.3.2"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.3.3"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.0.0"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.3.1"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.3.5"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.3.4"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.4.0"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 1.6,
        "vendor": "embedthis",
        "version": "3.3.6"
      },
      {
        "model": "goahead",
        "scope": "eq",
        "trust": 0.8,
        "vendor": "embedthis",
        "version": "3.0.0 to  3.4.1"
      },
      {
        "model": "webserver",
        "scope": "eq",
        "trust": 0.3,
        "vendor": "goahead",
        "version": "3.4.1"
      },
      {
        "model": "webserver",
        "scope": "eq",
        "trust": 0.3,
        "vendor": "goahead",
        "version": "3.0.0"
      },
      {
        "model": "webserver",
        "scope": "ne",
        "trust": 0.3,
        "vendor": "goahead",
        "version": "3.4.2"
      }
    ],
    "sources": [
      {
        "db": "BID",
        "id": "73404"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "configurations": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/configurations#",
      "children": {
        "@container": "@list"
      },
      "cpe_match": {
        "@container": "@list"
      },
      "data": {
        "@container": "@list"
      },
      "nodes": {
        "@container": "@list"
      }
    },
    "data": [
      {
        "CVE_data_version": "4.0",
        "nodes": [
          {
            "children": [],
            "cpe_match": [
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.0.0:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.3.2:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.3.1:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.4.0:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.3.6:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.3.5:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.3.4:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              },
              {
                "cpe23Uri": "cpe:2.3:a:embedthis:goahead:3.3.3:*:*:*:*:*:*:*",
                "cpe_name": [],
                "vulnerable": true
              }
            ],
            "operator": "OR"
          }
        ]
      }
    ],
    "sources": [
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      }
    ]
  },
  "credits": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/credits#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": "Matthew Daley",
    "sources": [
      {
        "db": "BID",
        "id": "73404"
      },
      {
        "db": "PACKETSTORM",
        "id": "131156"
      }
    ],
    "trust": 0.4
  },
  "cve": "CVE-2014-9707",
  "cvss": {
    "@context": {
      "cvssV2": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/cvss/cvssV2#"
        },
        "@id": "https://www.variotdbs.pl/ref/cvss/cvssV2"
      },
      "cvssV3": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/cvss/cvssV3#"
        },
        "@id": "https://www.variotdbs.pl/ref/cvss/cvssV3/"
      },
      "severity": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/cvss/severity#"
        },
        "@id": "https://www.variotdbs.pl/ref/cvss/severity"
      },
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        },
        "@id": "https://www.variotdbs.pl/ref/sources"
      }
    },
    "data": [
      {
        "cvssV2": [
          {
            "acInsufInfo": false,
            "accessComplexity": "LOW",
            "accessVector": "NETWORK",
            "authentication": "NONE",
            "author": "NVD",
            "availabilityImpact": "PARTIAL",
            "baseScore": 7.5,
            "confidentialityImpact": "PARTIAL",
            "exploitabilityScore": 10.0,
            "impactScore": 6.4,
            "integrityImpact": "PARTIAL",
            "obtainAllPrivilege": false,
            "obtainOtherPrivilege": false,
            "obtainUserPrivilege": false,
            "severity": "HIGH",
            "trust": 1.0,
            "userInteractionRequired": false,
            "vectorString": "AV:N/AC:L/Au:N/C:P/I:P/A:P",
            "version": "2.0"
          },
          {
            "acInsufInfo": null,
            "accessComplexity": "Low",
            "accessVector": "Network",
            "authentication": "None",
            "author": "NVD",
            "availabilityImpact": "Partial",
            "baseScore": 7.5,
            "confidentialityImpact": "Partial",
            "exploitabilityScore": null,
            "id": "CVE-2014-9707",
            "impactScore": null,
            "integrityImpact": "Partial",
            "obtainAllPrivilege": null,
            "obtainOtherPrivilege": null,
            "obtainUserPrivilege": null,
            "severity": "High",
            "trust": 0.8,
            "userInteractionRequired": null,
            "vectorString": "AV:N/AC:L/Au:N/C:P/I:P/A:P",
            "version": "2.0"
          },
          {
            "accessComplexity": "LOW",
            "accessVector": "NETWORK",
            "authentication": "NONE",
            "author": "VULHUB",
            "availabilityImpact": "PARTIAL",
            "baseScore": 7.5,
            "confidentialityImpact": "PARTIAL",
            "exploitabilityScore": 10.0,
            "id": "VHN-77652",
            "impactScore": 6.4,
            "integrityImpact": "PARTIAL",
            "severity": "HIGH",
            "trust": 0.1,
            "vectorString": "AV:N/AC:L/AU:N/C:P/I:P/A:P",
            "version": "2.0"
          }
        ],
        "cvssV3": [],
        "severity": [
          {
            "author": "NVD",
            "id": "CVE-2014-9707",
            "trust": 1.8,
            "value": "HIGH"
          },
          {
            "author": "CNNVD",
            "id": "CNNVD-201503-646",
            "trust": 0.6,
            "value": "HIGH"
          },
          {
            "author": "VULHUB",
            "id": "VHN-77652",
            "trust": 0.1,
            "value": "HIGH"
          }
        ]
      }
    ],
    "sources": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "description": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/description#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": "EmbedThis GoAhead 3.0.0 through 3.4.1 does not properly handle path segments starting with a . (dot), which allows remote attackers to conduct directory traversal attacks, cause a denial of service (heap-based buffer overflow and crash), or possibly execute arbitrary code via a crafted URI. EmbedThis GoAhead Is . Supplementary information : CWE Vulnerability type by CWE-17: Code ( code ) Has been identified. GoAhead WebServer is prone to a directory-traversal vulnerability because it fails to sufficiently sanitize user-supplied input. \nAttackers can exploit this issue to obtain sensitive information or crash the application resulting in a denial-of-service condition. Successful exploits will lead to other attacks. \nGoAhead WebServer versions 3.0.0 through 3.4.1 are vulnerable. Embedthis Software GoAhead is an embedded Web server of American Embedthis Software company. Embedthis Software GoAhead version 3.0.0 to 3.4.1 has a security hole, the hole is due to the program does not correctly handle the part of the path starting with the \u0027.\u0027 character. Affected software: GoAhead Web Server\nAffected versions: 3.0.0 - 3.4.1 (3.x.x series before 3.4.2)\nCVE ID: CVE-2014-9707\n\nDescription: The server incorrectly normalizes HTTP request URIs that\ncontain path segments that start with a \".\" but are not entirely equal\nto \".\" or \"..\" (eg. \".x\"). \n\nFixed version: 3.4.2\nBug entry: https://github.com/embedthis/goahead/issues/106\nFix: https://github.com/embedthis/goahead/commit/eed4a7d177bf94a54c7b06ccce88507fbd76fb77\nReported by: Matthew Daley\n\nDetail:\n\nThe vulnerability lies in the websNormalizeUriPath function. \n\n\nA quick runthrough of the important parts of this function:\n\nThe function starts by splitting up the URI into segments (at forward\nslashes) into an array. At the same time, it calculates the total\nlength of these segments. \n\nThe function then iterates through the resulting array in order to\nperform an in-place normalization (both the input and output pointers\npoint to the same array):\n\n* If a given segment does not start with a \u0027.\u0027, it is simply copied from the\n  current input pointer to the current output pointer. The for loop\u0027s\n  increment code will then advance both the input and output pointers. \n\n* Otherwise, if the segment is \".\" or \"..\", the input and output pointers are\n  adjusted appropriately (taking into account the for loop\u0027s increment code)\n  but (correctly) no segment is copied. \n\n* Otherwise the segment starts with a \u0027.\u0027 but is not \".\" nor \"..\"; in this\n  case the function incorrectly does nothing and both the input and output\n  pointers are simply advanced by the for loop\u0027s increment code. This\n  effectively skips over a segment in the segment array without any\n  modification by the function. \n\nAfter this iteration has completed, a string buffer for the final\noutput is allocated. The size used for this allocation comes from the\npreviously-calculated total segment length, with the addition of space\nfor forward slashes to join the segments back together again and a\nnull terminator. The segments in the array up to the final output\npointer are joined together in this buffer with forward slashes\nseparating them. \n\n\nThere are two ways to exploit this incorrect handling of certain segments:\n\n\n1) Heap overflow\n\nThe heap overflow exploitation lies in the possibility to create a\ndisconnect between the lengths of the segments left in the segment\narray after the iteration has completed and the previously-calculated\ntotal segment length. The previously-calculated length should, in\ntheory, be the worst-case (longest) final output string buffer size\nrequired (when all segments are left and none are removed by the\nnormalization iteration). However, since we can force the iteration to\nskip over certain segments in the array, it is possible to effectively\nduplicate segments in the resulting array; this is done by having the\nsegment copied from one location to another but then also having the\noriginal copy skipped over, making it appear in the resulting array\ntwice. When this is done, the previously-calculated length is no\nlonger long enough for the final output\u0027s string buffer, and a heap\noverflow occurs while joining together the final result. \n\nAs an example, take the following URI as input to the function:\n\"/./AAAAAAAA/.x\". \n\nThe URI is first split into the segments \"\", \".\", \"AAAAAAAA\" and \".\",\nwith the total segment length calculated as 0 + 1 + 8 + 2 = 11 bytes. \n\nThe normalization iteration proceeds as follows:\n\n* The \"\" segment is simply copied from input to output, and hence remains\n  unchanged. Both the input and output pointers are then advanced. \n\n* The \".\" segment causes the output pointer to stay in place while the input\n  pointer advances forward. \n\n* The \"AAAAAAAA\" segment is simply copied from input to output, and hence\n  overwrites the previous \".\" segment. Both the input and output pointers are\n  then advanced. \n\n* Finally, the \".x\" segment is incorrectly handled: no modification of\n  segments is performed but both the input and output pointers are still\n  advanced, moving the output pointer over the original \"AAAAAAAA\" segment. \n\nHence, the resulting segments in the array that are left up to the\nfinal output pointer are \"\", \"AAAAAAAA\" and \"AAAAAAAA\". Note that the\n\"AAAAAAAA\" segment has been duplicated. These segments, including\nspace for forward slashes to join them together with and a null\nterminator, have a total length of 0 + 8 + 8 + 2 + 1 = 19 bytes. \n\nA string buffer is then allocated for the final output, which uses the\npreviously-calculated total segment length of 11 bytes plus 3 bytes\nfor forward slashes and 1 byte for a null terminator, giving a total\nsize of 11 + 3 + 1 = 15 bytes. \n\nThe resulting segments are finally joined together into this final\noutput string buffer. In doing so in this case, however, the buffer is\noverflowed by 19 - 15 = 4 bytes. \n\nSo, a remote attacker can make (ie.) a simple HTTP GET request for the\nURI in question and cause a heap overflow. ASAN gives the following\noutput in this case, which shows the exact moment that the heap\noverflow occurs:\n\n=================================================================\n==2613==ERROR: AddressSanitizer: heap-buffer-overflow on address\n0x60200000d47f at pc 0x7ffff6f34020 bp 0x7fffffffd410 sp\n0x7fffffffcbd0\nWRITE of size 9 at 0x60200000d47f thread T0\n    #0 0x7ffff6f3401f in __interceptor_strcpy\n(/usr/lib/x86_64-linux-gnu/libasan.so.1+0x2f01f)\n    #1 0x7ffff63a7d6d in websNormalizeUriPath src/http.c:3320\n    #2 0x7ffff639b4de in parseFirstLine src/http.c:969\n    #3 0x7ffff639a905 in parseIncoming src/http.c:880\n    #4 0x7ffff639a4c9 in websPump src/http.c:829\n    #5 0x7ffff639a19c in readEvent src/http.c:802\n    #6 0x7ffff6399de7 in socketEvent src/http.c:740\n    #7 0x7ffff6399cbc in websAccept src/http.c:719\n    #8 0x7ffff63ac8ed in socketAccept src/socket.c:327\n    #9 0x7ffff63ade95 in socketDoEvent src/socket.c:638\n    #10 0x7ffff63add5f in socketProcess src/socket.c:622\n    #11 0x7ffff639daf8 in websServiceEvents src/http.c:1307\n    #12 0x401b5c in main src/goahead.c:153\n    #13 0x7ffff597ab44 in __libc_start_main\n(/lib/x86_64-linux-gnu/libc.so.6+0x21b44)\n    #14 0x4011d8\n(/home/matthew/goahead-3.4.1/build/linux-x64-debug/bin/goahead+0x4011d8)\n\n0x60200000d47f is located 0 bytes to the right of 15-byte region\n[0x60200000d470,0x60200000d47f)\nallocated by thread T0 here:\n    #0 0x7ffff6f5973f in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5473f)\n    #1 0x7ffff63a7d04 in websNormalizeUriPath src/http.c:3318\n    #2 0x7ffff639b4de in parseFirstLine src/http.c:969\n    #3 0x7ffff639a905 in parseIncoming src/http.c:880\n    #4 0x7ffff639a4c9 in websPump src/http.c:829\n    #5 0x7ffff639a19c in readEvent src/http.c:802\n    #6 0x7ffff6399de7 in socketEvent src/http.c:740\n    #7 0x7ffff6399cbc in websAccept src/http.c:719\n    #8 0x7ffff63ac8ed in socketAccept src/socket.c:327\n    #9 0x7ffff63ade95 in socketDoEvent src/socket.c:638\n    #10 0x7ffff63add5f in socketProcess src/socket.c:622\n    #11 0x7ffff639daf8 in websServiceEvents src/http.c:1307\n    #12 0x401b5c in main src/goahead.c:153\n    #13 0x7ffff597ab44 in __libc_start_main\n(/lib/x86_64-linux-gnu/libc.so.6+0x21b44)\n(... snip ...)\n\nAs with all heap overflows, it\u0027s likely that this can then go on to be\nexploited in order to gain full remote code execution, especially in\nembedded systems which are less likely to have heap allocators with\nmodern hardening techniques. \n\n\n2) Directory traversal\n\nThe directory traversal exploitation lies in the fact that we can\nforce the normalization iteration to skip over certain segments in the\narray; namely, we can force it to skip over a \"..\" segment. The \"..\"\nsegment will pass through unchanged into the final output string\nbuffer, where it is treated by the rest of the server as an actual\nparent-directory relative segment. \n\nAs an example, take the following URI as input to the function:\n\"/../../../../../.x/.x/.x/.x/.x/.x/etc/passwd\". \n\nThe URI is first split into the segments \"\", \"..\", \"..\", \"..\", \"..\",\n\"..\", \".x\", \".x\", \".x\", \".x\", \".x\", \".x\", \"etc\", and \"passwd\". (The\ntotal segment length that is calculated during this operation is\nirrelevant for this mode of exploitation.)\n\nWhen the normalization iteration reaches the \".x\" segments, the\ncontents of the segment array are still untouched (as all the previous\nsegments are either empty or are \"..\") and the output pointer is still\npointing back at the \"\" segment. The incorrect handling of the \".x\"\nsegments only causes the output (and input) pointers to be advanced\nforward over the \"\" and \"..\" segments. \n\nWhen the iteration reaches the \"etc\" segment, all the \"\" and \"..\"\nsegments have been skipped over; the output pointer is now pointing at\nthe first \".x\" segment. The \"etc\" is copied over the first \".x\"\nsegment, and the \"passwd\" segment is copied over the second \".x\"\nsegment. \n\nHence, the resulting segments in the array that are left up to the\nfinal output pointer are \"\", \"..\", \"..\", \"..\", \"..\", \"..\", \"etc\" and\n\"passwd\"; note that the \"..\" segments are still present. \n\nThe final output string buffer is created and the resulting segments\nare joined together to give a string of \"/../../../../../etc/passwd\". \n\nThe rest of the server is expecting that the result from the function\nis normalized and that it contains no relative segments. Hence, the\n\"..\" segments go unnoticed when opening the content file while\nhandling the HTTP request. The end result is that the local filesystem\nis traversed up from the administrator-configured web root until\nreaching the filesystem\u0027s root directory and back down again into the\n\"/etc/passwd\" file. Hence, the file \"/etc/passwd\" is given in response\nto the HTTP request, regardless of the configured web root. \n\nSo, a remote attacker can make (ie.) a simple HTTP GET request for the\nURI in question and get the contents of the \"/etc/passwd\" file:\n\n$ echo -ne \u0027GET /../../../../../.x/.x/.x/.x/.x/.x/etc/passwd\nHTTP/1.0\\r\\n\\r\\n\u0027 | nc localhost 4700\nHTTP/1.0 200 OK\nServer: GoAhead-http\nDate: Sun Nov 16 17:21:01 2014\nContent-Length: 1346\nConnection: close\nLast-Modified: Sat Oct 25 17:07:25 2014\n\nroot:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\n(... snip ...)\n\nOf course, 5 \"..\" segments may not be enough to reach the filesystem\u0027s\nroot directory in all cases and so the crafted URI may have to be\nextended with more \"..\" and \".x\" segments. \n\n\n- Matthew Daley\n",
    "sources": [
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "BID",
        "id": "73404"
      },
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "db": "PACKETSTORM",
        "id": "131156"
      }
    ],
    "trust": 2.07
  },
  "exploit_availability": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/exploit_availability#",
      "data": {
        "@container": "@list"
      },
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": [
      {
        "reference": "https://www.scap.org.cn/vuln/vhn-77652",
        "trust": 0.1,
        "type": "unknown"
      }
    ],
    "sources": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      }
    ]
  },
  "external_ids": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/external_ids#",
      "data": {
        "@container": "@list"
      },
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": [
      {
        "db": "NVD",
        "id": "CVE-2014-9707",
        "trust": 2.9
      },
      {
        "db": "PACKETSTORM",
        "id": "131156",
        "trust": 1.2
      },
      {
        "db": "SECTRACK",
        "id": "1032208",
        "trust": 1.1
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006",
        "trust": 0.8
      },
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646",
        "trust": 0.7
      },
      {
        "db": "BID",
        "id": "73404",
        "trust": 0.4
      },
      {
        "db": "SEEBUG",
        "id": "SSVID-92042",
        "trust": 0.1
      },
      {
        "db": "VULHUB",
        "id": "VHN-77652",
        "trust": 0.1
      }
    ],
    "sources": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "db": "BID",
        "id": "73404"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "PACKETSTORM",
        "id": "131156"
      },
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "id": "VAR-201503-0424",
  "iot": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/iot#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": true,
    "sources": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      }
    ],
    "trust": 0.01
  },
  "last_update_date": "2023-12-18T13:03:27.897000Z",
  "patch": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/patch#",
      "data": {
        "@container": "@list"
      },
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": [
      {
        "title": "GoAhead",
        "trust": 0.8,
        "url": "https://embedthis.com/goahead/"
      },
      {
        "title": "FIX: Dot filename segments permit directory traversal [issue 106]",
        "trust": 0.8,
        "url": "https://github.com/embedthis/goahead/commit/eed4a7d177bf94a54c7b06ccce88507fbd76fb77"
      },
      {
        "title": "URI Parsing Dot Segments #106",
        "trust": 0.8,
        "url": "https://github.com/embedthis/goahead/issues/106"
      }
    ],
    "sources": [
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      }
    ]
  },
  "problemtype_data": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/problemtype_data#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": [
      {
        "problemtype": "CWE-17",
        "trust": 1.1
      },
      {
        "problemtype": "CWE-Other",
        "trust": 0.8
      }
    ],
    "sources": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      }
    ]
  },
  "references": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/references#",
      "data": {
        "@container": "@list"
      },
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": [
      {
        "trust": 2.1,
        "url": "https://github.com/embedthis/goahead/commit/eed4a7d177bf94a54c7b06ccce88507fbd76fb77"
      },
      {
        "trust": 2.1,
        "url": "https://github.com/embedthis/goahead/issues/106"
      },
      {
        "trust": 1.7,
        "url": "http://seclists.org/fulldisclosure/2015/mar/157"
      },
      {
        "trust": 1.1,
        "url": "http://www.securityfocus.com/archive/1/535027/100/0/threaded"
      },
      {
        "trust": 1.1,
        "url": "http://packetstormsecurity.com/files/131156/goahead-3.4.1-heap-overflow-traversal.html"
      },
      {
        "trust": 1.1,
        "url": "http://www.securitytracker.com/id/1032208"
      },
      {
        "trust": 0.8,
        "url": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2014-9707"
      },
      {
        "trust": 0.8,
        "url": "http://web.nvd.nist.gov/view/vuln/detail?vulnid=cve-2014-9707"
      },
      {
        "trust": 0.6,
        "url": "http://www.securityfocus.com/archive/1/archive/1/535027/100/0/threaded"
      },
      {
        "trust": 0.3,
        "url": "http://www.goahead.com/products/webserver/default.aspx"
      },
      {
        "trust": 0.1,
        "url": "https://nvd.nist.gov/vuln/detail/cve-2014-9707"
      }
    ],
    "sources": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "db": "BID",
        "id": "73404"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "PACKETSTORM",
        "id": "131156"
      },
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "sources": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/sources#",
      "data": {
        "@container": "@list"
      }
    },
    "data": [
      {
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "db": "BID",
        "id": "73404"
      },
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "db": "PACKETSTORM",
        "id": "131156"
      },
      {
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "sources_release_date": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/sources_release_date#",
      "data": {
        "@container": "@list"
      }
    },
    "data": [
      {
        "date": "2015-03-31T00:00:00",
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "date": "2015-03-28T00:00:00",
        "db": "BID",
        "id": "73404"
      },
      {
        "date": "2015-04-03T00:00:00",
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "date": "2015-03-28T18:02:22",
        "db": "PACKETSTORM",
        "id": "131156"
      },
      {
        "date": "2015-03-31T14:59:06.250000",
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "date": "2015-03-31T00:00:00",
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "sources_update_date": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/sources_update_date#",
      "data": {
        "@container": "@list"
      }
    },
    "data": [
      {
        "date": "2018-10-09T00:00:00",
        "db": "VULHUB",
        "id": "VHN-77652"
      },
      {
        "date": "2015-03-28T00:00:00",
        "db": "BID",
        "id": "73404"
      },
      {
        "date": "2015-04-03T00:00:00",
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      },
      {
        "date": "2018-10-09T19:55:10.497000",
        "db": "NVD",
        "id": "CVE-2014-9707"
      },
      {
        "date": "2015-04-01T00:00:00",
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ]
  },
  "threat_type": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/threat_type#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": "remote",
    "sources": [
      {
        "db": "CNNVD",
        "id": "CNNVD-201503-646"
      }
    ],
    "trust": 0.6
  },
  "title": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/title#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": "EmbedThis GoAhead Vulnerable to directory traversal attacks",
    "sources": [
      {
        "db": "JVNDB",
        "id": "JVNDB-2014-008006"
      }
    ],
    "trust": 0.8
  },
  "type": {
    "@context": {
      "@vocab": "https://www.variotdbs.pl/ref/type#",
      "sources": {
        "@container": "@list",
        "@context": {
          "@vocab": "https://www.variotdbs.pl/ref/sources#"
        }
      }
    },
    "data": "Input Validation Error",
    "sources": [
      {
        "db": "BID",
        "id": "73404"
      }
    ],
    "trust": 0.3
  }
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading...

Loading...