Cyber RoadmapINDONESIA

Fondasi · Fase 1

String Manipulation dan Regex Dasar untuk Parsing Log dengan Python

Log asli tidak serapi contoh di buku. Pelajari fungsi string Python, dasar regex, grup bernama, dan modul re, lalu terapkan untuk mengurai log SSH dari /var/log/auth.log: menghitung login gagal, menemukan akun palsu, dan mendeteksi login berhasil setelah gagal.

Di artikel Dasar Python untuk Keamanan Siber, kita membuat skrip penghitung login gagal dari log yang formatnya sengaja dibuat rapi. Di dunia nyata, log tidak serapi itu. Satu baris bisa berisi tanggal, nama mesin, nama program, nomor proses, lalu pesan yang susunannya berbeda-beda.

Untuk mengurai log seperti itu, kamu butuh dua keterampilan: manipulasi string, yaitu mengolah teks dengan fungsi-fungsi bawaan Python, dan regex (regular expression), yaitu bahasa kecil untuk mencari pola di dalam teks. Keduanya dipakai setiap hari oleh analis SOC, penanggap insiden, dan siapa pun yang bekerja dengan log.

Mengenal log SSH yang asli

Di Ubuntu dan Debian, catatan login SSH tersimpan di /var/log/auth.log. Di keluarga Red Hat, lokasinya /var/log/secure. Di sistem yang hanya memakai journal, kamu bisa melihatnya dengan journalctl -u ssh, seperti di artikel Proses di Linux.

Bagian-bagian satu baris log SSH dari auth.log: waktu, nama mesin, program dan PID, status Failed password, invalid user, nama akun, alamat IP, dan port
Bagian-bagian satu baris log SSH dari auth.log: waktu, nama mesin, program dan PID, status Failed password, invalid user, nama akun, alamat IP, dan port

Ada satu detail penting. Kalau penyerang mencoba nama akun yang tidak ada di server, log menambahkan kata invalid user sebelum namanya. Ini petunjuk berharga, karena orang yang sah jarang salah mengetik nama akunnya sendiri, sedangkan penyerang biasanya menebak nama-nama umum seperti admin, test, atau oracle.

Manipulasi string: alat dasar mengolah teks

Sebelum memakai regex, kenali dulu fungsi string bawaan. Untuk banyak tugas sederhana, fungsi-fungsi ini sudah cukup dan lebih mudah dibaca.

baris = "  Nov  5 08:01:12 lab sshd[1201]: Failed password for budi from 203.0.113.7 port 52344 ssh2\n"

bersih = baris.strip()               # buang spasi dan baris baru di awal dan akhir
print(bersih.startswith("Nov"))      # True
print("Failed" in bersih)            # True
print(bersih[:15])                   # Nov  5 08:01:12  (15 karakter pertama)

bagian = bersih.split()              # pecah berdasarkan spasi
print(bagian[8], bagian[10])         # budi 203.0.113.7

print(bersih.replace("budi", "[disensor]"))
# Nov  5 08:01:12 lab sshd[1201]: Failed password for [disensor] from 203.0.113.7 port 52344 ssh2

print(" | ".join(["203.0.113.7", "5 kali", "BLOKIR"]))
# 203.0.113.7 | 5 kali | BLOKIR
Fungsi string yang paling sering dipakai untuk log
FungsiKegunaanContoh
strip()Membuang spasi dan baris baru di tepibaris.strip()
lower(), upper()Menyamakan huruf besar dan kecil sebelum dibandingkanbaris.lower()
split()Memecah teks menjadi listbaris.split(":")
startswith(), endswith()Memeriksa awal atau akhir teksnama.endswith(".log")
inMemeriksa apakah sebuah kata ada di dalam teks"Failed" in baris
replace()Mengganti sebagian teksbaris.replace("budi", "***")
teks[a:b]Mengambil potongan teks (slicing)baris[:15]
"pemisah".join(list)Menggabungkan list menjadi teks", ".join(akun)

Kapan split() tidak cukup

Masalah muncul ketika susunan kata berubah. Perhatikan baris dengan invalid user:

baris = "Nov  5 08:03:01 lab sshd[1222]: Failed password for invalid user admin from 203.0.113.7 port 52401 ssh2"
print(baris.split()[8])              # invalid  (bukan nama pengguna!)

Karena ada dua kata tambahan, posisi nama akun bergeser. Cara split() yang bergantung pada nomor posisi langsung salah. Di sinilah regex lebih unggul: ia mencari pola, bukan posisi.

Regex: mencari pola, bukan posisi

Regex adalah susunan simbol yang menggambarkan bentuk teks yang dicari. Misalnya, "satu atau lebih angka, lalu titik, diulang empat kali" adalah gambaran sebuah alamat IPv4.

Contekan dua belas simbol regex dasar seperti backslash d, backslash w, plus, tanda tanya, kurung kurawal, dan grup, beserta arti dan contohnya
Contekan dua belas simbol regex dasar seperti backslash d, backslash w, plus, tanda tanya, kurung kurawal, dan grup, beserta arti dan contohnya

