Files
Deep-Package-Inspection/scripts/fix-css-and-security.js
T

142 lines
6.1 KiB
JavaScript

// scripts/fix-css-and-security.js
// 1. Fix CSS tidak termuat: buat symlink public_html/_next -> public_html/.next
// 2. Security audit: hapus cmd.php dan file berbahaya lainnya
'use strict';
const { Client } = require('ssh2');
const https = require('https');
const SSH = {
host: '103.185.47.52', port: 2222,
username: 'adminbackend', password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const PUB = '/home/adminbackend/web/demoplace.my.id/public_html';
function sshExec(conn, cmd, label = '') {
if (label) console.log(`\n[${label}]`);
console.log(`$ ${cmd.substring(0, 100)}${cmd.length > 100 ? '...' : ''}`);
return new Promise((resolve, reject) => {
conn.exec(cmd, (err, stream) => {
if (err) return reject(err);
let out = '';
stream.on('close', () => resolve(out))
.on('data', d => { out += d; process.stdout.write(d.toString()); })
.stderr.on('data', d => { out += d; process.stdout.write(d.toString()); });
});
});
}
async function main() {
console.log('\n╔══════════════════════════════════════════════════════════╗');
console.log('║ BackOne DPI — Fix CSS + Security Audit ║');
console.log('╚══════════════════════════════════════════════════════════╝\n');
const conn = new Client();
await new Promise((resolve, reject) => { conn.on('ready', resolve).on('error', reject).connect(SSH); });
console.log('[SSH] Terhubung!\n');
// ── 1. SECURITY AUDIT ─────────────────────────────────────────────────
await sshExec(conn,
`echo "=== FILE BERBAHAYA ===" && ls -la ${PUB}/*.php ${PUB}/*.sh 2>/dev/null || echo "Tidak ada .php/.sh di root"`,
'1. Audit file PHP di public_html'
);
// Hapus cmd.php jika ada (file backdoor berbahaya)
await sshExec(conn,
`[ -f ${PUB}/cmd.php ] && rm -f ${PUB}/cmd.php && echo "DIHAPUS: cmd.php" || echo "cmd.php tidak ada (aman)"`,
'2. Hapus cmd.php (backdoor)'
);
// Hapus proxy.php lama (tidak diperlukan lagi karena nginx routing langsung ke port 3000)
await sshExec(conn,
`[ -f ${PUB}/proxy.php ] && rm -f ${PUB}/proxy.php && echo "DIHAPUS: proxy.php (tidak diperlukan)" || echo "proxy.php tidak ada"`,
'3. Hapus proxy.php (tidak dibutuhkan)'
);
// ── 2. CEK STRUKTUR DIREKTORI ──────────────────────────────────────────
await sshExec(conn,
`echo "=== STRUKTUR public_html ===" && ls -la ${PUB}/ | head -30`,
'4. Cek struktur public_html'
);
await sshExec(conn,
`echo "=== .next directory ===" && ls -la ${PUB}/.next/ 2>/dev/null | head -10 || echo "TIDAK ADA .next/"`,
'5. Cek .next directory'
);
await sshExec(conn,
`echo "=== static assets ===" && ls -la ${PUB}/.next/static/ 2>/dev/null | head -10 || echo "Tidak ada .next/static/"`,
'6. Cek .next/static'
);
await sshExec(conn,
`echo "=== _next symlink ===" && ls -la ${PUB}/_next 2>/dev/null || echo "Symlink _next belum ada"`,
'7. Cek symlink _next'
);
// ── 3. FIX CSS: Buat symlink _next → .next ────────────────────────────
await sshExec(conn,
`[ -e ${PUB}/_next ] && echo "Sudah ada _next" || (ln -s ${PUB}/.next ${PUB}/_next && echo "BERHASIL: Symlink _next → .next dibuat")`,
'8. Buat symlink _next -> .next'
);
// Verifikasi symlink
await sshExec(conn,
`ls -la ${PUB}/_next && ls ${PUB}/_next/static/ | head -5`,
'9. Verifikasi symlink'
);
// ── 4. PERBARUI .htaccess (bersih tanpa proxy.php) ────────────────────
const cleanHtaccess = `# BackOne DPI — Apache .htaccess
# Redirect HTTP ke HTTPS saja
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
`;
await sshExec(conn,
`printf '%s' ${JSON.stringify(cleanHtaccess)} > ${PUB}/.htaccess && echo "BERHASIL: .htaccess diperbarui"`,
'10. Perbarui .htaccess (hanya redirect HTTPS)'
);
// ── 5. TEST CSS LOADING ─────────────────────────────────────────────────
console.log('\n[11. Test loading CSS dari /_next/static/]');
await sshExec(conn,
`CSS_FILE=$(ls ${PUB}/.next/static/css/*.css 2>/dev/null | head -1) && ` +
`[ -n "$CSS_FILE" ] && ` +
`FILENAME=$(basename "$CSS_FILE") && ` +
`curl -sk -o /dev/null -w "CSS via domain: %{http_code} (size: %{size_download} bytes)" https://demoplace.my.id/_next/static/css/$FILENAME || ` +
`echo "Tidak ada file CSS ditemukan"`,
'11. Test CSS via domain'
);
conn.end();
// ── Test dari luar ──────────────────────────────────────────────────────
console.log('\n[12. Test domain setelah fix...]');
await new Promise(r => setTimeout(r, 2000));
for (const path of ['/login', '/api/health']) {
const r = await new Promise(resolve => {
const req = https.get(`https://demoplace.my.id${path}`,
{ timeout: 10000, rejectUnauthorized: false },
res => {
let body = '';
res.on('data', d => body += d);
res.on('end', () => resolve({ status: res.statusCode, body: body.substring(0, 100) }));
}
);
req.on('error', e => resolve({ status: 0, error: e.message }));
});
const icon = r.status === 200 ? '✅' : r.status === 301 ? '↩️ ' : '❌';
console.log(` ${icon} https://demoplace.my.id${path} → HTTP ${r.status}`);
if (path === '/api/health') console.log(` Body: ${r.body}`);
}
console.log('\n✅ Fix selesai! Coba refresh https://demoplace.my.id/login\n');
}
main().catch(err => { console.error('[FATAL]', err.message); process.exit(1); });