Усё новае — гэта добра забытае старое

Усё новае — гэта добра забытае старое

Падчас рэагавання на інцыдэнт у нацыянальным сегменце сеткі Інтэрнэт камандай CERT.BY была выяўлена актыўнасць APT-групоўкі «Cloud Atlas». У гэтым матэрыяле не будзе разгледжана поўная ланцужковая схема кампраметацыі — увага засяроджана на вектары пачатковага доступу ў арганізацыю.

Для атрымання доступу ў арганізацыю быў выкарыстаны класічны метад — фішынг з укладаннем. У якасці шкоднаснай нагрузкі выкарыстоўваўся тэкставы дакумент. Нягледзячы на наяўнасць ахоўных сродкаў і актуальнасць абнаўленняў, дакумент быў дастаўлены канчатковаму карыстальніку. На момант напісання артыкула антывірусныя рашэнні, прадстаўленыя на платформе «VirusTotal», не вызначаюць яго як шкоднасны.

Усё новае — гэта добра забытае старое
Малюнак 1. Вынік аналізу з дапамогай антывірусных рашэнняў.


Пры адкрыцці файла ў ізаляваным асяроддзі адбываліся звароты да нестандартнага рэсурсу: https[:]//processmanagerpro[.]net?transparencia/homeothermic.

У даследаваным файле знойдзена радок, па якім адбываўся зварот:

Усё новае — гэта добра забытае старое
Малюнак 2. Шкоднасны рэсурс у дампе файла.

Спецыялістамі CERT.BY было праведзена дэталёвае вывучэнне файла і выяўлены механізм злоўжывання функцыянальнасцю Word з мэтай атрымання першаснага доступу.

Даследаванне праводзілася на падставе афіцыйнай дакументацыі, прадстаўленай кампаніяй Microsoft у апошняй версіі праграмы:

https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/ 53989ce4-7b05-4f8d-829b-d08d6148375b – формат CFB;

https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-doc/ ccd7b486-7881-484c-a137-51170af7cc22 – формат DOC.

Не будзем выкарыстоўваць метады здабывання асноўных патокаў дадзеных з CFB-файлаў, а перайдзем да аналізу патоку дадзеных дакумента ў фармаце «doc», а менавіта:

«WordDocument» утрымлівае асноўныя загалоўкі файла ў фармаце «doc» і самі дадзеныя;

«xTable» утрымлівае службовыя дадзеныя файла ў фармаце «doc».

Шкоднасны рэсурс быў знойдзены ў патоку «1Table» у службовых дадзеных файла, што звузіла кола пошуку патэнцыйных тэхнік эксплуатацыі.

Правёўшы парсінг унутраных структур файла ў фармаце «doc», а менавіта
FibRgFcLcb97, што адпавядае фармат у «doc 97–2003», была знойдзена структура SttbfAssoc, якая адпавядае патрэбным зрухам.

Усё новае — гэта добра забытае старое
Малюнак 3. Парсінг унутраных структур файла.


Структура «SttbfAssoc» адказвае за асацыяцыі файла згодна з афіцыйнай дакументацыяй, і яе памер не павінен быць роўны 0. Структура «SttbfAssoc» уключае 18 спецыяльных радкоў, кожны з якіх мае сваё прызначэнне (глядзі афіцыйную дакументацыю). У даследаваным файле прысутнічае радок з індэксам 0x1, што адпавядае шаблону дакумента.

Усё новае — гэта добра забытае старое
Малюнак 4. Прызначэнне радкоў структуры «SttbfAssoc».

Такім чынам, была атрымана інфармацыя аб падыходзе, які выкарыстоўваецца кібергрупай, а таксама аб праблемах пры эксплуатацыі сучасных сродкаў абароны.

У выніку названая кібергрупа выкарыстоўвае як магчымасць сітуацыю, калі вытворца падтрымлівае працу са «старымі» фарматамі даных, а ахоўныя механізмы гэта не ўлічваюць або не падтрымліваюць, што прыводзіць да праблем забеспячэння кібербяспекі з дапамогай стандартных сродкаў распіяраных вытворцаў.

Дадзенае пытанне разглядалася ў публічнай прасторы ў 2023 годзе, аднак рашэнне не было прапанавана і не інтэгравана:

IOCs:

md5

006d454ab563ed82f7c5b9c7ce441316

1a761f40cd19ebded77173a8bd959869