Di Python, regex ada di modul bawaan re. Fungsi yang paling sering dipakai adalah re.search(), yang mencari kecocokan pertama di sebuah teks.

import re

baris = "Nov  5 08:03:01 lab sshd[1222]: Failed password for invalid user admin from 203.0.113.7 port 52401 ssh2"

cocok = re.search(r"from (\d+\.\d+\.\d+\.\d+) port (\d+)", baris)
if cocok:
    print(cocok.group(1))            # 203.0.113.7
    print(cocok.group(2))            # 52401

Tanda kurung ( ) membuat grup. Setiap grup menangkap bagian teks yang cocok, lalu bisa diambil dengan group(1), group(2), dan seterusnya. Titik ditulis \. karena titik biasa berarti "karakter apa saja".

Fungsi penting lainnya:

teks = "Serangan dari 203.0.113.7 dan 198.51.100.4, lalu 203.0.113.7 lagi."
pola_ip = r"\d{1,3}(?:\.\d{1,3}){3}"

print(re.findall(pola_ip, teks))
# ['203.0.113.7', '198.51.100.4', '203.0.113.7']

print(sorted(set(re.findall(pola_ip, teks))))     # tanpa duplikat
# ['198.51.100.4', '203.0.113.7']

print(re.sub(pola_ip, "x.x.x.x", teks))           # menyamarkan IP
# Serangan dari x.x.x.x dan x.x.x.x, lalu x.x.x.x lagi.
Fungsi utama modul re
FungsiHasilnyaCocok untuk
re.search(pola, teks)Kecocokan pertama, atau NoneMengambil data dari satu baris
re.findall(pola, teks)List semua kecocokanMengumpulkan semua IP di sebuah teks
re.sub(pola, ganti, teks)Teks yang sudah digantiMenyamarkan data pribadi sebelum log dibagikan
re.compile(pola)Pola yang siap dipakai berulangMengurai ribuan baris dengan pola yang sama

Grup bernama: hasil yang mudah dibaca

Kalau grupnya banyak, group(1), group(2), dan group(3) mudah tertukar. Python mendukung grup bernama dengan tulisan (?P<nama>...). Hasilnya bisa diambil sebagai dictionary.

Pola regex dengan grup bernama user, ip, dan port dipetakan ke teks log dan hasil groupdict
Pola regex dengan grup bernama user, ip, dan port dipetakan ke teks log dan hasil groupdict

Proyek: menganalisis log SSH

Sekarang kita buat pengurai log SSH yang sungguhan. Simpan contoh log berikut sebagai auth.log. Isinya meniru format asli Ubuntu, termasuk baris dari program lain (CRON) yang harus diabaikan.

Nov  5 08:01:12 lab sshd[1201]: Failed password for budi from 203.0.113.7 port 52344 ssh2
Nov  5 08:01:15 lab sshd[1201]: Failed password for budi from 203.0.113.7 port 52344 ssh2
Nov  5 08:02:40 lab sshd[1210]: Accepted password for sari from 198.51.100.4 port 50122 ssh2
Nov  5 08:03:01 lab sshd[1222]: Failed password for invalid user admin from 203.0.113.7 port 52401 ssh2
Nov  5 08:03:05 lab sshd[1222]: Failed password for invalid user oracle from 203.0.113.7 port 52401 ssh2
Nov  5 08:03:09 lab sshd[1225]: Failed password for root from 203.0.113.7 port 52455 ssh2
Nov  5 08:04:00 lab CRON[1230]: pam_unix(cron:session): session opened for user root by (uid=0)
Nov  5 08:06:30 lab sshd[1240]: Failed password for budi from 192.0.2.50 port 41000 ssh2
Nov  5 08:06:35 lab sshd[1240]: Failed password for budi from 192.0.2.50 port 41000 ssh2
Nov  5 08:06:40 lab sshd[1240]: Failed password for budi from 192.0.2.50 port 41000 ssh2
Nov  5 08:07:02 lab sshd[1244]: Accepted password for budi from 192.0.2.50 port 41022 ssh2

Lalu buat file parse_auth.py:

# parse_auth.py - mengurai log SSH dan mencari pola mencurigakan
import re
import sys
from collections import Counter

POLA = re.compile(
    r"(?P<status>Failed|Accepted) password for "
    r"(?P<invalid>invalid user )?(?P<user>\S+) "
    r"from (?P<ip>\d{1,3}(?:\.\d{1,3}){3}) port (?P<port>\d+)"
)


def urai_log(nama_file):
    """Mengambil data penting dari setiap baris login SSH."""
    kejadian = []
    with open(nama_file, "r", encoding="utf-8", errors="replace") as f:
        for baris in f:
            cocok = POLA.search(baris)
            if cocok:
                kejadian.append(cocok.groupdict())
    return kejadian


