Skip to content
ZONATA.ID ZONATA.ID ZONATA.ID

Satu Klik Lebih Pintar

ZONATA.ID ZONATA.ID ZONATA.ID

Satu Klik Lebih Pintar

  • Home
  • About
  • Privacy Policy
  • Home
  • About
  • Privacy Policy
Close

Search

  • https://www.facebook.com/
  • https://twitter.com/
  • https://t.me/
  • https://www.instagram.com/
  • https://youtube.com/
ZONATA.ID ZONATA.ID ZONATA.ID

Satu Klik Lebih Pintar

ZONATA.ID ZONATA.ID ZONATA.ID

Satu Klik Lebih Pintar

  • Home
  • About
  • Privacy Policy
  • Home
  • About
  • Privacy Policy
Close

Search

  • https://www.facebook.com/
  • https://twitter.com/
  • https://t.me/
  • https://www.instagram.com/
  • https://youtube.com/
Home/Security/Hardening Tomcat / Remediate Tomcat
Security

Hardening Tomcat / Remediate Tomcat

By Administrator
November 8, 2026 9 Min Read
0

Linux · Apache Tomcat · Security Engineering · 2026

Hardening Tomcat bukan soal mengganti satu-dua parameter lalu menyebut server aman. Yang saya cari justru konfigurasi yang bisa dipertanggungjawabkan: tahu baseline-nya, paham alasan tiap perubahan, punya bukti pengujian, dan tetap bisa rollback kalau ada yang tidak sesuai.

Catatan ruang lingkup. Artikel ini ditujukan untuk Apache Tomcat 9.x di Linux dengan systemd, baik menggunakan reverse proxy maupun koneksi langsung yang dikendalikan firewall. Identitas server, domain, alamat jaringan, nama aplikasi, dan detail integrasi sengaja tidak disertakan. Contoh path /opt/tomcat, service tomcat, dan port 8080 adalah placeholder.
Daftar isi

  1. Apa yang di-hardening
  2. Topologi dan trust boundary
  3. Flow remediasi
  4. 1. Audit baseline
  5. 2. Konfigurasi XML
  6. 3. Skrip dry-run/remediasi
  7. 4. OS dan systemd
  8. 5. Validasi dan rollback
  9. Catatan risiko
  10. Referensi

Checklist: yang diperiksa, yang diubah, dan alasannya

Sebelum menulis skrip, saya pisahkan dulu exposure, runtime configuration, access control, dan operasional. Kalau semuanya langsung ditembak sekaligus, saat ada error kita susah menentukan perubahan mana yang menyebabkannya.

Area Target Pendekatan Catatan
Versi & CVE Rilis 9.0.x yang sudah mendapat perbaikan terbaru Bandingkan advisory resmi dan uji upgrade Configuration hardening tidak menggantikan security update
Service account Non-root, hak tulis minimum Dedicated user dan file permission Direktori webapps/config jangan writable oleh runtime bila tidak diperlukan
Network connector Port dan interface minimum Batasi bind, firewall, reverse proxy Jangan bind ke loopback jika LB berada di host lain
Shutdown port Nonaktif bila mekanisme stop mendukung Server port="-1" Uji systemd terlebih dahulu
Deployment Tidak menerima deploy liar autoDeploy=false, deployXML=false Validasi deployment pipeline; jangan asal ubah deployOnStartup
Banner/error Informasi internal minim Connector server header dan ErrorReportValve Bukan pengganti patching, WAF atau auth
Request parsing Header ilegal ditolak rejectIllegalHeader=true Sudah default pada versi modern; tetap audit
Cookie & session HttpOnly, Secure/SameSite bila sesuai context.xml dan pengujian browser Secure/SameSite perlu evaluasi HTTPS offload/SSO
Log & monitoring Audit trail tersedia tanpa rahasia AccessLogValve, journal, retensi Jangan log token, password atau cookie autentikasi
TLS / mTLS Protokol, trust CA dan client auth sesuai model Evaluasi connector/proxy dan sertifikat Opsional; clientAuth tidak boleh diwajibkan tanpa kebutuhan

Topologi referensi dan batas kepercayaan

Contoh ini memakai reverse proxy sebagai pintu masuk. Tomcat tidak otomatis menjadi aman karena berada di belakang proxy: trafik dari proxy ke aplikasi tetap perlu ACL, dan header X-Forwarded-* tidak boleh dipercaya dari klien sembarangan.

ClientHTTPS 443Edge / WAFTLS terminationTomcat 9Dedicated userBackendRestricted ACLLog / MonitoringJournal, access log, alertContoh arsitektur, bukan jaringan aktual
North–SouthInternet ke edge melalui HTTPS. Tambahkan rate limiting, access policy dan pemantauan.
East–WestEdge ke Tomcat dan Tomcat ke backend hanya pada port yang diperlukan.
Kalau tanpa reverse proxy, apa yang berubah?

Tomcat dapat melayani TLS sendiri menggunakan SSLHostConfig, tetapi hardening TLS, sertifikat, timeout, pembatasan akses dan observabilitas harus ditangani pada connector Tomcat. Jangan menggunakan contoh connector HTTP loopback untuk menggantikan konfigurasi HTTPS yang sedang berjalan.

Flowchart perubahan yang saya pakai

Urutannya penting. Perubahan yang kelihatannya kecil tetap harus lewat review diff dan pengujian fungsional. Flow berikut menghindari pola “edit XML, restart, lalu berharap”.

InventarisAudit baselineBackup & planDry-run / diffReview & stagingTes lulus?Apply & restartPost-checkRollback jika gagalYaTidakGagal

1. Ambil baseline sebelum menyentuh konfigurasi

Audit versi, socket, user service, dan XML

Skrip ini read-only. Hasilnya dipakai sebagai catatan kondisi awal sekaligus bahan change record. Jalankan di host yang memang Anda kelola; output versi, user dan listener bukan untuk diumbar ke publik.

tomcat-audit.shBASH
#!/usr/bin/env bash
# tomcat-audit.sh - read-only baseline collection
set -Eeuo pipefail
BASE="${CATALINA_BASE:-/opt/tomcat}"
CONF="$BASE/conf"
SERVICE="${TOMCAT_SERVICE:-tomcat}"

printf '== Environment ==\n'
id; java -version 2>&1 | head -n 3
printf '\n== Tomcat binary ==\n'
if [[ -x "$BASE/bin/version.sh" ]]; then
  "$BASE/bin/version.sh" 2>&1 | head -n 14
fi
printf '\n== Listener ==\n'
ss -lntp || true
printf '\n== systemd ==\n'
systemctl show "$SERVICE" -p User -p Group -p ExecStart -p FragmentPath 2>/dev/null || true
printf '\n== Config file access ==\n'
for f in "$CONF/server.xml" "$CONF/context.xml" "$CONF/web.xml"; do
  [[ -f "$f" ]] && stat -c '%A %U:%G %n' "$f"
done
printf '\n== Configuration markers ==\n'
python3 - "$CONF/server.xml" <<'PY_AUDIT'
import sys, xml.etree.ElementTree as ET
try:
    root=ET.parse(sys.argv[1]).getroot()
    print('shutdown port:', root.get('port'))
    for node in root.iter('Connector'):
        print('connector:', {k: node.get(k) for k in
              ('port','protocol','SSLEnabled','server','connectionTimeout')})
    for node in root.iter('Host'):
        print('host:', {k: node.get(k) for k in
              ('name','autoDeploy','deployXML','deployOnStartup')})
except (OSError, ET.ParseError) as exc:
    sys.exit(f'Could not read XML: {exc}')