sha1

b2f1467838de604023ec9e332a81dfad07658d68

5b7a92c00ba086b9fbdb9f454eb6aad0ebee83e9

sha256

1256f4faad88f8ce27922e8f1236fffb65a47c2873d8fdab4c486c83fbb852a1

6a13803593d72150319b91aafb5e47f0f87e447793e548b31add00d6db96e48a

ssdeep

192:M6ESgUNq5hDQkRKX2VZlyGgEP327AmE/RkwynyrSH9lLZaAHi6/6rrILd/Kf3HO6:5EmlKZYiP328RkRyWzgiSUR/8d3iTkj

192:IpEvFlPCul/VPlLq1IelLZaAQ6/6rrILd/Kf3HO8tfYb8i08pi5h:EA9CuNVPoGiSUR/8df3i0A

net

processmanagerpro[.]net

У гэтым кантэксце спецыялістамі CERT.BY быў распрацаваны скрыпт для выяўлення шаблонаў у састарэлых фарматах дакументаў з выкарыстаннем бібліятэкі «olefile».

Ніжэй прадстаўлены зыходны код інструмента:

import olefile
import sys,struct

if __name__ == '__main__':  
    try:
        ole = olefile.OleFileIO(sys.argv[1])
        wordstream=bytearray(ole.openstream('WordDocument').read())
    except Exception as e:
        print('Warning! Can\'t get WordDocument stream, for file "{0}", reason {1}'.format(sys.argv[1],str(e)))
        exit(0)
    #https://msopenspecs.microsoft.com/files/MS-DOC/%5bMS-DOC%5d.pdf FIB info
    if len(wordstream) <= (32+2+28+2+88+2): #base_size + csw_size + csw*2 + cslw_size + cslw*4 + cbRgFcLcb_size
        print("Warning! Not correct size of 'WordDocument' stream")
        exit(0)
    
    #Check table name
    tablestream="0Table"
    flag=struct.unpack("<H",wordstream[10:12])[0]
    if flag &0x200:
        tablestream="1Table"
    try:
        tablestream=bytearray(ole.openstream(tablestream).read())
    except Exception as e:
        print("Warning! Can't get Table stream, reason {}".format(str(e)))
        exit(0)

    if len(tablestream)==0:
        print("Warning! Not correct size of Table Steam stream")
        exit(0)
    ole.close()
    # next version of FibRgFcLcb contains last, we need fcSttbfAssoc 0x100 lcbSttbfAssoc 0x104,
    # 0x9a offset to FibRgFcLcb
    fcSttbfAssoc=struct.unpack("<I",wordstream[0x9a+0x100:0x9a+0x100+0x4])[0]
    lcbSttbfAssoc=struct.unpack("<I",wordstream[0x9a+0x104:0x9a+0x104+0x4])[0]
    if (fcSttbfAssoc <=0 or fcSttbfAssoc>=len(tablestream)) or lcbSttbfAssoc <=0:
        print("Warning! Not valide fcSttbfAssoc")
        exit(0)
    
    if fcSttbfAssoc+lcbSttbfAssoc>len(tablestream):
        print("Warning! Not valide fcSttbfAssoc")
        exit(0)
    
    # https://msopenspecs.microsoft.com/files/MS-DOC/%5bMS-DOC%5d.pdf#%5B%7B%22num%22%3A905%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C69%2C329%2C0%5D
    # skip fExtend, cData, cbExtra, first item, and check size of template path
    cchData=struct.unpack("<H",tablestream[fcSttbfAssoc+0x8:fcSttbfAssoc+0x8+0x2])[0]
    if cchData!=0 and (cchData+fcSttbfAssoc+0x8) < len(tablestream): # it is unicode string, need to multiple size
        Data=tablestream[fcSttbfAssoc+0x8+0x2:fcSttbfAssoc+0x8+0x2+(cchData*2)]
        try:
            print(Data)
            Data=Data.decode('utf-16-le')         
        except:
            pass
        print('Template in file "{0}" found! location "{1}"'.format(sys.argv[1],Data))
    else:
        print('File "{0}" chechked, template not found'.format(sys.argv[1]))

Калі вы знойдзеце пагрозу, калі ласка, паведаміце нам паводле e -mail CERT.BY: support@cert.by.

Для зручнасці і своечасовага апавяшчэння аб навінах падпісвайцеся на нас у сацыяльных сетках: