T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/hwp_batch_convert.py:338- Finding
Automatic Security-Dialog Approval Is Not Restricted to the Converter Process
- Content
View full analysis
Vulnerability Details
File Location:
scripts/hwp_batch_convert.py, lines 338–360
Vulnerability Type: Improper process authorization for desktop UI automation
Risk Level: MediumVulnerable Code
python USER32.EnumWindows(enum_proc, 0) for hwnd in hwnds: if hwnd in self._handled_hwnds or not USER32.IsWindowVisible(hwnd): continue title = USER32.GetWindowTextLengthW(hwnd) if title <= 0: continue window_title = ctypes.create_unicode_buffer(title + 1) USER32.GetWindowTextW(hwnd, window_title, title + 1) if window_title.value.strip() not in DIALOG_TITLE_WHITELIST: continue text_parts, allow_button_hwnd, allow_button_text = self._inspect_dialog(hwnd) window_text = ' '.join(part for part in text_parts if part).strip() reason = self._classify_candidate( window_title.value.strip(), window_text, allow_button_text, ) if reason != 'match': if window_text: self._record_event( AutoDialogEvent( window_title=window_title.value.strip(), window_text=window_text, button_text=allow_button_text, clicked=False, reason=reason, ) ) self._handled_hwnds.add(hwnd) continue clicked = False if allow_button_hwnd: USER32.SendMessageW(allow_button_hwnd, BM_CLICK, 0, 0) clicked = TrueThe converter records process ownership information at lines 403 and 429, but the dialog watcher does not use it:
python self.owned_pids: set[int] = set()python self.owned_pids = _snapshot_hwp_pids() - before_pidsTechnical Analysis
When
--auto-allow-dialogsis enabled in real mode,AutoAllowDialogWatcherenumerates every top-level window on the user's interactive desktop. It approves a dialog based only on the following UI properties:- The top-level window tit ...[truncated 2551 chars]
- Remediation
View remediation
Remediation Suggestions
-
Restrict eligible windows by process ID
- Pass a verified set of converter-owned process IDs into
AutoAllowDialogWatcher. - Call
GetWindowThreadProcessIdfor each candidate top-level window. - Reject the window unless its PID is in the verified ownership set.
- Pass a verified set of converter-owned process IDs into
-
Fail closed when ownership cannot be established
- Do not enable automatic approval if
owned_pidsis empty or process discovery fails. - Record a warning and require manual interaction instead.
- Do not enable automatic approval if
-
Validate executable identity
- Resolve the candidate PID's executable path.
- Confirm that the executable is an expected Hancom binary in a trusted installation location.
- Do not rely solely on process names such as
hwp.exe.
-
Strengthen window validation
- Validate expected top-level and child window classes.
- Confirm that the candidate window is associated with the COM instance used for conversion where the API permits.
- Retain the existing exact-title, body-keyword, and button-label checks as secondary controls rather than ownership proof.
-
Minimize the approval window
- Start the watcher immediately before the specific COM operation that may display the prompt.
- Stop it immediately after that operation completes instead of keeping it active across the entire batch.
-
Avoid global UI approval where possible
- Prefer a documented Hancom API or trusted security module registration mechanism that scopes permission to the automation instance.
- If reliable process binding is unavailable, disable automatic clicking and require explicit user confirmation.
-
