CVE-2023-46300 (published 2023-10-22T04:15Z)

iTerm2 before 3.4.20 allow (potentially remote) code execution because of mishandling of certain escape sequences related to tmux integration.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-116
cwe_name: Improper Encoding or Escaping of Output
description: The product prepares a structured message for communication with another component, but encoding or escaping of the data is either missing or done incorrectly. As a result, the intended structure of the message is not preserved.
extended_description: 
            Improper encoding or escaping can allow attackers to change the commands that are sent to another component, inserting malicious commands instead.
            Most products follow a certain protocol that uses structured messages for communication between components, such as queries or commands. These structured messages can contain raw data interspersed with metadata or control information. For example, "GET /index.html HTTP/1.1" is a structured message containing a command ("GET") with a single argument ("/index.html") and metadata about which protocol version is being used ("HTTP/1.1").
            If an application uses attacker-supplied inputs to construct a structured message without properly encoding or escaping, then the attacker could insert special characters that will cause the data to be interpreted as control information or metadata. Consequently, the component that receives the output will perform the wrong operations, or otherwise interpret the data incorrectly.
         
         

Fix information:
repo_url: https://github.com/gnachman/iTerm2
commit_details: repo_url: https://github.com/gnachman/iTerm2
author: George Nachman
author_date: 2023-08-03 10:50:30-07:00
msg: Fixes for method 1.

Remove DECSCPP and DECNLS.
Sanitize title reports to remove risky characters.
repository: repo_url: https://github.com/gnachman/iTerm2
repo_name: gnachman/iTerm2
description: iTerm2 is a terminal emulator for Mac OS X that does amazing things.
repo_language: Objective-C
owner: gnachman
file_changes: filename: VT100Terminal.m
change_type: ModificationType.MODIFY
diff: @@ -2798,7 +2798,7 @@ static BOOL VT100TokenIsTmux(VT100Token *token) {
         }
         case XTERMCC_REPORT_ICON_TITLE: {
             NSString *s = [NSString stringWithFormat:@"\033]L%@\033\\",
-                           [_delegate terminalIconTitle]];
+                           [self reportSafeTitle:[_delegate terminalIconTitle]]];
             [_delegate terminalSendReport:[s dataUsingEncoding:NSUTF8StringEncoding]];
             break;
         }
@@ -2807,7 +2807,7 @@ static BOOL VT100TokenIsTmux(VT100Token *token) {
             // That was wrong and may cause bug reports due to breaking bugward compatibility.
             // (see xterm docs)
             NSString *s = [NSString stringWithFormat:@"\033]l%@\033\\",
-                           [_delegate terminalWindowTitle]];
+                           [self reportSafeTitle:[_delegate terminalWindowTitle]]];
             [_delegate terminalSendReport:[s dataUsingEncoding:NSUTF8StringEncoding]];
             break;
         }
@@ -3460,14 +3460,6 @@ static BOOL VT100TokenIsTmux(VT100Token *token) {
     return [@(height) stringValue];
  }
 
-- (NSString *)decrqssDECSCPP {
-    return self.columnMode ? @"132" : @"80";
-}
-
-- (NSString *)decrqssDECNLS {
-    return [@([self.delegate terminalSizeInCells].height) stringValue];
-}
-
 - (iTermPromise<NSString *> *)decrqssPayloadPromise:(NSString *)pt {
     if ([pt isEqualToString:@"m"]) {
         return [iTermPromise promiseValue:[self decrqssSGR]];
@@ -3490,12 +3482,7 @@ static BOOL VT100TokenIsTmux(VT100Token *token) {
     if ([pt isEqualToString:@"t"]) {
         return [iTermPromise promiseValue:[self decrqssDECSLPP]];
     }
-    if ([pt isEqualToString:@"$|"]) {
-        return [iTermPromise promiseValue:[self decrqssDECSCPP]];
-    }
-    if ([pt isEqualToString:@"*|"]) {
-        return [iTermPromise promiseValue:[self decrqssDECNLS]];
-    }
+    // DECSCPP and DECNLS not supported for security reasons.
 
     return [iTermPromise promiseDefaultError];
 }
@@ -5303,6 +5290,20 @@ static iTermPromise<NSNumber *> *VT100TerminalPromiseOfDECRPMSettingFromBoolean(
     return [title substringFromIndex:NSMaxRange(newlineRange)];
 }
 
+// Convert a title into a string that is safe to transmit in a report.
+// The goal is to make it hard for an attacker to issue a report that could be part of a command.
+- (NSString *)reportSafeTitle:(NSString *)unsafeTitle {
+    NSCharacterSet *unsafeSet = [NSCharacterSet characterSetWithCharactersInString:@"|;\r\n\e"];
+    NSString *result = unsafeTitle;
+    NSRange range;
+    range = [result rangeOfCharacterFromSet:unsafeSet];
+    while (range.location != NSNotFound) {
+        result = [result stringByReplacingCharactersInRange:range withString:@" "];
+        range = [result rangeOfCharacterFromSet:unsafeSet];
+    }
+    return result;
+}
+// This is used for titles received from the remote host.
 - (NSString *)sanitizedTitle:(NSString *)unsafeTitle {
     // Very long titles are slow to draw in the tabs. Limit their length and
     // cut off anything after newline since it wouldn't be visible anyway.

programming_language: Objective-C
repo_url: https://github.com/gnachman/iTerm2
commit_details: repo_url: https://github.com/gnachman/iTerm2
author: George Nachman
author_date: 2023-08-03 11:05:41-07:00
msg: Fix for method 1 and 2.

Send ^C as the first character of output when entering tmux integration mode.
repository: repo_url: https://github.com/gnachman/iTerm2
repo_name: gnachman/iTerm2
description: iTerm2 is a terminal emulator for Mac OS X that does amazing things.
repo_language: Objective-C
owner: gnachman
file_changes: filename: PTYSession.m
change_type: ModificationType.MODIFY
diff: @@ -7890,6 +7890,7 @@ scrollToFirstResult:(BOOL)scrollToFirstResult {
 // opened. Initial window opening is always blocked on establishing the server version.
 - (void)kickOffTmux {
     _haveKickedOffTmux = YES;
+    [_tmuxController sendControlC];
     [_tmuxController ping];
     [_tmuxController validateOptions];
     [_tmuxController checkForUTF8];

programming_language: Objective-C
filename: TmuxController.h
change_type: ModificationType.MODIFY
diff: @@ -131,6 +131,7 @@ extern NSString *const kTmuxControllerDidChangeHiddenWindows;
 - (void)fitLayoutToWindows;
 - (void)validateOptions;
 - (void)ping;
+- (void)sendControlC;
 - (void)enablePauseModeIfPossible;
 - (void)unpausePanes:(NSArray<NSNumber *> *)wps;
 - (void)pausePanes:(NSArray<NSNumber *> *)wps;

programming_language: Objective-C
filename: TmuxController.m
change_type: ModificationType.MODIFY
diff: @@ -1081,6 +1081,14 @@ static NSDictionary *iTermTmuxControllerDefaultFontOverridesFromProfile(Profile
     [gateway_ sendCommandList:commands];
 }
 
+- (void)sendControlC {
+    [gateway_ sendCommand:[NSString stringWithFormat:@"%cphony-command", 3]
+           responseTarget:nil
+         responseSelector:nil
+           responseObject:nil
+                    flags:kTmuxGatewayCommandShouldTolerateErrors];
+}
+
 - (void)ping {
     // This command requires tmux 3.2, but if it fails that's OK too.
     [gateway_ sendCommand:@"refresh-client -fpause-after=0,wait-exit"

programming_language: Objective-C