Closed Bug 527935 (CVE-2011-0067) Opened 15 years ago Closed 14 years ago

Untrusted events should not trigger autocomplete popup


(Core :: DOM: Editor, defect)

Windows XP
Not set



Tracking Status
blocking2.0 --- final+
blocking1.9.2 --- .17+
status1.9.2 --- .17-fixed
blocking1.9.1 --- .19+
status1.9.1 --- .19-fixed


(Reporter: bugzilla, Assigned: ehsan.akhgari)



(Whiteboard: [sg:moderate][3.6.x])


(12 files, 4 obsolete files)

348 bytes, text/java
647 bytes, application/java-vm
21.24 KB, text/javascript
7.82 KB, text/html
2.37 KB, text/html
2.27 KB, text/html
14.58 KB, patch
: review+
Details | Diff | Splinter Review
1.00 KB, patch
: review+
Details | Diff | Splinter Review
3.24 KB, patch
: review+
Details | Diff | Splinter Review
2.13 KB, patch
: review+
Details | Diff | Splinter Review
24.94 KB, patch
: approval1.9.2.17+
Details | Diff | Splinter Review
25.03 KB, patch
: approval1.9.1.19+
Details | Diff | Splinter Review
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv: Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Build Identifier: 

After bug 511615 was fixed, untrusted key events still cause the autocomplete popup to appear. By detecting whether or not the popup was triggered for certain inputs, it is possible to enumerate / brute force form history. 

Detection of the popup can be achieved with a Java applet placed underneath the text input. The applet will receive events when the popup disappears because its screen area needs to be repainted. This has been tested only on Windows XP, and I wouldn't expect this to work under composited desktop environments like Vista Aero or MacOS X.

The technique I used in bug 511615 required user interaction to work. This method is fully automatic, but it takes longer to get the data as it performs a blind true/false search of the form history. The page also needs to be visible and focused for this to work. 

Although getting lots of data from searchbar-history takes a while, an attack targeted at credit card data stored in form history would be very quick since the search space is mostly numeric.

Reproducible: Always

Steps to Reproduce:
1. Send untrusted key events to text input field
Actual Results:  
Autocomplete popup appears if value of text field matches form history

Expected Results:  
Autocomplete popup should not appear
Depends on: CVE-2009-3370
Attached file Java applet source
Attached file Java applet class
Attachment #411693 - Attachment mime type: text/x-c → text/javascript
Attached file Form history brute forcer (obsolete) —
The testcase doesn't work as attached - the Java class doesn't load due to the way bugzilla serves it. I will try to find somewhere else to host it.
Attachment #411692 - Attachment mime type: application/octet-stream → application/java-vm
This should work now. This testcase attempts to intelligently enumerate the data in searchbar-history. It will only work on the Firefox 3.5 branch since it assumes that autocomplete only matches the start of a string. There's no reason why it couldn't be made to work with awesomecomplete on 3.6 or the trunk, but that's left as an exercise for the reader :)
Attachment #411695 - Attachment is obsolete: true
dolske: want to take a whack at this one too?
Assignee: nobody → dolske
blocking1.9.1: --- → ?
Flags: blocking1.9.2?
Whiteboard: [sg:moderate]
blocking1.9.1: ? → .7+
I don't think this blocks the 3.6 release, but we'd obviously want to take a patch quickly for 3.6.1.
Flags: blocking1.9.2? → blocking1.9.2-
Looks like this gets caused by editor firing a (trusted) input event at us. Not sure how easy that will be to fix, editor being involved...
Whiteboard: [sg:moderate] → [sg:moderate][3.6.x]
Ever confirmed: true
This has lingered to the point where I'm pretty sure it won't get fixed in this upcoming release, which is sadmaking. Sorry, Paul. Moving to needed and hopefully we can get it next time.

cc'ing Ehsan if this has to do with editor, since that's now his bag. Dolske, can you work with him to make progress, here?
blocking1.9.1: .8+ → needed
blocking1.9.2: --- → needed
Bah, my fault, this slipped through the cracks. Will take another look this week.
I'm not having any luck getting a simplified version of this to work on trunk or 3.6. Not sure if I'm doing something wrong, or if this was fixed by some other change.

Paul, do you see if there's something wrong with this test? It's based on what you wrote, and I'd expect it to at least show the autocomplete dropdown. A testcase that does that should be be the minimum sufficient to demonstrate there's a problem (since your clever Java paint-detection applet can then make use of the presence of the popup to know if the current value matches something).
I needed to use setInterval to add a slight pause between clicking the button and sending the key events.
Yeah, so per comment 9 the autocomplete dropdown is getting triggered by a "trusted" input event [nsFormFillController::Input()]. We're already listening for keypress events (which have a working isTrusted flag), so we should just be able to drop the ::Input() code and drive everything from keypresses. But doing that makes typing not trigger the autocomplete, and if I add the ::Input()'s mController->HandleText() call to the keypress handler, I get odd autocomplete matching. *sigh*

We've previously had problems with the autocomplete code being finicky, so it just might be broken wrt to event timing/order.
blocking2.0: --- → ?
blocking2.0: ? → beta1+
Did bug 439716 touch any of the code involved here? The testcase from comment 13 still works in the latest trunk nightly.
--> beta2+, maybe later!
blocking2.0: beta1+ → beta2+
Indeed, later! I'd rather this appear in a beta, but will not be dogmatic about it.
blocking2.0: beta2+ → final+
The problem is that here we just fire all input events as trusted: <>.  We should keep track of whether the last keypress event was trusted or not, and then use that value to init the input event as trusted.

Note to myself: (from typing) (from the test case)
Assignee: dolske → ehsan
Attached patch Patch (v1) (obsolete) — Splinter Review
Attachment #495731 - Flags: review?(roc)
Component: Form Manager → Editor
Product: Toolkit → Core
QA Contact: form.manager → editor
Version: unspecified → Trunk
nsIEditor_MOZILLA_2_0_BRANCH should go in nsIEditor.idl.

Why the tristate? Why not just let the initial value be false?
Attached patch Patch (v2)Splinter Review
(In reply to comment #20)
> nsIEditor_MOZILLA_2_0_BRANCH should go in nsIEditor.idl.


> Why the tristate? Why not just let the initial value be false?

The value is *only* meaningful during keypress event processing.  I wanted to make the lastKeypressEventTrusted property access throw if someone calls it at the wrong time, to ensure that future code wouldn't use the property incorrectly.  But I can revert to using a simple boolean if you think this is not necessary.
Attachment #495731 - Attachment is obsolete: true
Attachment #495766 - Flags: review?(roc)
Attachment #495731 - Flags: review?(roc)
Dolske promised that he would take care of the test failures caused by this patch, so I guess we should expect a patch from him.  This was cleared to land on beta8 by release-drivers.
Whiteboard: [sg:moderate][3.6.x] → [sg:moderate][3.6.x][needs test fix from dolske]
I will look into doing the test fixes myself.
Whiteboard: [sg:moderate][3.6.x][needs test fix from dolske] → [sg:moderate][3.6.x][needs test fix from ehsan]
(In reply to comment #23)
> I will look into doing the test fixes myself.

Dolske said that he has a half-baked patch on this.  Can you please attach it to the bug?
Attached patch Test fix (not quite working) (obsolete) — Splinter Review
This _mostly_ fixes test_bug_511615.html, except for a single failure at the end (the test expects a "v" in the input, it finds the input to be empty). I don't understand why this is happening, apparently the simulated Escape-key press now causes the input to be cleared?

Ehsan: might be worth a try push to see if anything else is failing. I _might_ be willing to just make this test pass and investigate in a followup, but I'd really like to understand why this is happening.
So, this stack leads to the input value being cleared after pressing Escape at the end of the test:

(gdb) bt
#0  nsTextControlFrame::FireOnInput (this=0x101f517b0, aTrusted=0) at /Users/ehsanakhgari/moz/mozilla-central/layout/forms/nsTextControlFrame.cpp:1335
#1  0x00000001144d654f in nsTextInputListener::EditAction (this=0x12d670be0) at /Users/ehsanakhgari/moz/mozilla-central/content/html/content/src/nsTextEditorState.cpp:887
#2  0x000000011480536d in nsEditor::NotifyEditorObservers (this=0x11e5f69c0) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/base/nsEditor.cpp:1734
#3  0x0000000114814f0f in nsEditor::EndPlaceHolderTransaction (this=0x11e5f69c0) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/base/nsEditor.cpp:964
#4  0x00000001147fc727 in nsAutoPlaceHolderBatch::~nsAutoPlaceHolderBatch (this=0x7fff5fbfaa40) at nsEditorUtils.h:65
#5  0x00000001147f4bb1 in nsPlaintextEditor::DeleteSelection (this=0x11e5f69c0, aAction=0) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/text/nsPlaintextEditor.cpp:794
#6  0x00000001144d852c in nsTextEditorState::SetValue (this=0x11e523650, aValue=@0x7fff5fbfad40, aUserInput=1) at /Users/ehsanakhgari/moz/mozilla-central/content/html/content/src/nsTextEditorState.cpp:1824
#7  0x000000011450c032 in nsHTMLInputElement::SetValueInternal (this=0x11e523500, aValue=@0x7fff5fbfaec0, aUserInput=1, aSetValueChanged=1) at /Users/ehsanakhgari/moz/mozilla-central/content/html/content/src/nsHTMLInputElement.cpp:1410
#8  0x000000011450d9fe in nsHTMLInputElement::SetUserInput (this=0x11e523500, aValue=@0x7fff5fbfaec0) at /Users/ehsanakhgari/moz/mozilla-central/content/html/content/src/nsHTMLInputElement.cpp:1203
#9  0x00000001173663bc in nsFormFillController::SetTextValue (this=0x1217e4ce0, aTextValue=@0x7fff5fbfaec0) at /Users/ehsanakhgari/moz/mozilla-central/toolkit/components/satchel/src/nsFormFillController.cpp:481
#10 0x0000000117337ff6 in nsAutoCompleteController::RevertTextValue (this=0x121725660) at /Users/ehsanakhgari/moz/mozilla-central/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp:1209
#11 0x00000001173380fa in nsAutoCompleteController::HandleEscape (this=0x121725660, _retval=0x7fff5fbfb01c) at /Users/ehsanakhgari/moz/mozilla-central/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp:306
#12 0x00000001173662b7 in nsFormFillController::KeyPress (this=0x1217e4ce0, aEvent=0x12d6e0770) at /Users/ehsanakhgari/moz/mozilla-central/toolkit/components/satchel/src/nsFormFillController.cpp:864

The mSearchString set in SetInput is empty, while I _think_ it should be "v".  I'm investigating more.
OK, so I figured out what causes this problem.  Here is how we set mSearchString when the value of the text control is changed (after SetInput has been called):

(gdb) bt
#0  nsXXXString::operator= (this=0x1210d4c48, foo=@0x7fff5fbfbdb0) at nsAutoCompleteController.h:58
#1  0x000000011733d042 in nsAutoCompleteController::HandleText (this=0x1210d4be0) at /Users/ehsanakhgari/moz/mozilla-central/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp:258
#2  0x0000000117369bd1 in nsFormFillController::Input (this=0x12185d610, aEvent=0x12e62b4e0) at /Users/ehsanakhgari/moz/mozilla-central/toolkit/components/satchel/src/nsFormFillController.cpp:972
#3  0x00000001144fc221 in DispatchToInterface (aEvent=0x12e62b4e0, aListener=0x12185d640, aMethod={__pfn = 0x41, __delta = 0}, aIID=@0x114e87280) at /Users/ehsanakhgari/moz/mozilla-central/content/events/src/nsEventListenerManager.cpp:175
#4  0x00000001144fda25 in nsEventListenerManager::HandleEventInternal (this=0x121179020, aPresContext=0x124bd56b0, aEvent=0x7fff5fbfc450, aDOMEvent=0x7fff5fbfc1f0, aCurrentTarget=0x121085170, aFlags=4, aEventStatus=0x7fff5fbfc1f8, aPusher=0x7fff5fbfc210) at /Users/ehsanakhgari/moz/mozilla-central/content/events/src/nsEventListenerManager.cpp:1206
#5  0x000000011452dc93 in nsEventListenerManager::HandleEvent (this=0x121179020, aPresContext=0x124bd56b0, aEvent=0x7fff5fbfc450, aDOMEvent=0x7fff5fbfc1f0, aCurrentTarget=0x121085170, aFlags=4, aEventStatus=0x7fff5fbfc1f8, aPusher=0x7fff5fbfc210) at nsEventListenerManager.h:146
#6  0x000000011452de3e in nsEventTargetChainItem::HandleEvent (this=0x1012fb008, aVisitor=@0x7fff5fbfc1e0, aFlags=4, aMayHaveNewListenerManagers=0, aPusher=0x7fff5fbfc210) at /Users/ehsanakhgari/moz/mozilla-central/content/events/src/nsEventDispatcher.cpp:212
#7  0x000000011452c13c in nsEventTargetChainItem::HandleEventTargetChain (this=0x1012fa470, aVisitor=@0x7fff5fbfc1e0, aFlags=6, aCallback=0x7fff5fbfc320, aMayHaveNewListenerManagers=0, aPusher=0x7fff5fbfc210) at /Users/ehsanakhgari/moz/mozilla-central/content/events/src/nsEventDispatcher.cpp:311
#8  0x000000011452cee6 in nsEventDispatcher::Dispatch (aTarget=0x124d728f0, aPresContext=0x124bd56b0, aEvent=0x7fff5fbfc450, aDOMEvent=0x0, aEventStatus=0x7fff5fbfc4ac, aCallback=0x7fff5fbfc320, aTargets=0x0) at /Users/ehsanakhgari/moz/mozilla-central/content/events/src/nsEventDispatcher.cpp:628
#9  0x00000001140f2eeb in PresShell::HandleEventInternal (this=0x125909420, aEvent=0x7fff5fbfc450, aView=0x0, aStatus=0x7fff5fbfc4ac) at /Users/ehsanakhgari/moz/mozilla-central/layout/base/nsPresShell.cpp:6939
#10 0x00000001140f3b25 in PresShell::HandleEventWithTarget (this=0x125909420, aEvent=0x7fff5fbfc450, aFrame=0x0, aContent=0x124d728f0, aStatus=0x7fff5fbfc4ac) at /Users/ehsanakhgari/moz/mozilla-central/layout/base/nsPresShell.cpp:6788
#11 0x000000011412a211 in nsTextControlFrame::FireOnInput (this=0x124314b40, aTrusted=1) at /Users/ehsanakhgari/moz/mozilla-central/layout/forms/nsTextControlFrame.cpp:1345
#12 0x000000011455b54f in nsTextInputListener::EditAction (this=0x124d5b020) at /Users/ehsanakhgari/moz/mozilla-central/content/html/content/src/nsTextEditorState.cpp:887
#13 0x000000011488a36d in nsEditor::NotifyEditorObservers (this=0x1259c7a70) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/base/nsEditor.cpp:1734
#14 0x0000000114899f0f in nsEditor::EndPlaceHolderTransaction (this=0x1259c7a70) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/base/nsEditor.cpp:964
#15 0x0000000114881727 in nsAutoPlaceHolderBatch::~nsAutoPlaceHolderBatch (this=0x7fff5fbfc750) at nsEditorUtils.h:65
#16 0x0000000114879bb1 in nsPlaintextEditor::DeleteSelection (this=0x1259c7a70, aAction=2) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/text/nsPlaintextEditor.cpp:794
#17 0x000000011488bb92 in nsEditor::HandleKeyPressEvent (this=0x1259c7a70, aKeyEvent=0x124db9158) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/base/nsEditor.cpp:5047
#18 0x000000011487ed85 in nsPlaintextEditor::HandleKeyPressEvent (this=0x1259c7a70, aKeyEvent=0x124db9158) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/text/nsPlaintextEditor.cpp:382
#19 0x00000001148aa396 in nsEditorEventListener::KeyPress (this=0x120c93830, aKeyEvent=0x124db90c0) at /Users/ehsanakhgari/moz/mozilla-central/editor/libeditor/base/nsEditorEventListener.cpp:362

Note that we're using the input event.  This means that for non-privileged events, mSearchString will not be set correctly, because the input event will  be ignored because of this check <>.  In practice, this means that if the content javascript modifies the content of the text box when the popup is open, pressing Escape will reset the popup to the value that the user had entered manually.  I think this is fine, and this is certainly the intention of the original code, so I'm just going to submit a modified patch which corrects this test.

Also, this patch causes some other failures besides this test as well <>.  I'm investigating them now.
One of the test failures (in test_input_events_on_deactive_window.xul) was caused because the IME transaction commit was not generating the input event, while it was privileged.  We need to take the editor IME transaction commit events' trustedness into account too.
Attachment #498409 - Flags: review?(roc)
With the additional test fix.
Attachment #498415 - Flags: review?(dolske)
Attachment #498011 - Attachment is obsolete: true
The other test failure (in browser_bug321000.js) is caused because this patch does not let input events to be raised on paste operations.  As paste's are already privileged actions, we can safely allow raising the input event for paste operations.

I'm also adding a test to test this explicitly.
Attachment #498426 - Flags: review?(roc)
Attachment #498415 - Flags: review?(dolske) → review+
Whiteboard: [sg:moderate][3.6.x][needs test fix from ehsan] → [sg:moderate][3.6.x][needs landing]
Closed: 14 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Whiteboard: [sg:moderate][3.6.x][needs landing] → [sg:moderate][3.6.x]
Target Milestone: --- → mozilla2.0b9
The fix to bug 625452 should be considered before the fix here can be landed on branches.
Depends on: 625452
Whiteboard: [sg:moderate][3.6.x] → [sg:moderate][3.6.x][branch landing needs bug 625452]
Depends on: 626411
blocking1.9.1: needed → .18+
blocking1.9.2: needed → .15+
Comment on attachment 495766 [details] [diff] [review]
Patch (v2)

Requesting approval on *all* of the patches in this bug.
Attachment #495766 - Flags: approval1.9.2.15?
Attachment #495766 - Flags: approval1.9.1.18?
Whiteboard: [sg:moderate][3.6.x][branch landing needs bug 625452] → [sg:moderate][3.6.x][branch landing needs bug 625452 and bug 626411]
(In reply to comment #33)
> Requesting approval on *all* of the patches in this bug.

Do these apply as-is? If so please add approval requests to signal that you've looked at them. If not what we'd really like is one big "1.9.2 branch patch" that includes the patches here plus the required bug 625452 and 626411. What we've found (unfortunately) is that people will grab the approved patches, and not whatever merges you in fact end up doing to get it into the tree. Between the three bugs it's hard to believe they will land cleanly on a different branch.
Fair enough.  I'll attach rolled up patches here then.
Well, good thing you brought this up!  Barely a single hunk of these patches apply cleanly.  I need to basically port the code to 1.9.2 and 1.9.1.

Here's two questions:

1. What should I use instead of the _MOZILLA_2_0_BRANCH for interface suffixes?  _MOZILLA_1_9_2_BRANCH and _MOZILLA_1_9_1_BRANCH?

2. This is going to take some time porting and testing on each branch.  How should I prioritize this over 2.0 blockers?
Comment on attachment 495766 [details] [diff] [review]
Patch (v2)

need a merged version for branches, not approved
Attachment #495766 - Flags: approval1.9.2.15?
Attachment #495766 - Flags: approval1.9.2.15-
Attachment #495766 - Flags: approval1.9.1.18?
Attachment #495766 - Flags: approval1.9.1.18-
(In reply to comment #36)
> 1. What should I use instead of the _MOZILLA_2_0_BRANCH for interface suffixes?

if they're different use those. If it ends up being the same for both 1.9.x branches you could use the same for both (1_9_2 is fine).

> 2. This is going to take some time porting and testing on each branch.  How
> should I prioritize this over 2.0 blockers?

Lower priority than hardblockers (of which you appear to have none) and IMHO higher than "soft" blockers.
Whiteboard: [sg:moderate][3.6.x][branch landing needs bug 625452 and bug 626411] → [sg:moderate][3.6.x]
Attached patch 1.9.2 patch (obsolete) — Splinter Review
This is the patch I ported to 1.9.2 and tested there.  I've submitted it to the try server as well (
Attachment #509318 - Flags: approval1.9.2.15?
Attached patch 1.9.2 patchSplinter Review
Added a test file which was missing from the patch.
Attachment #509318 - Attachment is obsolete: true
Attachment #509336 - Flags: approval1.9.2.15?
Attachment #509318 - Flags: approval1.9.2.15?
Attached patch 1.9.1 patchSplinter Review
Attachment #509348 - Flags: approval1.9.1.18?
Is it OK for the nsIEditor_MOZILLA_1_9_2_BRANCH interface on 1.9.1 and 1.9.2 to have the same uuid?  (I made sure that the uuid of nsIEditor_MOZILLA_1_9_2_BRANCH is different to the uuid of nsIEditor_MOZILLA_1_2_0_BRANCH as used on trunk).
Attachment #509336 - Flags: approval1.9.2.15? → approval1.9.2.15+
Attachment #509348 - Flags: approval1.9.1.18? → approval1.9.1.18+
I'd rather to land it sooner so that it gets on the nightlies if possible, FWIW.
Well, I didn't see the a+'es there obviously!
FWIW, the landing was all green sans an instance of bug 550963 on 1.9.1.  :-)
The "3.6.15" we're releasing today does not fix this bug, the release containing this bug fix has been renamed to "3.6.16" and the bugzilla flags will be updated to reflect that soon. Today's release is a re-release of 3.6.14 plus a fix for a bug that prevented many Java applets from starting up.
Alias: CVE-2011-0067
Group: core-security
You need to log in before you can comment on or make changes to this bug.