PY_AUDIT
printf '\nAudit complete; no changes made.\n'
Menjalankan auditBASH
chmod +x tomcat-audit.sh
CATALINA_BASE=/opt/tomcat TOMCAT_SERVICE=tomcat ./tomcat-audit.sh | tee audit-local.txt
# Simpan audit-local.txt hanya di repositori/penyimpanan internal yang aman.
Hal yang wajib direview dari hasil audit
  • JDK dan Tomcat benar-benar versi yang didukung; ada patch security tertunda atau tidak.
  • Port yang listening sesuai desain, termasuk AJP, JMX, debug dan shutdown.
  • User service bukan root dan tidak punya write access berlebihan ke konfigurasi.
  • Deployment otomatis, Manager, host-manager, examples, dan docs memang diperlukan atau tidak.
  • Log tidak mengandung access token, session ID, kredensial, atau detail internal berlebihan.

2. Memahami perubahan di server.xml dan context.xml

Di bawah ini contoh struktur XML, bukan file server.xml lengkap. Jangan replace file asli: listener, TLS, keystore, realm, connector dan virtual host yang ada dapat hilang. Pada lingkungan reverse proxy lokal, connector dapat di-bind ke 127.0.0.1; untuk proxy di mesin lain gunakan IP antarmuka internal yang sesuai.

server.xml — potongan konseptualXML
<!-- Illustrative excerpt; merge into existing server.xml, never replace whole file. -->
<Server port="-1">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               address="127.0.0.1"
               connectionTimeout="20000"
               server="WebServer"
               rejectIllegalHeader="true" />
    <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost" appBase="webapps"
            autoDeploy="false" deployXML="false">
        <Valve className="org.apache.catalina.valves.ErrorReportValve"
               showReport="false" showServerInfo="false" />
        <Valve className="org.apache.catalina.valves.AccessLogValve"
               directory="logs" prefix="access_log" suffix=".txt"
               pattern="%a %t &quot;%r&quot; %s %b %D" />
      </Host>
    </Engine>
  </Service>
</Server>

Menonaktifkan shutdown port berguna jika proses dihentikan oleh service manager yang benar. Namun, bila unit systemd masih mengandalkan shutdown.sh untuk stop, perubahan ini bisa membuat penghentian layanan tidak berjalan sesuai harapan. Parameter itu tidak dimasukkan dalam skrip otomatis di bawah.

context.xml — pengaturan awalXML
<!-- conf/context.xml: only after reviewing all applications -->
<Context useHttpOnly="true" crossContext="false" privileged="false">
  <!-- Set sessionCookiePath, SameSite, or secure flag only after testing
       HTTPS offload, authentication and browser behavior. -->
</Context>
Kenapa tidak mengunci semua cookie dan header secara otomatis?

Aplikasi dengan autentikasi lintas domain, SSO, WebSocket, redirect HTTPS, atau reverse proxy punya karakteristik berbeda. HttpOnly biasanya layak, sedangkan Secure dan SameSite harus divalidasi pada alur login dan cross-site request. Header HSTS dan CSP paling mudah dikelola di edge, tetapi butuh keputusan scope dan pengecualian yang jelas.

3. Remediasi berbasis Python: tampilkan diff, baru apply

Ini bagian yang paling berguna saat menangani banyak instance dengan pola konfigurasi serupa. Skrip sengaja dibatasi: memilih satu port connector, memperbarui banner/error valve, dan menonaktifkan hot deployment pada host. Konfigurasi TLS, backend, aplikasi, JMX, AJP, dan shutdown port tidak disentuh. Tidak ada auto-restart.

Prasyarat: Python 3 + lxml. Uji dahulu di staging. Backup dibuat otomatis sebelum perubahan permanen, dan mode standar hanya mencetak unified diff. Jika ada beberapa Connector memakai nomor port sama atau XML tidak valid, skrip berhenti.
tomcat-remediate.pyPYTHON
#!/usr/bin/env python3
"""Minimal, conservative server.xml remediator. Dry-run by default.
Requires Python 3 and lxml (python3 -m pip install lxml).
Use only on a maintenance/test copy before production.
"""
import argparse
import difflib
import os
from pathlib import Path
import shutil
import sys
from datetime import datetime, timezone
from lxml import etree

