ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Notepad++_v7.6.3 Command Injection
    System/Windows 2019. 6. 13. 23:37

    얼마전에 Windows 기본 프로그램 메모장에서 RCE가 발견됐다는 기사를 본 적이 있었다.

    보자마자 드는 생각이 '가능해?'라는 생각이 들었는데, Notepad++ 에서도 취약점이 발견됐다고 한다.


    이것도 마찬가지로 처음에 드는 생각이 '가능한가?' 였다.

    나는 Notepad++를 써본 적이 없어서 기본 메모장처럼 글만 쓰는 아주 베이직한 프로그램일 줄 알았다.


    근데 공격벡터가 아예 없는건 아니였다.

    Search Engine을 설정해서 구글이나 야후등의 검색 서비스 기능도 있었고,

    각종 플러그인으로 추가적인 기능들을 프로그램에서 사용할 수 있었다.


    이번에 발견된 취약점 재현 절차는 다음과 같으며, v7.6.3이하의 버전에서만 유효하다.

    1. [설정] - [환경 설정] - [Search Engine]에서 사용자의 Custom Engine을 정의할 수 있다.


    2. Custom Engine 설정칸에 커맨드를 입력한다. (cmd /k calc)


    3. [편집] - [선택 시] - [인터넷에서 검색] 을 선택하는 순간 입력했던 커맨드가 실행된다.

    출처: https://hackerone.com/reports/495382


    [ Exploit! ]


    [ Vuln Analysis ]

    Notepad++은 오픈소스로 공개된 프로그램이기 때문에 깃허브에서 소스코드를 받아볼 수 있다.


    [Notepad++ Github]

    https://github.com/notepad-plus-plus/notepad-plus-plus


    PowerEditor/src/NppCommands.cpp ]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    case IDM_EDIT_SEARCHONINTERNET:
            {
                if (_pEditView->execute(SCI_GETSELECTIONS) != 1// Multi-Selection || Column mode || no selection
                    return;
     
                const NppGUI & nppGui = (NppParameters::getInstance())->getNppGUI();
                generic_string url;
                if (nppGui._searchEngineChoice == nppGui.se_custom)
                {
                    if (nppGui._searchEngineCustom.empty())
                    {
                        url = TEXT("https://www.google.com/search?q=$(CURRENT_WORD)");
                    }
                    else
                    {
                        url = nppGui._searchEngineCustom.c_str();
                    }
                }
                else if (nppGui._searchEngineChoice == nppGui.se_duckDuckGo)
                {
                    url = TEXT("https://duckduckgo.com/?q=$(CURRENT_WORD)");
                }
                else if (nppGui._searchEngineChoice == nppGui.se_google)
                {
                    url = TEXT("https://www.google.com/search?q=$(CURRENT_WORD)");
                }
                else if (nppGui._searchEngineChoice == nppGui.se_bing)
                {
                    url = TEXT("https://www.bing.com/search?q=$(CURRENT_WORD)");
                }
                else if (nppGui._searchEngineChoice == nppGui.se_yahoo)
                {
                    url = TEXT("https://search.yahoo.com/search?q=$(CURRENT_WORD)");
                }
     
                Command cmd(url.c_str());
                cmd.run(_pPublicInterface->getHSelf());    
            }
            break;
    cs

    취약점은 위 코드에서 발생된다.


    [편집] - [선택 시] - [인터넷에서 검색] 옵션을 클릭하면 실행되는 코드인데


     if (nppGui._searchEngineChoice == nppGui.se_custom)
                {
                    if (nppGui._searchEngineCustom.empty())
                    {
                        url = TEXT("https://www.google.com/search?q=$(CURRENT_WORD)");
                    }
                    else
                    {
                        url = nppGui._searchEngineCustom.c_str();
                    }
                }

    검색엔진이 Custom Engine으로 설정되어 있으면 위 분기문에 진입한다.

    만약, 선택만 되어있고 설정칸이 비어 있으면 google로 설정하고

    설정칸에 값이 있으면 url변수에 사용자가 입력한 값을 저장한다.



              
      Command cmd(url.c_str());
                cmd.run(_pPublicInterface->getHSelf());  

    그 후, 별도의 검사없이 cmd.run( )으로 명령을 실행한다.


    정상적인 경우라면 

    https://www.google.com/search?q=$(CURRENT_WORD)

    이런 값이 cmd( )의 인자로 넘어가서 브라우저가 실행 됐겠지만,

    사용자가 URL이 아닌 임의의 명령을 넣어놨을 경우, 해당 명령이 실행되는 취약점이 발생하게 되는 것이다.


    [ How to Patch? ]

    해당 취약점은 어떻게 패치되었는지 확인해보자

    취약점은 v7.6.4에서 패치되었으며, 아래는 패치된 코드 부분이다.



    [ Notepad++ v7.6.4 ]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (nppGui._searchEngineChoice == nppGui.se_custom)
                {
                    url = nppGui._searchEngineCustom;
                    remove_if(url.begin(), url.end(), isspace);
     
                    auto httpPos = url.find(TEXT("http://"));
                    auto httpsPos = url.find(TEXT("https://"));
     
                    if (url.empty() || (httpPos != 0 && httpsPos != 0)) 
                    {
                        url = TEXT("https://www.google.com/search?q=$(CURRENT_WORD)");
                    }
    // if string is not a url (for launching only browser)
                }

    cs

    취약점이 패치된 버전인 v7.6.4에는 위 코드가 추가되었다.


    [ 첫 번째 패치포인트 ]

    remove_if(url.begin(), url.end(), isspace);

    - 명령의 인자를 넘기기위해 사용되는 공백값을 검사하고, 만약에 발견되면 없앤다.


    [두 번째 패치포인트 ]

                    auto httpPos = url.find(TEXT("http://"));
                    auto httpsPos = url.find(TEXT("https://"));
     
                    if (url.empty() || (httpPos != 0 && httpsPos != 0)) 
                    {
                        url = TEXT("https://www.google.com/search?q=$(CURRENT_WORD)");
                    }

    - 값의 "http://" 와 "https://" 포함되어 있는지 확인한다.

    그 후, 입력값이 없거나 HTTP포맷이 발견되지 않으면 Google로 강제 설정한다.


    [ 여담 ]

    처음 Notepad++에서 취약점이 발견됐다고 했을 때는 "오??" 했다가,

    취약점을 재현했을 때는 "음??" 했다가,

    취약점을 분석했을 때는 "오!!" 했다.


    "음??"이라는 반응의 이유를 말해보자면, 사실 소스코드 분석없이 Notepad++를 사용하다가

    저 취약점을 발견했을 때 나는 취약점으로 느끼지 않았을지도 모른다는 생각이 들었다.


    "음? 커맨드가 실행되네.." 하고 넘겼을지도 모르겠다.


    이 취약점이 트리거되려면, [편집] - [선택 시] - [인터넷에서 검색]을 누르는건 둘째 치고

    우선 설정창에 들어가서 검색엔진에 Command를 넣어줘야 한다.


    공격 시나리오를 생각해봤을 때, 카페에서 Notepad++를 사용하는 사람이 자리 비운틈에 설정을 바꾼다!

    뭐 이런 시나리오가 제일 현실적으로 떠오른다.


    한마디로 말하자면, 시나리오가 너무 제한적이다.


    그 때문인지 버그바운티도 100만원 선에서 책정된 것 같다.


    물론, 소스코드를 분석해보니 확실히 취약점이 맞다라는 생각이 든다.

    이렇게 Vulnerability의 범위를 좀 더 명확하게 알아가는 것 같다.

    'System > Windows' 카테고리의 다른 글

    Universal Calc Shellcode (+ExitProcess)  (0) 2020.01.26
    [Windows] ALMind 1day Exploit  (1) 2019.03.08
    [Windows] ALMind 1day Analysis  (3) 2019.03.08

    댓글

Designed by Tistory.