Ha csütörtökön befut a riasztás egy kritikus, távoli kódfuttatást (RCE) lehetővé tevő PHP-sebezhetőségről – legyen szó akár a „PHP2Shell” néven futó támadási láncról –, nincs idő várakozni. A hír levélben, Slacken vagy riasztásban érkezik, a támadók pedig már pásztázzák a nyilvános IP-tartományokat. Ilyenkor a legfontosabb, hogy perceken belül legyen egy végrehajtható elhárítási tervünk, ne pedig órákig kutakodjunk, hogy melyik szerveren is fut Apache és melyiken nginx.
Ebben a cikkben végigmegyünk a teljes folyamaton – az azonnali izolációtól a csomagfrissítésen át a PHP keményítéséig –, és adunk egy egyszerű, hibamentesen futtatható bash scriptet, amely az egész procedúrát automatizálja. A cél: egyetlen paranccsal eljussunk az „uh-oh” állapotból a „megvagyunk” állapotba.
1. Azonnali izoláció és kármentesítés
Ha felmerül a fertőzés gyanúja – gyanús folyamat, ismeretlen fájl a webrootban, furcsa kimenő forgalom –, első lépés a webszerver leállítása. Ez nem esztétikai kérdés: amíg a szolgáltatás fut, a támadó akár percenként újra tudja használni a sebezhetőséget.
Debian/Ubuntu alatt:
bash
sudo systemctl stop apache2
RHEL/AlmaLinux/Rocky Linux alatt:
bash
sudo systemctl stop httpd
Ezután nézzük meg, mi történt az elmúlt 48 órában. A leggyakoribb nyomok: frissen módosult PHP fájlok, eval(), base64_decode(), system() vagy shell_exec() hívások a webrootban.
bash
# Elmúlt 48 órában módosult PHP fájlok
find /var/www/html -type f -name "*.php" -mmin -2880
# Veszélyes minták keresése
grep -rnwi "eval(" /var/www/html/
grep -rnwi "base64_decode" /var/www/html/
grep -rnwi "shell_exec" /var/www/html/Tipp: a -mmin -2880 a 48 órán belül módosult fájlokat jelenti (2880 perc = 48 óra). Ha a támadás régebbi, növeld az értéket, vagy használj -mtime -7-et.
2. Frissítés – lehetőleg központilag
A sebezhetőség lényege, hogy a hibás PHP-verzió távoli kódfuttatást tesz lehetővé. A javítás szinte minden esetben a csomag frissítése. Egy szerveren ez néhány perc; száz szerveren viszont rémálom, ha kézzel csináljuk.
Itt jön képbe a Hermes Agent – vagy bármilyen konfigurációmenedzsment eszköz (Ansible, Puppet, Salt) –, amellyel a frissítés központilag, szinkronban futtatható a teljes flottán. A lényeg: ne egyesével SSH-zzunk, hanem adjunk ki egy parancsot, és nézzük, ahogy a flotta frissül.
Debian/Ubuntu alatt:
bash
sudo apt update && sudo apt install --only-upgrade php* -y sudo systemctl restart apache2
RHEL/AlmaLinux/Rocky Linux alatt:
bash
sudo dnf upgrade --refresh -y && sudo dnf upgrade php* -y sudo systemctl restart httpd
Ha a hivatalos OS-tárolók még nem frissültek (ez a kritikus napokban gyakori), az Agent segítségével vedd fel a dedikált tárolókat:
-
Debian/Ubuntu: Sury PPA – frissebb PHP verziók
-
RHEL/AlmaLinux/Rocky: Remi repository – friss PHP build-ek
Figyelem: a tárolók hozzáadása disztribúció- és verziófüggő. Automatizálni csak akkor érdemes, ha a flotta homogén – heterogén környezetben ez könnyen eltörheti a rendszert. Éles rollout előtt tesztelj egy canary gépen.
3. PHP keményítés (Hardening)
A frissítés megszünteti a sebezhetőséget, de a mélységi védelem jegyében érdemes korlátozni a veszélyes függvényeket is. A php.ini fájlban a disable_functions sornál tiltsd le a parancsvégrehajtó és hálózati függvényeket:
ini
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec
Emellett a webszerver konfigurációjában tiltsd le a PHP scriptek futtatását az uploads és egyéb írható mappákban. Apache esetén például:
apache
<Directory /var/www/html/uploads>
php_admin_flag engine off
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
</Directory>Nginx esetén a location blokkban érdemes internal-ra állítani a PHP-t, vagy egyáltalán nem továbbítani a PHP kéréseket az adott könyvtárból.
Figyelem: a curl_exec letiltása sok legitim alkalmazást (pl. WordPress pluginok, API-kliensek) eltörhet. Éles környezetben először tesztkörnyezetben próbáld ki, és nézd meg, mit panaszkodik az alkalmazás.
4. Ellenőrzés
A frissítés és hardening után ellenőrizzük, hogy minden rendben van-e:
bash
# PHP verzió php -v # Webszerver hibanapló (Debian/Ubuntu) tail -n 50 /var/log/apache2/error.log # Webszerver hibanapló (RHEL/AlmaLinux/Rocky) tail -n 50 /var/log/httpd/error_log
Ha a webszervert leállítottuk, most indítsuk újra:
bash
sudo systemctl start apache2 # vagy httpd
5. A bash script – egy parancs, végponttól végpontig
A fenti lépéseket összefogja az alábbi script. Több disztribúciót kezel (Debian/Ubuntu és RHEL/AlmaLinux/Rocky), biztonsági mentést készít a php.ini-ről, és hibatűrően fut: egy-egy nem kritikus lépés hibája nem állítja le a teljes folyamatot.
bash
#!/usr/bin/env bash
#
# php2shell-response.sh
# PHP2Shell / kritikus PHP RCE sebezhetőség – gyors elhárító script
#
# Használat:
# sudo ./php2shell-response.sh [--stop-web] [--no-upgrade] [--hardening-only]
#
# Opciók:
# --stop-web Leállítja a webszervert az izolációhoz (fertőzés gyanúja esetén)
# --no-upgrade Kihagyja a csomagfrissítést (csak vizsgálat + hardening)
# --hardening-only Csak a php.ini hardening + ellenőrzés fut
#
set -euo pipefail
# ---------- Színek / logolás ----------
RED='\033[0;31m'; GRN='\033[0;32m'; YEL='\033[1;33m'; NC='\033[0m'
log() { echo -e "${GRN}[+]${NC} $*"; }
warn() { echo -e "${YEL}[!]${NC} $*"; }
err() { echo -e "${RED}[x]${NC} $*" >&2; }
die() { err "$*"; exit 1; }
# ---------- Root ellenőrzés ----------
[[ $EUID -eq 0 ]] || die "Root jogosultság szükséges. Futtasd: sudo $0"
# ---------- Argumentumok ----------
STOP_WEB=0
DO_UPGRADE=1
HARDENING_ONLY=0
for arg in "$@"; do
case "$arg" in
--stop-web) STOP_WEB=1 ;;
--no-upgrade) DO_UPGRADE=0 ;;
--hardening-only) HARDENING_ONLY=1; DO_UPGRADE=0 ;;
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
*) die "Ismeretlen opció: $arg" ;;
esac
done
# ---------- Disztribúció felismerése ----------
if [[ -f /etc/os-release ]]; then
. /etc/os-release
OS_ID="${ID:-unknown}"
OS_LIKE="${ID_LIKE:-}"
else
die "Nem található /etc/os-release"
fi
is_debian() { [[ "$OS_ID" =~ (debian|ubuntu) || "$OS_LIKE" =~ debian ]]; }
is_rhel() { [[ "$OS_ID" =~ (rhel|centos|almalinux|rocky|fedora) || "$OS_LIKE" =~ (rhel|fedora) ]]; }
if is_debian; then
PKG_MGR="apt"; WEB_SVC="apache2"; WEB_LOG="/var/log/apache2/error.log"
elif is_rhel; then
PKG_MGR="dnf"; WEB_SVC="httpd"; WEB_LOG="/var/log/httpd/error_log"
else
die "Nem támogatott disztribúció: $OS_ID"
fi
log "Disztribúció: $OS_ID | Csomagkezelő: $PKG_MGR | Webszerver: $WEB_SVC"
# ---------- Webszerver szolgáltatás nevének ellenőrzése ----------
if ! systemctl list-unit-files | grep -q "^${WEB_SVC}\.service"; then
if systemctl list-unit-files | grep -q '^nginx\.service'; then
warn "Apache nem található, de nginx igen. A script Apache-ra készült – ellenőrizd kézzel."
else
warn "A(z) $WEB_SVC szolgáltatás nem található."
fi
fi
# ---------- 1) Izoláció ----------
if [[ $HARDENING_ONLY -eq 0 && $STOP_WEB -eq 1 ]]; then
log "Webszerver leállítása (izoláció)..."
systemctl stop "$WEB_SVC" || warn "Nem sikerült leállítani: $WEB_SVC"
fi
# ---------- 2) Gyanús fájlok keresése ----------
if [[ $HARDENING_ONLY -eq 0 ]]; then
log "Elmúlt 48 órában módosult PHP fájlok keresése..."
if [[ -d /var/www/html ]]; then
find /var/www/html -type f -name "*.php" -mmin -2880 -print 2>/dev/null || true
else
warn "/var/www/html nem létezik – kihagyva."
fi
log "Veszélyes minták keresése..."
for pattern in 'eval(' 'base64_decode' 'shell_exec' 'system(' 'passthru' 'assert('; do
echo "--- minta: $pattern ---"
grep -rnwi --include='*.php' -- "$pattern" /var/www/html 2>/dev/null | head -n 50 || true
done
fi
# ---------- 3) Csomagfrissítés ----------
if [[ $DO_UPGRADE -eq 1 ]]; then
log "PHP csomagok frissítése..."
if [[ "$PKG_MGR" == "apt" ]]; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install --only-upgrade -y 'php*' || warn "apt upgrade részben sikertelen – ellenőrizd kézzel."
else
dnf upgrade --refresh -y || warn "dnf upgrade sikertelen – ellenőrizd kézzel."
dnf upgrade -y 'php*' || warn "dnf php upgrade sikertelen – ellenőrizd kézzel."
fi
log "Webszerver újraindítása..."
systemctl restart "$WEB_SVC" || warn "Nem sikerült újraindítani: $WEB_SVC"
fi
# ---------- 4) PHP hardening ----------
log "PHP hardening (disable_functions)..."
PHP_INI=$(php --ini 2>/dev/null | awk -F': ' '/Loaded Configuration File/ {print $2}')
if [[ -z "${PHP_INI:-}" || "$PHP_INI" == "(none)" ]]; then
warn "Nem található betöltött php.ini – hardening kihagyva."
else
BACKUP="${PHP_INI}.bak.$(date +%Y%m%d%H%M%S)"
cp -a "$PHP_INI" "$BACKUP"
log "Biztonsági mentés: $BACKUP"
DANGEROUS="exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec"
if grep -qE '^\s*disable_functions\s*=' "$PHP_INI"; then
sed -i -E "s|^\s*disable_functions\s*=.*|disable_functions = ${DANGEROUS}|" "$PHP_INI"
log "Meglévő disable_functions sor frissítve."
else
printf '\ndisable_functions = %s\n' "$DANGEROUS" >> "$PHP_INI"
log "disable_functions hozzáadva a php.ini-hez."
fi
fi
# ---------- 5) Ellenőrzés ----------
log "PHP verzió ellenőrzése..."
php -v 2>/dev/null | head -n 1 || warn "php parancs nem elérhető."
if [[ -f "$WEB_LOG" ]]; then
log "Webszerver hibanapló utolsó 10 sora ($WEB_LOG):"
tail -n 10 "$WEB_LOG" || true
else
warn "Hibanapló nem található: $WEB_LOG"
fi
log "Kész. Ha a webszervert leállítottad, indítsd újra kézzel: systemctl start $WEB_SVC"Használat
bash
chmod +x php2shell-response.sh # Teljes elhárítás (izoláció + vizsgálat + frissítés + hardening) sudo ./php2shell-response.sh --stop-web # Csak vizsgálat + frissítés (webszerver futva marad) sudo ./php2shell-response.sh # Csak hardening + ellenőrzés sudo ./php2shell-response.sh --hardening-only # Súgó ./php2shell-response.sh --help
Miért biztonságos?
-
Idempotens: többször futtatható, a disable_functions sort frissíti, nem duplikálja.
-
Biztonsági mentés: minden php.ini módosítás előtt .bak.<timestamp> mentés készül.
-
Hibatűrő: set -euo pipefail a kritikus hibáknál megállít, de a nem kritikus lépéseknél || warn van, így egy-egy hiba nem borítja fel a folyamatot.
-
--stop-web nélkül a webszerver futva marad – éles környezetben először ezt futtasd, csak fertőzés gyanúja esetén állítsd le.
-
Sury PPA / Remi repo hozzáadását szándékosan nem automatizáltam – ez disztribúció- és verziófüggő, könnyen eltörheti a rendszert. Ha kell, futtasd kézzel a cikk szerint.
Egy kritikus PHP-sebezhetőség nem attól veszélyes, hogy létezik, hanem attól, hogy mennyi idő alatt reagálunk rá. A fenti folyamat – izoláció → vizsgálat → frissítés → hardening → ellenőrzés – percek alatt végigvihető, ha van egy kész scriptünk, és ha a flotta frissítését központilag tudjuk vezérelni.
A script nem csodaszer: a grep találatokat mindig nézd át kézzel, a hardening élesítése előtt tesztelj, és a tárolók hozzáadását csak homogén környezetben automatizáld. De arra tökéletes, hogy a „csütörtöki meglepetés” ne húzza el napokra a rendszergazda délutánját – hanem legyen meg a válasz már az első órában.
Jó vadászatot – és jó csütörtököt!

Hozzászólások
Szerintem nem kell már a Sury
Beküldte kami911 -
Értékelés:
Szerintem nem kell már a Sury PPA, mert: