취약점 제보글: https://hackerone.com/reports/480883
notepad-plus-plus/PowerEditor/src/Notepad_plus.cpp의 xml파싱 기능중 오버플로우가 존재한다는 내용입니다.
Notepad++는 오픈소스 프로젝트로 공식 github에서 소스코드를 다운로드 받을 수 있습니다.
https://github.com/notepad-plus-plus/notepad-plus-plus/releases/tag/v7.6.2 취약점이 존재하는 7.6.2버전의 소스코드를 다운로드 받고, 해당 부분을 분석해보겠습니다.
949번째 줄 부터 시작되는 getHtmlXmlEncoding함수입니다.
int Notepad_plus::getHtmlXmlEncoding(const TCHAR *fileName) const
{
// Get Language type
TCHAR *ext = PathFindExtension(fileName);
if (*ext == '.') //extension found
{
ext += 1;
}
else
{
return -1;
}
NppParameters *pNppParamInst = NppParameters::getInstance();
LangType langT = pNppParamInst->getLangFromExt(ext);
if ((langT != L_XML) && (langT != L_HTML))
return -1;
가장 처음 부분에 fileName으로 파일의 확장자를 받아서 ext에 저장하는 것을 볼 수 있습니다.
이후 getLangFromExt함수로 해당 파일의 언어 타입을 받아와 XML과 HTML이 아닌 경우 return을 하게됩니다.
// Get the beginning of file data
FILE *f = generic_fopen(fileName, TEXT("rb"));
if (!f)
return -1;
const int blockSize = 1024; // To ensure that length is long enough to capture the encoding in html
char data[blockSize];
size_t lenFile = fread(data, 1, blockSize, f);
fclose(f);
// Put data in _invisibleEditView
_invisibleEditView.execute(SCI_CLEARALL);
_invisibleEditView.execute(SCI_APPENDTEXT, lenFile, reinterpret_cast<LPARAM>(data));
const char *encodingAliasRegExpr = "[a-zA-Z0-9_-]+";
이후 파일을 열고 xml의 encoding부분을 받아오기 위해 1024바이트 만큼 파일을 읽어옵니다.
if (langT == L_XML)
{
// find encoding by RegExpr
const char *xmlHeaderRegExpr = "<?xml[ \\t]+version[ \\t]*=[ \\t]*\"[^\"]+\"[ \\t]+encoding[ \\t]*=[ \\t]*\"[^\"]+\"[ \\t]*.*?>";
size_t startPos = 0;
size_t endPos = lenFile-1;
_invisibleEditView.execute(SCI_SETSEARCHFLAGS, SCFIND_REGEXP|SCFIND_POSIX);
_invisibleEditView.execute(SCI_SETTARGETRANGE, startPos, endPos);
auto posFound = _invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(xmlHeaderRegExpr), reinterpret_cast<LPARAM>(xmlHeaderRegExpr));
if (posFound != -1 && posFound != -2)
{
const char *encodingBlockRegExpr = "encoding[ \\t]*=[ \\t]*\"[^\".]+\"";
_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(encodingBlockRegExpr), reinterpret_cast<LPARAM>(encodingBlockRegExpr));
const char *encodingRegExpr = "\".+\"";
_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(encodingRegExpr), reinterpret_cast<LPARAM>(encodingRegExpr));
_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(encodingAliasRegExpr), reinterpret_cast<LPARAM>(encodingAliasRegExpr));
startPos = int(_invisibleEditView.execute(SCI_GETTARGETSTART));
endPos = _invisibleEditView.execute(SCI_GETTARGETEND);
char encodingStr[128];
_invisibleEditView.getText(encodingStr, startPos, endPos);
EncodingMapper *em = EncodingMapper::getInstance();
int enc = em->getEncodingFromString(encodingStr);
return (enc==CP_ACP?-1:enc);
startPos와 endPos를 초기화 해둔 뒤, 아래 부분에서 SCI_GETTARGETSTART와 SCI_GETTARGETEND로 encoding부분의 시작과 끝을 구합니다.
그 뒤 getText함수로 128바이트의 encodingStr에 startPos와 endPos사이의 데이터를 받아옵니다.
이때 encoding을 받아오는 배열이 128바이트로 정해져 있기 때문에 encoding이 128바이트가 넘어가면 버퍼오버플로우가 발생하게됩니다.
'Security > Windows Exploit' 카테고리의 다른 글
[CVE-2018-10027] 알집 load malicious DLL 취약점 분석 (0) | 2020.08.21 |
---|---|
[CVE-2011-1336]알집 mim 파일 버퍼 오버플로우 분석 (0) | 2020.08.17 |
아드레날린 2.2.5.3 플레이리스트 파일 wvx overflow 취약점 one day exploit 분석 (0) | 2020.07.14 |