Skip to content

Belajar Melakukan Application Security Testing

Saat mendengar istilah β€œkeamanan komputer”, biasanya yang berada dalam bayangan adalah hacking. Namun kini keamanan komputer sudah berubah menjadi industri dimana banyak vendor berlomba-lomba menawarkan produk keamanan mereka. Sepertinya security engineer akan lebih banyak menghabiskan waktu memilih produk keamanan untuk dipakai (atau berbicara dengan sales produk keamanan) ketimbang berada di situasi hacking yang menegangkan seperti di film aksi Hollywood πŸ˜€οΈ Sama seperti di industri lainnya, cyber security juga punya terminologi sendiri. Sebagai contoh, tool untuk menguji keamanan aplikasi biasanya dikategorikan menjadi:

  1. Static Application Security Testing (SAST)
  2. Dynamic Application Security Testing (DAST)
  3. Interactive Application Security Testing (IAST)

Bila aplikasi berjalan di cloud, terdapat beberapa kategori tool untuk memeriksa keamanan di cloud seperti:

  1. Cloud Workload Protection Platform (CWPP)
  2. Cloud Security Posture Management (CSPM)
  3. Cloud Access Security Broker (CASB)

Pada artikel ini, saya akan mencoba memakai beberapa tool gratis yang terdaftar di https://owasp.org/www-community/Free_for_Open_Source_Application_Security_Tools untuk melakukan pengujian keamanan aplikasi.

Static Application Security Testing (SAST)

SAST merupakan salah satu bentuk white-box testing dimana tool akan menganalisa seluruh kode program yang ada untuk mencari kemungkinan celah keamanan. Karena tidak perlu menjalankan aplikasi, ini adalah bentuk pengujian yang paling gampang di-integrasi-kan dengan tool CI/CD. Proses deployment dapat segera dihentikan bila tool SAST mendeteksi celah keamanan kritis di kode program.

SAST juga biasanya sangat mudah di-setup. Sebagai contoh, bila menggunakan GitHub, terdapat fitur code scanning yang gratis untuk public repository. Untuk mengaktifkannya, saya dapat memilih tab Security di repository saya, men-klik tab Overview dan men-klik tombol Set up code scanning. Secara bawaan, GitHub akan memakai CodeQL dimana saya hanya perlu men-klik tombol Configure CodeQL alerts. Ini akan menambahkan sebuah konfigurasi Github Actions baru dengan nama codeql-analysis.yml yang akan memanggil action seperti github/codeql-action/init dan github/codeql-action/analyze. Setelah ini, setiap kali commit pada branch main akan memicu eksekusi CodeQL.

Contoh hasil eksekusi GitHub Action yang melakukan pengujian SAST dengan CodeQL dapat dijumpai di https://github.com/JockiHendry/latihan-k8s/actions/runs/1911555844 milik repository publik saya. Untuk melihat hasil analisanya, saya dapat membuka tab Security dan memilih Code scanning alerts. Halaman ini tidak dapat di-akses oleh publik, namun sebagai pemilik repository, saya akan menemukan laporan seperti pada gambar berikut ini:

Tampilan Code Scanning Alerts Di Github

Selain diterapkan di CI/CD, tool SAST biasanya juga ter-integrasi dengan IDE sehingga programmer akan mendapatkan informasi keamanan kode program langsung tanpa harus menjalankan aplikasi. Sebagai latihan, saya akan mengaktifkan plugin Snyk di IDE IntelliJ IDEA yang saya pakai. Selain SAST, plugin Snyk ini juga akan melakukan Software Composition Analysis (SCA).

SCA adalah jenis security testing dimana tool akan menganalisa apakah kode program menggunakan library (langsung maupun tidak langsung) yang mengandung celah keamanan. Bila kode program yang ditulis oleh programmer sudah β€œbenar” dan β€œaman”, namun library atau framework aplikasi yang dipakai memiliki celah keamanan, tentu saja pada akhirnya aplikasi tidak aman.

Berikut ini adalah contoh hasil scan Snyk pada sebuah proyek Spring Boot di IntelliJ IDEA:

Tampilan Plugin Snyk Di IntelliJ IDEA

Pada hasil di atas, plugin Snyk menampilkan hasil SAC di bagian Open Source Security. Terlihat bahwa proyek ini memakai banyak dependency lama yang memiliki masalah keamanan dengan prioritas tinggi (high). Salah satunya adalah library ORM Hibernate 5.4.17 yang memiliki celah keamanan SQL Injection. Selain Open Source Security, juga terdapat bagian Code Security yang berisi informasi celah keamanan pada kode program dan Code Quality yang berisi saran untuk meningkatkan kualitas kode program.

Tool otomatis tidak selalu sempurna dan tidak bisa menggantikan analisa dari manusia. Sebagai contoh, pada hasil scan Snyk di atas, terdapat peringatan di bagian Code Security karena saya memakai @CrossOrigin("*") yang membolehkan front-end dari domain apa saja untuk memanggil back-end Spring Boot ini. Namun, ini sebenarnya memang apa yang hendak saya capai: endpoint di method ini khusus dipakai oleh publik. Untuk endpoint lainnya, saya sudah melakukan konfigurasi secara global di bean CorsConfigurationSource yang memanggil CorsConfiguration.setAllowedOrigins() dengan nama domain front-end saya. Dengan demikian, sesungguhnya tidak ada masalah keamanan di sini.

Dynamic Application Security Testing (DAST)

Kebalikan dari SAST, DAST adalah black-box testing yang tidak perlu mengakses kode program. Dengan demikian, tool DAST sama sekali tidak dibatasi oleh bahasa pemograman dan teknologi yang dipakai untuk membangun aplikasi. Tool DAST akan mengakses front-end dan mensimulasikan serangan, misalnya dengan mengirim masukan yang mengandung injeksi (untuk mendeteksi SQL Injection, XSS, dan sebagainya). Karena tool ini melakukan serangan secara langsung, ia hanya dipakai untuk server staging atau testing (bila ada). Bayangkan bila tool menyuntikkan SQL yang berhasil menghapus seluruh isi database dan ini dilakukan di server production πŸ˜€οΈ

Salah satu tool yang populer untuk melakukan DAST adalah OWASP Zed Attack Proxy (ZAP). Biasanya OWASP ZAP dipakai dengan menggunakan OWASP ZAP Desktop yang merupakan aplikasi desktop berbasis Java. OWASP ZAP Desktop sering dipakai untuk penetration testing (tersedia sebagai aplikasi bawaan di Kali Linux). Setelah membuka aplikasi desktop tersebut, pengguna mengetikkan URL yang hendak di-akses dan men-klik tombol untuk membuka browser yang dikendalikan oleh OWASP ZAP. Setiap kali pengguna berpindah halaman, ZAP Proxy akan menganalisa halaman baru tersebut. Walaupun mudah dipakai untuk penetration testing, tentu saja cara manual seperti ini tidak cocok untuk di-integrasi-kan pada pipeline CI/CD.

OWASP ZAP memiliki fitur spider untuk mencari URL secara otomatis (dengan melakukan crawling). Ini lebih tepat dipakai untuk CI/CD. Namun, salah satu masalah yang sering saya alami saat melakukan pengujian otomatis adalah authentication. OWASP ZAP akan mengalami kesulitan melakukan login pada OAuth2 sehingga fitur spider-nya tidak akan pernah bisa melewati halaman login yang sebenarnya bukan bagian dari aplikasi yang hendak diuji.

