CVE-2014-125098 (Other, published 2023-04-10T04:15Z)
Description: value: A vulnerability was found in Dart http_server up to 0.9.5 and classified as problematic. Affected by this issue is the function VirtualDirectory of the file lib/src/virtual_directory.dart of the component Directory Listing Handler. The manipulation of the argument request.uri.path leads to cross site scripting. The attack may be launched remotely. Upgrading to version 0.9.6 is able to address this issue. The name of the patch is 27c1cbd8125bb0369e675eb72e48218496e48ffb. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-225356.
Severity: nan (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/dart-archive/http_server
Files changed:
lib/src/virtual_directory.dart
test/virtual_directory_test.dart
Commit message: Fix XSS issues in http_server's dir-listing and error-page.

BUG=
R=sgjesse@google.com

Review URL: https://codereview.chromium.org//225813002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/http_server@34769 260f80e4-7a28-3924-810f-c04153c831b5


Vulnerable code:
      var path = request.uri.path;
<title>Index of $path</title>
<h1>Index of $path</h1>
        var p = normalize(join(path, name));
    <td><a href="$p">$name</a></td>
    <td>$modified</td>
    <td style="text-align: right">$size</td>
    var path = request.uri.path;
    var reason = response.reasonPhrase;
<title>$reason: $path</title>
<h1>Error $error at \'$path\': $reason</h1>
            expect(result, contains('Index of /'));
            expect(result, contains('Index of /'));
            expect(result, contains('Index of /'));
                  (s) => s.contains('recursive/')),
                  (s) => s.contains('Index of /')),
                  (s) => s.contains('recursive/')),
                  (s) => s.contains('../')),
                  (s) => s.contains('Index of /recursive'))])

Fixed code:
      var path = Uri.decodeComponent(request.uri.path);
      var encodedPath = new HtmlEscape().convert(path);
<title>Index of $encodedPath</title>
<h1>Index of $encodedPath</h1>
        try {
        var encodedSize = new HtmlEscape().convert(size.toString());
        var encodedModified = new HtmlEscape().convert(modified);
        var encodedLink = new HtmlEscape(HtmlEscapeMode.ATTRIBUTE)
            .convert(Uri.encodeComponent(normalize(join(path, name))));
        var encodedName = new HtmlEscape().convert(name);

    <td><a href="$encodedLink">$encodedName</a></td>
    <td>$encodedModified</td>
    <td style="text-align: right">$encodedSize</td>
        } catch (e) {
          print(e);
        }
    var path = Uri.decodeComponent(request.uri.path);
    var encodedPath = new HtmlEscape().convert(path);
    var encodedReason = new HtmlEscape().convert(response.reasonPhrase);
    var encodedError = new HtmlEscape().convert(error.toString());
<title>$encodedReason: $encodedPath</title>
<h1>Error $encodedError at \'$encodedPath\': $encodedReason</h1>
            expect(result, contains('Index of &#x2F'));
            expect(result, contains('Index of &#x2F'));
            expect(result, contains('Index of &#x2F'));
          });
      });

      testVirtualDir('encoded-dir', (dir) {
        var virDir = new VirtualDirectory(dir.path);
        new Directory('${dir.path}/alert(\'hacked!\');').createSync();
        virDir.allowDirectoryListing = true;

        return getAsString(virDir, '/alert(\'hacked!\');')
          .then((result) {
            expect(result, contains('&#x2F;alert(&#x27;hacked!&#x27;);&#x2F;'));
          });
      });

      testVirtualDir('encoded-path', (dir) {
        var virDir = new VirtualDirectory(dir.path);
        new Directory('${dir.path}/javascript:alert(document);"').createSync();
        virDir.allowDirectoryListing = true;

        return getAsString(virDir, '/')
          .then((result) {
            expect(result, contains('%2Fjavascript%3Aalert(document)%3B%22'));
          });
      });

      testVirtualDir('encoded-special', (dir) {
        var virDir = new VirtualDirectory(dir.path);
        new Directory('${dir.path}/<>&"').createSync();
        virDir.allowDirectoryListing = true;

        return getAsString(virDir, '/')
          .then((result) {
            expect(result, contains('&lt;&gt;&amp;&quot;&#x2F;'));
            expect(result, contains('href="%2F%3C%3E%26%22"'));
                  (s) => s.contains('recursive&#x2F;')),
                  (s) => s.contains('Index of &#x2F;')),
                  (s) => s.contains('recursive&#x2F;')),
                  (s) => s.contains('..&#x2F;')),
                  (s) => s.contains('Index of &#x2F;recursive'))])