Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
af4af02
tambah sort di kolom jumlah ke semua statistik data presisi
habibie11 Feb 13, 2026
54a61c4
fix(user) : optimization query API
Revanza1106 Feb 21, 2026
0412f0f
fix(user) : query optimazation API with collection map
Revanza1106 Feb 21, 2026
46c7f2d
fix(web): eager load category for article
Revanza1106 Feb 21, 2026
2a3303a
Merge branch 'rilis-dev' into dev-sort-statistik-presisi
habibie11 Feb 26, 2026
c4a5f20
[ci skip] memutahirkan catatan rilis
vickyrolanda Feb 27, 2026
e1af86e
Merge pull request #940 from OpenSID/dev-sort-statistik-presisi
vickyrolanda Feb 27, 2026
140e09e
Merge remote-tracking branch 'origin/master' into rilis-dev
pandigresik Mar 4, 2026
bca3f83
Tambahkan filter tahun pada statistik papan & sandang data presisi
pandigresik Mar 4, 2026
811e8d2
Tambahkan filter tahun pada statistik seni budaya & pendidikan data p…
pandigresik Mar 4, 2026
4e21cbf
Tambahkan filter tahun pada statistik kesehatan & jaminan sosial data…
pandigresik Mar 4, 2026
dcbd3e7
fix: list menu tidak tampil
pandigresik Mar 4, 2026
c6c25d5
add artikel opensid ke frontend
habibie11 Mar 4, 2026
09b830c
tambahkan test
pandigresik Mar 4, 2026
585468a
tambahkan filter tahun pada statistik Aktivitas Keagamaan & ketenagak…
pandigresik Mar 4, 2026
933c65b
[SECURITY] Implementasi & Perkuat Rate Limiting pada Semua Endpoint K…
pandigresik Mar 5, 2026
fa6eb7c
hapus code yang tidak dipakai
pandigresik Mar 5, 2026
819f8f0
Merge branch 'rilis-dev' into fix/n+1-problem
Revanza1106 Mar 5, 2026
c86cf38
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 6, 2026
092433a
Merge pull request #944 from Revanza1106/fix/n+1-problem
vickyrolanda Mar 6, 2026
908ef03
Merge branch 'rilis-dev' into dev-946
vickyrolanda Mar 6, 2026
103e496
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 6, 2026
3c49135
Merge pull request #947 from OpenSID/dev-946
vickyrolanda Mar 6, 2026
c2dbba0
Merge branch 'rilis-dev' into dev-948
vickyrolanda Mar 6, 2026
759500c
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 6, 2026
cfa5de3
Merge pull request #949 from OpenSID/dev-948
vickyrolanda Mar 6, 2026
38b9c14
Terapkan CAPTCHA pada Login & Endpoint Auth untuk Batasi Bot/Bruteforce
pandigresik Mar 9, 2026
b362264
perbaikan hardcode
pandigresik Mar 9, 2026
8096579
Jadikan Content Security Policy (CSP) Selalu Aktif, Tidak Boleh Auto-…
pandigresik Mar 9, 2026
08547bd
Prevent IDOR (Insecure Direct Object Reference) pada Endpoint Berbasi…
pandigresik Mar 9, 2026
94042dd
[SECURITY] Enforce Strong Password Policy di Seluruh Fitur (Change/Re…
pandigresik Mar 11, 2026
22511d5
perbaikan extends layout
pandigresik Mar 11, 2026
fd7757d
update
pandigresik Mar 11, 2026
13850c3
Merge branch 'rilis-dev' into dev-950
vickyrolanda Mar 12, 2026
f62daf0
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 12, 2026
0323c88
Merge pull request #951 from OpenSID/dev-950
vickyrolanda Mar 12, 2026
8c557b9
Merge branch 'rilis-dev' into dev-952
vickyrolanda Mar 12, 2026
4656e2b
Merge pull request #970 from OpenSID/dev-952
vickyrolanda Mar 12, 2026
ab65eb8
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 12, 2026
4c797cd
Merge branch 'rilis-dev' into dev-954
vickyrolanda Mar 12, 2026
910c357
Merge pull request #956 from OpenSID/dev-954
vickyrolanda Mar 12, 2026
d122487
Merge branch 'rilis-dev' into dev-942
vickyrolanda Mar 12, 2026
b82795a
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 12, 2026
8c33f75
Merge pull request #960 from OpenSID/dev-942
vickyrolanda Mar 12, 2026
495d8e3
feat: Implement XSS prevention by integrating HTML Purifier, sanitizi…
habibie11 Mar 16, 2026
9d6fa09
Apply suggestion from @habibie11
pandigresik Mar 25, 2026
d7739a9
Merge branch 'rilis-dev' into dev-969
vickyrolanda Mar 29, 2026
64e750b
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 29, 2026
413cbc7
Merge pull request #976 from OpenSID/dev-969
vickyrolanda Mar 29, 2026
c1a80c8
Merge branch 'rilis-dev' into dev-962
vickyrolanda Mar 29, 2026
f4bdde9
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 29, 2026
5927c97
Merge pull request #985 from OpenSID/dev-962
vickyrolanda Mar 29, 2026
b4c97b7
Merge remote-tracking branch 'origin/rilis-dev' into dev-968
pandigresik Mar 29, 2026
f76a5f1
Merge remote-tracking branch 'origin/rilis-dev' into dev-966
pandigresik Mar 29, 2026
ee3436c
Merge remote-tracking branch 'origin/rilis-dev' into dev-963
pandigresik Mar 29, 2026
50583da
Persiapan rilis 2604.0.0
pandigresik Mar 29, 2026
ab2f078
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 30, 2026
850a86c
Merge pull request #978 from OpenSID/dev-966
vickyrolanda Mar 30, 2026
2f4b08d
Merge branch 'rilis-dev' into dev-968
vickyrolanda Mar 30, 2026
e7bfade
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 30, 2026
cdec378
Merge pull request #977 from OpenSID/dev-968
vickyrolanda Mar 30, 2026
1677fa2
Merge branch 'rilis-dev' into dev-963
vickyrolanda Mar 30, 2026
5fb293f
[ci skip] memutahirkan catatan rilis
vickyrolanda Mar 30, 2026
22d37b5
Merge pull request #979 from OpenSID/dev-963
vickyrolanda Mar 30, 2026
201a686
Merge branch 'rilis-dev' into rilis-v2604.0.0
pandigresik Mar 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
TELEGRAM_BOT_NAME=@your_bot_username_here

# Global Rate Limiter Configuration
RATE_LIMITER_ENABLED=false
# IMPORTANT: Keep RATE_LIMITER_ENABLED=true for production to prevent brute-force and DDoS attacks
RATE_LIMITER_ENABLED=true
RATE_LIMITER_MAX_ATTEMPTS=60
RATE_LIMITER_DECAY_MINUTES=1

# Account Lockout Configuration
# Temporary lock after repeated failed login attempts
ACCOUNT_LOCKOUT_MAX_ATTEMPTS=5
ACCOUNT_LOCKOUT_DECAY_MINUTES=15

# Progressive Delay Configuration
# Additional delay (in seconds) added after each failed attempt
PROGRESSIVE_DELAY_BASE_SECONDS=2
PROGRESSIVE_DELAY_MULTIPLIER=2
280 changes: 280 additions & 0 deletions app/Console/Commands/AuditWeakPasswords.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
<?php

namespace App\Console\Commands;

use App\Models\PasswordHistory;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class AuditWeakPasswords extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'password:audit-weak {--force : Force flag without confirmation} {--dry-run : Show what would be done without making changes}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Audit existing users for weak passwords and force password reset';

/**
* Minimum password length for strong password.
*/
protected int $minLength = 12;

/**
* Common passwords list.
*/
protected array $commonPasswords = [
'password',
'password123',
'123456',
'123456789',
'qwerty',
'abc123',
'monkey',
'master',
'dragon',
'letmein',
'login',
'admin',
'welcome',
'admin123',
'root',
'toor',
'pass',
'test',
'guest',
'guest123',
];

/**
* Weak patterns to check.
*/
protected array $weakPatterns = [
'/^(.)\1{5,}$/', // Same character repeated 6+ times
'/^(012|123|234|345|456|567|678|789|890)/', // Sequential numbers
'/^(abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz)/i', // Sequential letters
];

/**
* Execute the console command.
*/
public function handle()
{
$this->info('=== Audit Password Lemah ===');
$this->newLine();

$dryRun = $this->option('dry-run');
$force = $this->option('force');

if ($dryRun) {
$this->warn('MODE DRY-RUN: Tidak ada perubahan yang akan dilakukan.');
$this->newLine();
}

// Get all users
$users = User::all();
$totalUsers = $users->count();
$weakPasswordCount = 0;
$affectedUsers = [];

$this->info("Memeriksa {$totalUsers} user...");
$this->newLine();

$bar = $this->output->createProgressBar($totalUsers);
$bar->start();

foreach ($users as $user) {
$bar->advance();

// Skip users without password (e.g., OAuth users)
if (!$user->password) {
continue;
}

if ($this->isPasswordWeak($user->password)) {
$weakPasswordCount++;
$affectedUsers[] = [
'id' => $user->id,
'email' => $user->email,
'name' => $user->name,
'reason' => $this->getWeakReason($user->password),
];

if (!$dryRun) {
$this->flagUserForPasswordReset($user);
}
}
}

$bar->finish();
$this->newLine(2);

$this->table(
['ID', 'Email', 'Name', 'Alasan'],
$affectedUsers
);

$this->newLine();
$this->info("Ditemukan {$weakPasswordCount} user dengan password lemah dari {$totalUsers} total user.");

if ($dryRun) {
$this->warn("Dry-run selesai. Jalankan tanpa --dry-run untuk menerapkan perubahan.");
return 0;
}

if ($weakPasswordCount > 0 && !$force) {
if (!$this->confirm("Apakah Anda yakin ingin memaksa {$weakPasswordCount} user untuk reset password?")) {
$this->info('Operasi dibatalkan.');
return 1;
}

// Re-flag all users since confirmation was given
foreach ($affectedUsers as $userData) {
$user = User::find($userData['id']);
$this->flagUserForPasswordReset($user);
}
}

if ($weakPasswordCount > 0) {
$this->info("Berhasil menandai {$weakPasswordCount} user untuk reset password wajib.");
$this->info('User tersebut akan diminta reset password saat login berikutnya.');
} else {
$this->info('Tidak ada user dengan password lemah yang terdeteksi.');
}

return 0;
}

/**
* Check if a password hash is weak.
*
* Note: Since we can't know the original password from the hash,
* we check for common patterns by testing common passwords.
*/
protected function isPasswordWeak(string $passwordHash): bool
{
// Check if password matches any common password
foreach ($this->commonPasswords as $common) {
if (Hash::check($common, $passwordHash)) {
return true;
}
}

// Check for short passwords (less than 8 characters)
// We can't directly check length from hash, but we can check
// if any short common password matches
for ($i = 1; $i <= 7; $i++) {
// Generate test patterns
$patterns = [
str_repeat('a', $i),
str_repeat('1', $i),
implode('', range('a', chr(ord('a') + $i - 1))),
implode('', range('1', (string) $i)),
];

foreach ($patterns as $pattern) {
if (Hash::check($pattern, $passwordHash)) {
return true;
}
}
}

// Check if password doesn't meet complexity requirements
// by testing common variations
$weakVariations = [
'Password1!',
'Password123!',
'Welcome1!',
'Welcome123!',
'Admin123!',
'admin123!',
'password123!',
'Qwerty123!',
'qwerty123!',
];

foreach ($weakVariations as $variation) {
if (Hash::check($variation, $passwordHash)) {
return true;
}
}

// Additional heuristic: check for users who never changed password
// and have old-style hashes (not using bcrypt)
// Old MD5/SHA1 hashes are 32/40 chars, bcrypt is 60 chars
if (strlen($passwordHash) < 60) {
return true;
}

return false;
}

/**
* Get the reason why password is weak.
*/
protected function getWeakReason(string $passwordHash): string
{
// Check common passwords
foreach ($this->commonPasswords as $common) {
if (Hash::check($common, $passwordHash)) {
return 'Password umum/terkenal';
}
}

// Check hash length (old hash algorithm)
if (strlen($passwordHash) < 60) {
return 'Menggunakan algoritma hash lama';
}

// Check weak variations
$weakVariations = [
'Password1!',
'Password123!',
'Welcome1!',
'Welcome123!',
'Admin123!',
'admin123!',
'password123!',
'Qwerty123!',
'qwerty123!',
];

foreach ($weakVariations as $variation) {
if (Hash::check($variation, $passwordHash)) {
return 'Password mudah ditebak';
}
}

return 'Tidak memenuhi standar password kuat';
}

/**
* Flag a user for password reset.
*/
protected function flagUserForPasswordReset(User $user): void
{
// Only flag if not already flagged
if (!$user->force_password_reset) {
$user->force_password_reset = true;
$user->save();

// Record in password history
PasswordHistory::create([
'user_id' => $user->id,
'password' => $user->password,
'reason' => 'security_audit',
]);

$this->info(" → User {$user->email} ditandai untuk reset password");
}
}
}
4 changes: 2 additions & 2 deletions app/Helpers/general.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
*/
function openkab_versi()
{
return 'v2603.0.0';
return 'v2604.0.0';
}
}

Expand Down Expand Up @@ -769,7 +769,7 @@ function convertMenu($menu, $parentId = null, &$idCounter = 1)
'parent_id' => $parentId,
'text' => $menu['text'] ?? 'text',
'href' => $menu['url'] ?? null,
'icon' => $menu['icon'],
'icon' => $menu['icon'] ?? null,
'permission' => $menu['permission'] ?? null,
];

Expand Down
Loading
Loading