Solusi paling mudah adalah dengan mematikan fitur authentication (berdasarkan rekomendasi di https://zaproxy.org/docs/authentication/make-your-life-easier/). Oleh sebab itu, saya perlu men-deploy sebuah aplikasi baru dari repository yang sama, namun dengan fasilitas authentication yang telah dimatikan. Lagipula, walaupun authentication tidak dimatikan, saya tetap perlu men-deploy aplikasi yang berbeda dengan isi database yang berbeda agar pengujian DAST tidak merusak data yang ada di production.

Karena di aplikasi yang saya uji, fitur authentication ditangani Kong Ingress Controller, saya dapat mematikan authentication di back-end cukup dengan menghilang app-jwt-plugin pada annotations konghq.com/plugins di seluruh Ingress yang ada. Saya bisa mengotomatisasikan proses ini, misalnya dengan mengkonfigurasikan pipeline CI/CD supaya men-deploy dua versi aplikasi yang berbeda: dengan authentication dan tanpa authentication. Saat men-deploy versi tanpa authentication, saya dapat menggunakan function set-annotations dari Kpt untuk menghilangkan app-jwt-plugin di Ingress.

Di sisi front-end, saya dapat membuat sebuah konfigurasi Angular baru, misalnya environment.noauth.ts yang memiliki nilai auth berupa false seperti:

environment.noauth.ts
export const environment = {
production: true,
auth: false,
...
};

Saya kemudian membuat AuthService yang akan mengabaikan operasi seperti logoff() dan mengembalikan nama user yang di-hardcode bila nilai auth adalah false seperti pada contoh berikut ini:

auth.service.ts
@Injectable({
providedIn: 'root'
})
export class AuthService {
private oidcSecurityService: OidcSecurityService|null;
constructor(private injector: Injector) {
this.oidcSecurityService = environment.auth ? injector.get(OidcSecurityService) : null;
}
getUserData(): Observable<UserDataResult> {
if (this.oidcSecurityService) {
return this.oidcSecurityService.userData$;
} else {
return of({
userData: {
preferred_username: 'demo_user',
email: 'demo@jocki.me',
},
allUserData: []
});
}
}
logoff() {
if (this.oidcSecurityService != null) {
this.oidcSecurityService.logoff();
}
}
getAccessToken() {
return this.oidcSecurityService?.getAccessToken() ?? '';
}
}

Sekarang, bila ingin men-build aplikasi front-end yang tidak membutuhkan authentication, saya cukup memberikan perintah seperti berikut ini:

Terminal window
ng build --configuration noauth

Saya kemudian dapat melakukan konfigurasi pada pipeline CI/CD supaya menghasilkan dua image Docker dengan tag berbeda, misalnya yang di-build dengan --configuration noauth memiliki tag seperti latihan-k8s-angular-web:noauth-edge. Saya akan memakai image ini di namespace Kubernetes dimana fitur authentication-nya ingin dimatikan.

Untuk memakai OWASP ZAP di GitHub Actions, saya dapat menggunakan action resmi seperti OWASP ZAP Baseline Scan, OWASP ZAP Full Scan, atau OWASP ZAP API Scan. GitHub Action tersebut membutuhkan nilai target berupa URL yang akan diuji.

Saya juga dapat memakai image Docker owasp/zap2docker-stable yang telah disediakan oleh OWASP ZAP bila ingin menjalankan pengujian DAST dari CI/CD tool lain. Sebagai contoh, untuk menjalankan pengujian secara lokal, saya dapat memberikan perintah seperti berikut ini:

Terminal window
ng serve --configuration noauth --host 0.0.0.0
docker run -t owasp/zap2docker-stable zap-full-scan.py -t http://172.17.0.1:4200
Total of 11 URLs
PASS: Directory Browsing [0]
PASS: Vulnerable JS Library [10003]
PASS: Cookie No HttpOnly Flag [10010]
PASS: Cookie Without Secure Flag [10011]
PASS: Incomplete or No Cache-control Header Set [10015]
...
FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 6 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 49

Interactive Application Security Testing (IAST)

Bila dilihat dari cara kerjanya, IAST mirip seperti DAST: selama pengujian, aplikasi harus aktif dan dapat di-akses. Salah satu kelemahan DAST adalah karena ia diakses dari eksternal oleh sebuah tool yang mewakili pengguna, ia tidak memiliki informasi tentang kode program yang sedang dikerjakan. Bila tool mendeteksi celah keamanan, ia hanya bisa menambahkan informasi seperti URL, request/response, dan sebagainya. Tool DAST tidak dapat menunjukkan baris kode program mana yang bermasalah dan perlu diperbaiki. Sebagai kebalikannya, tool SAST dapat menunjukkan secara persis kode program mana yang bermasalah dan merekomendasikan perbaikannya.

Tool IAST berusaha menggabungkan SAST dan DAST. Pada saat menggunakan tool IAST, aplikasi perlu menambahkan instrumentasi tertentu (tergantung pada vendor) seperti menambahkan library milik vendor dan menulis beberapa baris kode program yang melakukan inisialisasi. Berkat instrumentasi ini, IAST dapat melakukan lebih banyak analisa dan memberikan informasi yang lebih berguna saat menemukan celah keamanan. Bila instrumentasi ini tidak dimatikan di production, tool IAST akan terus bekerja mendeteksi celah keamanan saat aplikasi dipakai oleh pengguna.

Karena tidak berhasil mendapatkan tool IAST yang bisa dipakai secara gratis dan mendukung registrasi dari email pribadi, saya tidak tahu seperti apa implementasi IAST, seberapa akurat hasilnya, apa dampak instrumentasi pada kinerja aplikasi, dan sebagainya.

Cloud Security Posture Management (CSPM)

CSPM adalah kategori tool yang dapat dipakai untuk mendeteksi masalah keamanan pada konfigurasi di cloud platform. CSPM juga biasanya dipakai untuk cloud compliance. Salah satu tool CSPM yang open source adalah CloudSploit. Tool ini mendukung cloud platform populer seperti Alibaba, AWS, Azure, GCP, dan OCI. Untuk compliance, CloudSploit mendukung Health Insurance Portability and Accountability Act of 1996 (HIPAA), Payment Card Industry Data Security Standard (PCI DSS), dan CIS Benchmarks Level 1 & Level 2.

Karena tidak menemukan binary siap pakai di repository dan juga image resmi di DockerHub, saya akan menjalankan CloudSploit secara langsung dari kode programnya di branch master. CloudSploit ditulis dengan menggunakan JavaScript, jadi saya perlu memastikan bahwa Node.js sudah ter-install di komputer saya. Setelah itu, saya memberikan perintah berikut ini:

Terminal window
git clone https://github.com/aquasecurity/cloudsploit.git
cd cloudsploit
npm install
chmod +x index.js

Sebelum menjalankan index.js, saya perlu membuat sebuah service account di proyek GCP yang hendak di-scan. Saya dapat melakukannya dengan langkah-langkah seperti berikut ini:

  1. Buka menu IAM & Admin dari Google Cloud Console dan pilih Service Accounts.
  2. Isi nama service account dengan nilai berupa csm-security-audit (boleh apa saja).
  3. Klik tombol Done.
  4. Pastikan terdapat nama csm-security-audit dari daftar service account yang muncul. Klik nama service account tersebut.
  5. Buka tab Keys dan klik tombol Add Key, Create New Key. Pilih JSON dan klik tombol Create.
  6. Buka file yang di-download dan salin isinya ke clipboard.

Saya kemudian membuat sebuah file baru dengan nama config.js yang isinya seperti berikut ini:

config.js
// CloudSploit config file
module.exports = {
credentials: {
alibaba: {},
aws: {},
aws_remediate: {},
azure: {},
azure_remediate: {},
google: {
"project": "nama_proyek_gcp",
"private_key": "<salin dari file service account>",
"client_email": "<salin dari file service account>",
},
oracle: {},
github: {}
}
};

Di property google, saya mengisi project dengan nama proyek GCP yang hendak di-scan. Nilai private_key dan client_email dapat diambil dari isi file service account yang barusan saya download.

Selanjutnya, saya akan memberikan permission pada service account tersebut supaya mendapatkan hak akses baca ke seluruh resources yang ada. Untuk itu, saya melakukan langkah-langkah berikut ini di Google Cloud Console:

  1. Buka menu IAM & Admin, IAM.
  2. Klik tombol Add.
  3. Isi nilai Principal dengan nama service account yang buat (seperti csmp-security-audit@nama-proyek.iam.gserviceaccount.com). Tambahkan Role berupa Viewer.
  4. Klik tombol Save.

Sekarang, saya siap untuk memulai scanning proyek GCP. Untuk itu, saya memberikan perintah berikut ini:

Terminal window
./index.js --compliance=pci --config ./config.js --cloud google --junit result-pci.xml
_____ _ _ _____ _ _ _
/ ____| | | |/ ____| | | (_) |
| | | | ___ _ _ __| | (___ _ __ | | ___ _| |_
| | | |/ _ \| | | |/ _` |\___ \| '_ \| |/ _ \| | __|
| |____| | (_) | |_| | (_| |____) | |_) | | (_) | | |_
\_____|_|\___/ \__,_|\__,_|_____/| .__/|_|\___/|_|\__|
| |
|_|
CloudSploit by Aqua Security, Ltd.
Cloud security auditing for AWS, Azure, GCP, Oracle, and GitHub
INFO: Using CloudSploit config file: ./config.js
INFO: Using compliance modes: pci
INFO: Skipping AWS pagination mode
INFO: Determining API calls to make...
DEBUG: Skipping plugin Open Cassandra because it is not used for compliance programs
DEBUG: Skipping plugin Open DNS because it is not used for compliance programs
DEBUG: Skipping plugin Open Docker because it is not used for compliance programs
DEBUG: Skipping plugin Open SSH because it is not used for compliance programs
...
INFO: Found 19 API calls to make for google plugins
INFO: Collecting metadata. This may take several minutes...
INFO: Metadata collection complete. Analyzing...
INFO: Analysis complete. Scan report to follow...
INFO: JUnit file written to result-pci.xml
β”‚ Cat β”‚ Plugi β”‚ Description β”‚ Resource β”‚ Reg β”‚ Sta β”‚ Message β”‚ Compliance β”‚
β”‚ ego β”‚ n β”‚ β”‚ β”‚ ion β”‚ tus β”‚ β”‚ β”‚
β”‚ ry β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ VPC β”‚ Exces β”‚ Determines if there are an β”‚ N/A β”‚ glo β”‚ OK β”‚ Acceptable number of β”‚ PCI: PCI has strict requirements to segment networks using β”‚
β”‚ Net β”‚ sive β”‚ excessive number of β”‚ β”‚ bal β”‚ β”‚ firewall rules: 4 rules β”‚ firewalls. Firewall Rules are a software-layer firewall that β”‚
β”‚ wor β”‚ Firew β”‚ firewall rules in the β”‚ β”‚ β”‚ β”‚ present β”‚ should be used to isolate resources. Ensure the number of β”‚
β”‚ k β”‚ all β”‚ account β”‚ β”‚ β”‚ β”‚ β”‚ groups does not become unmanageable. β”‚
β”‚ β”‚ Rules β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ VPC β”‚ Open β”‚ Determines if all ports are β”‚ N/A β”‚ glo β”‚ OK β”‚ No public open ports found β”‚ PCI: PCI has explicit requirements around firewalled access to β”‚
β”‚ Net β”‚ All β”‚ open to the public β”‚ β”‚ bal β”‚ β”‚ β”‚ systems. Firewalls should be properly secured to prevent access β”‚
β”‚ wor β”‚ Ports β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ to backend services. β”‚
β”‚ k β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ VPC β”‚ Defau β”‚ Determines whether the β”‚ β”‚ glo β”‚ OK β”‚ Default VPC is not in use β”‚ PCI: PCI has explicit requirements around default accounts and β”‚
β”‚ Net β”‚ lt β”‚ default VPC is being used β”‚ β”‚ bal β”‚ β”‚ β”‚ resources. PCI recommends removing all default accounts, only β”‚
β”‚ wor β”‚ VPC β”‚ for launching VM instances β”‚ β”‚ β”‚ β”‚ β”‚ enabling necessary services as required for the function of the β”‚
β”‚ k β”‚ In β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ system β”‚
β”‚ β”‚ Use β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ VPC β”‚ Flow β”‚ Ensures VPC flow logs are β”‚ β”‚ us- β”‚ FAI β”‚ The subnet does not have β”‚ PCI: PCI requires logging of all network access to environments β”‚
β”‚ Net β”‚ Logs β”‚ enabled for traffic logging β”‚ β”‚ eas β”‚ L β”‚ flow logs enabled β”‚ containing cardholder data. Enable VPC flow logs to log these β”‚
β”‚ wor β”‚ Enabl β”‚ β”‚ β”‚ t1 β”‚ β”‚ β”‚ network requests. β”‚
β”‚ k β”‚ ed β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ VPC β”‚ Priva β”‚ Ensures Private Google β”‚ β”‚ us- β”‚ FAI β”‚ Subnet does not have Private β”‚ PCI: PCI recommends implementing additional security features β”‚
β”‚ Net β”‚ te β”‚ Access is enabled for all β”‚ β”‚ eas β”‚ L β”‚ Google Access Enabled β”‚ for any required service. This includes using secured β”‚
β”‚ wor β”‚ Acces β”‚ Subnets β”‚ β”‚ t1 β”‚ β”‚ β”‚ technologies such as Private Google Access. β”‚
β”‚ k β”‚ s β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ Enabl β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ ed β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ Com β”‚ OS β”‚ Ensures OS login is enabled β”‚ β”‚ glo β”‚ OK β”‚ OS login is enabled by β”‚ PCI: PCI recommends implementing additional security features β”‚
β”‚ put β”‚ Login β”‚ for the project β”‚ β”‚ bal β”‚ β”‚ default β”‚ for any required service. This includes using secured β”‚
β”‚ e β”‚ Enabl β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ technologies such as SSH. β”‚
β”‚ β”‚ ed β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ SQL β”‚ DB β”‚ Ensures SQL instances can β”‚ β”‚ glo β”‚ OK β”‚ SQL instance has backup β”‚ PCI: PCI requires that security procedures, including β”‚
β”‚ β”‚ Resto β”‚ be restored to a recent β”‚ β”‚ bal β”‚ β”‚ available β”‚ restoration of compromised services, be tested frequently. RDS β”‚
β”‚ β”‚ rable β”‚ point β”‚ β”‚ β”‚ β”‚ β”‚ restorable time indicates the last known time to which the β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ instance can be restored. β”‚
β”‚ SQL β”‚ DB β”‚ Ensures that SQL instances β”‚ β”‚ glo β”‚ OK β”‚ SQL Instance is not publicly β”‚ PCI: PCI requires backend services to be properly firewalled. β”‚
β”‚ β”‚ Publi β”‚ do not allow public access β”‚ β”‚ bal β”‚ β”‚ accessible β”‚ Ensure SQL instances are not accessible from the Internet and β”‚
β”‚ β”‚ cly β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ use proper jump box access mechanisms. β”‚
β”‚ β”‚ Acces β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ sible β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
...
INFO: Scan complete

Pada perintah di atas, saya menggunakan --compliance=pci untuk memeriksa apakah konfigurasi proyek GCP tersebut sudah sesuai dengan standar PCI DSS. Nilai --config ./config.js merujuk pada file konfigurasi yang saya buat sebelumnya (pastikan untuk diawali dengan tanda titik). Selain itu, saya menambahkan --junit result-pci.xml supaya CloudSploit juga menulis hasil pengujian pada file result-pci.xml (di folder yang sama) dalam format JUnit. Saya kemudian dapat membuka file ini di IntelliJ IDEA seperti yang terlihat pada gambar berikut ini:

Tampilan Hasil Scan Di JUnit

Terlihat bahwa proyek GCP yang saya scan masih memiliki 132 item yang masih tidak memenuhi aturan di PCI DSS seperti koneksi database SQL tidak menggunakan SSL, beberapa service account memiliki key yang usianya lebih dari 90 hari (tidak dirotasi), tidak ada log alert bila terjadi perubahan project ownership, dan sebagainya.