parser = argparse.ArgumentParser()
parser.add_argument('--base', default='/opt/tomcat')
parser.add_argument('--port', required=True, help='Existing Connector port to target')
parser.add_argument('--header', default='WebServer')
parser.add_argument('--apply', action='store_true', help='Write changes; default is preview')
a = parser.parse_args()
file = Path(a.base) / 'conf' / 'server.xml'
if not file.is_file():
    sys.exit(f'File not found: {file}')
original = file.read_bytes()
xml_parser = etree.XMLParser(resolve_entities=False, no_network=True,
                             remove_blank_text=False, strip_cdata=False)
root = etree.fromstring(original, parser=xml_parser)
if root.tag != 'Server':
    sys.exit('Expected Server root element')
connectors = [c for c in root.iter('Connector') if c.get('port') == a.port]
if len(connectors) != 1:
    sys.exit(f'Expected exactly one Connector port={a.port}, got {len(connectors)}')
conn = connectors[0]
# Apply ONLY explicitly reviewed low-risk settings to the chosen connector.
conn.set('server', a.header)
conn.set('serverRemoveAppProvidedValues', 'true')
conn.set('rejectIllegalHeader', 'true')
conn.set('connectionTimeout', '20000')
# Do not touch TLS, HTTP/2, AJP, proxy settings, apps, or shutdown port.
for host in root.iter('Host'):
    host.set('deployXML', 'false')
    host.set('autoDeploy', 'false')
    # Avoid forcibly changing deployOnStartup: may prevent existing app startup.
    valves = [v for v in host.findall('Valve')
              if v.get('className') == 'org.apache.catalina.valves.ErrorReportValve']
    if len(valves) > 1:
        sys.exit('Multiple ErrorReportValve entries: review manually')
    valve = valves[0] if valves else etree.SubElement(host, 'Valve')
    valve.set('className', 'org.apache.catalina.valves.ErrorReportValve')
    valve.set('showServerInfo', 'false')
    valve.set('showReport', 'false')
new = etree.tostring(root, encoding='UTF-8', xml_declaration=True)
old_text = original.decode('utf-8').splitlines(keepends=True)
new_text = new.decode('utf-8').splitlines(keepends=True)
print(''.join(difflib.unified_diff(old_text, new_text,
                                  fromfile='server.xml.before',
                                  tofile='server.xml.after')), end='')
if not a.apply:
    print('\nDRY-RUN: nothing written. Inspect diff; then rerun with --apply.')
    sys.exit(0)
backup = file.with_name('server.xml.bak.' +
                        datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ'))
shutil.copy2(file, backup)
os.chmod(backup, 0o600)
tmp = file.with_name('.server.xml.hardening.tmp')
try:
    with tmp.open('xb') as out:
        out.write(new)
        out.flush()
        os.fsync(out.fileno())
    shutil.copymode(file, tmp)
    shutil.chown(tmp, user=file.stat().st_uid, group=file.stat().st_gid)
    os.replace(tmp, file)
except Exception:
    tmp.unlink(missing_ok=True)
    raise
print(f'APPLIED. Backup: {backup}')
print('NEXT: validate with catalina.sh configtest; restart only in change window.')
Eksekusi amanBASH
# Dependency di virtualenv/admin workstation; contoh saja
python3 -m venv /tmp/tomcat-xml-venv
/tmp/tomcat-xml-venv/bin/pip install lxml
# Preview: tanpa perubahan pada server.xml
sudo /tmp/tomcat-xml-venv/bin/python tomcat-remediate.py \
  --base /opt/tomcat --port 8080
# Setelah review diff, backup eksternal dan persetujuan change:
sudo /tmp/tomcat-xml-venv/bin/python tomcat-remediate.py \
  --base /opt/tomcat --port 8080 --apply
# Jalankan configtest sebelum restart layanan
sudo /opt/tomcat/bin/catalina.sh configtest
Apa saja yang sengaja tidak diotomatisasi?

Rotasi dan masking log, security header, pembatasan request body, konfigurasi mTLS, enable/disable HTTP/2, penghapusan webapps, firewall, dan perubahan permission massal. Semuanya perlu audit dependensi serta validasi bisnis. Pemilihan parameter seperti maxParameterCount atau maxHttpHeaderSize sebaiknya mengikuti profil request aplikasi, bukan angka acak yang diambil dari internet.

4. Hardening host dan isolasi layanan dengan systemd

Lapisan OS sering lebih menentukan daripada menyamarkan header. Service account khusus, folder konfigurasi non-writable, limit akses outbound, dan unit sandbox memberi pengurangan risiko yang nyata. Contoh berikut template, bukan perintah untuk langsung diterapkan.

tomcat.service.d/hardening.confINI
# /etc/systemd/system/tomcat.service.d/hardening.conf
# Example only: adjust writable paths & service name to your package/layout.
[Service]
User=tomcat
Group=tomcat
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/tomcat/logs /opt/tomcat/temp /opt/tomcat/work
# Do not blindly enable DynamicUser, MemoryDenyWriteExecute or
# SystemCallFilter: Java/native libraries may require extra permissions.
Validasi systemdBASH
sudo systemd-analyze security tomcat.service
sudo systemctl cat tomcat.service
# Jika sudah menyesuaikan dan menyimpan drop-in:
sudo systemctl daemon-reload
sudo systemctl restart tomcat
sudo journalctl -u tomcat -n 120 --no-pager

Dengan ProtectSystem=strict, folder di luar ReadWritePaths menjadi tidak bisa ditulis oleh unit. Tambahkan path yang benar-benar dibutuhkan, bukan membuka seluruh /opt/tomcat. Beberapa paket atau framework juga membuat file dinamis di lokasi lain; ini alasan staging test harus mencakup startup, transaksi, unggahan dan cleanup.

5. Verifikasi, evidence, dan rollback

Hasil hardening yang bisa diterima bukan sekadar proses menunjukkan status active. Saya cek sintaks XML, port, response header, error page, log, endpoint fungsional, dan perilaku aplikasi setelah restart. Buat perbandingan sebelum/sesudah dan catat change ID pada evidence internal.

tomcat-verify.shBASH
#!/usr/bin/env bash
set -Eeuo pipefail
BASE="${CATALINA_BASE:-/opt/tomcat}"
SERVICE="${TOMCAT_SERVICE:-tomcat}"
TARGET="${TARGET_URL:-http://127.0.0.1:8080}"
"$BASE/bin/catalina.sh" configtest
systemctl is-active --quiet "$SERVICE" && echo 'Service active'
curl --silent --show-error --max-time 10 -D - -o /dev/null "$TARGET/" \
  | sed -n '1,18p'
curl --silent --show-error --max-time 10 -D - -o /dev/null \
  "$TARGET/this-page-should-not-exist-2026" | sed -n '1,18p'
echo 'Validate TLS with openssl s_client (if TLS terminates on Tomcat).'
echo 'Confirm expected endpoints, sessions, file upload, websocket, async flows.'
Technical checksConfigtest, port exposure, TLS handshake, HTTP status, header dan permission.
Functional checksLogin, session, redirect, upload, WebSocket/async bila digunakan, integrasi backend.

Rollback harus sudah siap sebelum change

Contoh pemulihan konfigurasiBASH
# Replace with the EXACT backup path printed by the remediator.
sudo systemctl stop tomcat
sudo cp -a /opt/tomcat/conf/server.xml.bak.YYYYMMDDTHHMMSSZ \
  /opt/tomcat/conf/server.xml
sudo /opt/tomcat/bin/catalina.sh configtest
sudo systemctl start tomcat
sudo systemctl status tomcat --no-pager
# Restore the previous systemd drop-in separately if one was changed.
Checklist untuk menyatakan perubahan selesai
  • Versi software dan advisory security diperiksa.
  • Backup file/VM dan prosedur restore diuji atau diverifikasi.
  • Diff direview dan disetujui.
  • Service startup, health check dan transaksi utama lulus.
  • Header, error page, connector, log dan permission dicek ulang.
  • Monitoring tidak menunjukkan lonjakan error/latency.
  • Rollback path dan change record terdokumentasi.

Catatan khusus: Security Manager, TLS, dan patch

Java Security Manager bukan switch yang sebaiknya diaktifkan asal

Java Security Manager historisnya menawarkan sandbox per permission melalui catalina.policy. Namun dependency lama, akses property, logging, classloader dan library native dapat terkena AccessControlException. Dukungan Java juga berubah menurut versi JDK. Untuk implementasi modern, utamakan runtime user non-root, least privilege, segmentasi jaringan, isolasi proses dan patching. Kalau lingkungan legacy masih memerlukannya, kerjakan sebagai proyek kompatibilitas terpisah dengan uji regresi menyeluruh.

TLS dan mutual TLS

Server certificate untuk serverAuth dan client certificate untuk clientAuth menjalankan peran berbeda. mTLS membutuhkan CA yang dipercaya, kebijakan validasi klien dan distribusi sertifikat yang rapi. Jika terminasi TLS ada di reverse proxy, validasi sertifikat klien dilakukan di sana; jika langsung di Tomcat, gunakan konfigurasi connector SSLHostConfig yang sesuai. Hindari meneruskan identitas sertifikat melalui header yang dapat dipalsukan.

Prioritaskan update keamanan

Ketika tulisan ini disusun (8 November 2026), advisory Tomcat 9 mencantumkan perbaikan pada 9.0.123, termasuk isu HTTP/2 dan autentikasi tertentu yang memengaruhi versi sebelumnya. Jangan mengandalkan tutorial ini sebagai bukti bahwa sebuah versi sudah bebas CVE: rujuk advisory terbaru sebelum maintenance.

Penutup. Saya lebih percaya hasil hardening yang punya tiga hal: konfigurasi bisa dijelaskan, perubahan dapat diuji, dan layanan bisa dikembalikan dengan cepat. Menyembunyikan versi itu boleh sebagai pelengkap, tetapi patch management, least privilege dan validasi fungsional tetap menjadi pekerjaan utamanya.

Referensi teknis

  • Apache Tomcat — Security Considerations
  • Apache Tomcat 9 — Security Advisories
  • Apache Tomcat — HTTP Connector
  • Apache Tomcat — Valve Configuration
  • Apache Tomcat — Security Manager (legacy)

Artikel teknis, bukan baseline universal. Sesuaikan dengan platform, versi JDK, SLA, arsitektur dan kebijakan change management masing-masing. Contoh menggunakan data sintetis.

/* Copy button stays scoped to this article; no third-party JavaScript dependency. */
(function(){
var root=document.getElementById(‘zt-tomcat-hardening’);
if(!root) return;
root.querySelectorAll(‘.zt-copy’).forEach(function(button){
button.addEventListener(‘click’,async function(){
var source=button.closest(‘.zt-code’).querySelector(‘.zt-source’);
var value=source ? source.textContent : ”;
try{await navigator.clipboard.writeText(value);button.textContent=’Tersalin’;}
catch(e){button.textContent=’Blok kode lalu salin’;}
setTimeout(function(){button.textContent=’Salin kode’;},1800);
});
});
})();

Tags:

cvehardeningremediatetomcatvulnerability
Author

Administrator

Administrator

Follow Me
Other Articles
Previous

Protected: Filosofi Logo ZONATA.ID: Satu Klik Lebih Pintar

No Comment! Be the first one.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

Archives

Recent Posts

  • Hardening Tomcat / Remediate Tomcat November 8, 2026
  • Protected: Filosofi Logo ZONATA.ID: Satu Klik Lebih Pintar November 8, 2026

Recent Comments

  • Administrator on Protected: Filosofi Logo ZONATA.ID: Satu Klik Lebih Pintar
  • Administrator on Protected: Filosofi Logo ZONATA.ID: Satu Klik Lebih Pintar

Tags

cve (1) filosofi (1) hardening (1) logo (1) remediate (1) tomcat (1) vulnerability (1)
Copyright 2026 — ZONATA.ID. All rights reserved.