def analisis(kejadian):
    gagal_ip = Counter()
    gagal_user = Counter()
    akun_palsu = set()
    berhasil_setelah_gagal = []

    for k in kejadian:
        if k["status"] == "Failed":
            gagal_ip[k["ip"]] += 1
            gagal_user[k["user"]] += 1
            if k["invalid"]:
                akun_palsu.add(k["user"])
        elif gagal_ip[k["ip"]] > 0:
            berhasil_setelah_gagal.append(f'{k["user"]} dari {k["ip"]}')

    print("Login gagal per IP:")
    for ip, n in gagal_ip.most_common():
        print(f"  {ip:<15} {n} kali")
    print("Akun yang paling sering dicoba:", ", ".join(u for u, _ in gagal_user.most_common(3)))
    print("Akun yang tidak ada di sistem:", ", ".join(sorted(akun_palsu)) or "-")
    for item in berhasil_setelah_gagal:
        print(f"PERHATIAN: berhasil login setelah gagal -> {item}")


if __name__ == "__main__":
    analisis(urai_log(sys.argv[1] if len(sys.argv) > 1 else "auth.log"))

Perhatikan pola regex di bagian atas. Bagian (?P<invalid>invalid user )? diakhiri tanda tanya, artinya boleh ada boleh tidak. Dengan satu pola saja, baris biasa dan baris invalid user sama-sama terurai dengan benar, masalah yang tidak bisa diatasi split(). Baris CRON tidak cocok dengan pola, sehingga otomatis terlewati.

Opsi errors="replace" saat membuka file membuat skrip tidak berhenti kalau ada karakter aneh di log, sesuatu yang cukup sering terjadi karena penyerang kadang sengaja mengirim data acak.

Bonus: regex di terminal

Regex tidak hanya ada di Python. Perintah grep yang sudah kamu kenal di artikel Navigasi Terminal Linux juga mendukungnya. Untuk analisis cepat tanpa menulis skrip, gabungan perintah ini sangat berguna:

grep "Failed password" auth.log | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort | uniq -c | sort -rn
#       5 203.0.113.7
#       3 192.0.2.50

Opsi -E mengaktifkan regex versi lengkap, dan -o hanya menampilkan bagian yang cocok. Lalu sort, uniq -c, dan sort -rn menghitung dan mengurutkannya. Hasilnya sama dengan skrip Python kita, dalam satu baris. Kapan pakai yang mana? Terminal cocok untuk pemeriksaan cepat. Python cocok kalau logikanya mulai rumit, seperti mendeteksi login berhasil setelah gagal.

Kebiasaan baik saat mengurai log

  • Uji regex dengan contoh nyata sebelum dipakai ke log besar. Situs seperti regex101.com membantu melihat bagian mana yang cocok. Jangan menempelkan log asli yang berisi data sensitif ke situs pihak ketiga, pakai contoh yang sudah disamarkan.
  • Buat pola sespesifik mungkin. Sertakan kata penanda seperti from dan port agar tidak salah tangkap.
  • Anggap isi log tidak bisa dipercaya. Nama pengguna di log ditulis oleh siapa pun yang mencoba login, termasuk penyerang. Jangan pernah menjalankan isi log sebagai perintah.
  • Samarkan data pribadi dengan re.sub() sebelum membagikan potongan log ke orang lain.

Kenapa ini penting untuk keamanan siber

Hampir semua jejak serangan tersimpan sebagai teks: log server, log firewall, log aplikasi web, dan catatan sistem deteksi. Alat besar seperti SIEM juga bekerja dengan mengurai log memakai pola seperti regex. Kalau kamu bisa membuat pola sendiri, kamu bisa mengolah log apa pun, menulis aturan deteksi, dan menemukan pola serangan yang tidak terlihat kalau dibaca satu per satu.

Ringkasan

  • Fungsi string seperti strip(), split(), replace(), dan in cukup untuk teks yang formatnya tetap.
  • Kalau susunan teks bisa berubah, gunakan regex yang mencari pola, bukan posisi.
  • Simbol dasar regex: \d, \w, \s, \S, +, *, ?, {n,m}, [ ], ^, $, dan grup ( ).
  • Modul re menyediakan search(), findall(), sub(), dan compile().
  • Grup bernama (?P<nama>...) membuat hasil mudah dipakai lewat groupdict().
  • grep -oE membawa kekuatan regex ke terminal untuk analisis cepat.

Tonton dan baca juga

Materi berikutnya membawa Python keluar dari komputermu: memakai pustaka requests untuk berkomunikasi dengan API dan mengambil data dari situs web. Buka di roadmap untuk melanjutkan.

Bermanfaat? Dukung konten berikutnya

Semua materi di sini gratis. Dukunganmu dipakai untuk membeli alat lab untuk praktik, eksplorasi, dan riset konten keamanan siber berikutnya.

Traktir di Trakteer ↗
Sampul course Cyber Security Fundamental

Pelajari lebih dalam

Cyber Security Fundamental di WPU Course

Lihat course ↗

Materi terkait di roadmap

Artikel lainnya

Artikel ini bersifat edukatif. Praktikkan teknik ofensif hanya di lingkungan yang kamu miliki izinnya. Baca Disclaimer.