summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/mochitest/test_form_action_2.html
blob: 2eae0958cabcf617586d66dbee50f39fffc59273 (plain)
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>Test for considering form action</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="pwmgr_common.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
Login Manager test: Bug 360493
<script>
gTestDependsOnDeprecatedLogin = true;
runChecksAfterCommonInit(() => startTest());

let DEFAULT_ORIGIN = window.location.origin;
</script>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">

/** Test for Login Manager: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/

async function startTest() {
  let win = window.open("about:blank");
  SimpleTest.registerCleanupFunction(() => win.close());
  await loadFormIntoWindow(DEFAULT_ORIGIN, `
    <!-- The tests in this page exercise things that shouldn't work. -->

    <!-- Change port # of action URL from 8888 to 7777 -->
    <form id="form1" action="http://localhost:7777/tests/toolkit/components/passwordmgr/test/formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- No port # in action URL -->
    <form id="form2" action="http://localhost/tests/toolkit/components/passwordmgr/test/formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Change protocol from http:// to ftp://, include the expected 8888 port # -->
    <form id="form3" action="ftp://localhost:8888/tests/toolkit/components/passwordmgr/test/formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Change protocol from http:// to ftp://, no port # specified -->
    <form id="form4" action="ftp://localhost/tests/toolkit/components/passwordmgr/test/formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Try a weird URL. -->
    <form id="form5" action="about:blank">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Try a weird URL. (If the normal embedded action URL doesn't work, that should mean other URLs won't either) -->
    <form id="form6" action="view-source:http://localhost:8888/tests/toolkit/components/passwordmgr/test/formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Try a weird URL. -->
    <form id="form7" action="view-source:formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Action URL points to a different host (this is the archetypical exploit) -->
    <form id="form8" action="http://www.cnn.com/">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Action URL points to a different host, user field prefilled -->
    <form id="form9" action="http://www.cnn.com/">
      <input  type="text"       name="uname" value="testuser">
      <input  type="password"   name="pword">

      <button type="submit">Submit</button>
      <button type="reset"> Reset </button>
    </form>

    <!-- Try wrapping a evil form around a good form, to see if we can confuse the parser. -->
    <form id="form10-A" action="http://www.cnn.com/">
     <form id="form10-B" action="formtest.js">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit (inner)</button>
      <button type="reset"> Reset  (inner)</button>
     </form>
     <button type="submit" id="neutered_submit10">Submit (outer)</button>
     <button type="reset">Reset (outer)</button>
    </form>

    <!-- Try wrapping a good form around an evil form, to see if we can confuse the parser. -->
    <form id="form11-A" action="formtest.js">
     <form id="form11-B" action="http://www.cnn.com/">
      <input  type="text"       name="uname">
      <input  type="password"   name="pword">

      <button type="submit">Submit (inner)</button>
      <button type="reset"> Reset  (inner)</button>
     </form>
     <button type="submit" id="neutered_submit11">Submit (outer)</button>
     <button type="reset">Reset (outer)</button>
    </form>`, win, 11);

  // TODO: probably should have some accounts which have no port # in the action url.
  // JS too. And different host/proto.
  // TODO: www.site.com vs. site.com?
  // TODO: foo.site.com vs. bar.site.com?

  for (var i = 1; i <= 8; i++) {
    // Check form i
    await checkLoginFormInFrameWithElementValues(win, i, "", "");
  }

  await checkLoginFormInFrameWithElementValues(win, 9, "testuser", "");

  await checkLoginFormInFrameWithElementValues(win, "10-A", "", "");

  // The DOM indicates this form could be filled, as the evil inner form
  // is discarded. And yet pwmgr seems not to fill it. Not sure why.
  todo(false, "Mangled form combo not being filled when maybe it could be?");
  await checkLoginFormInFrameWithElementValues(win, "11-A", "testuser", "testpass");

  // Verify this by making sure there are no extra forms in the document, and
  // that the submit button for the neutered forms don't do anything.
  // If the test finds extra forms the submit() causes the test to timeout, then
  // there may be a security issue.
  await SpecialPowers.spawn(win, [], async function submitForms() {
    is(this.content.document.forms.length, 11, "Checking for unexpected forms");
    this.content.document.getElementById("neutered_submit10").click();
    this.content.document.getElementById("neutered_submit11").click();
  });

  SimpleTest.finish();
}
</script>
</pre>
</body>
</html>