@php $_pdfLogo = null; foreach (['png','svg','jpg','jpeg'] as $_ext) { $_path = public_path('logo.'.$_ext); if (file_exists($_path)) { $_mime = $_ext === 'svg' ? 'image/svg+xml' : 'image/'.$_ext; $_pdfLogo = 'data:'.$_mime.';base64,'.base64_encode(file_get_contents($_path)); break; } } @endphp @php $bySev = $summary['by_severity'] ?? []; $total = $summary['total'] ?? 0; $openPorts = $summary['open_ports'] ?? 0; $hostsUp = $summary['hosts_up'] ?? 0; $pagesScanned= $summary['pages_scanned'] ?? null; $byOwasp = $summary['by_owasp'] ?? []; $critical = $bySev['critical'] ?? 0; $high = $bySev['high'] ?? 0; $medium = $bySev['medium'] ?? 0; $low = $bySev['low'] ?? 0; $info = $bySev['info'] ?? 0; $scannerType = $penTest->scanner_type ?? 'nmap'; $modeInfo = $scanModes[$penTest->scan_mode] ?? ['label'=>$penTest->scan_mode,'desc'=>'']; $scannerInfo = $scannerTypes[$scannerType] ?? ['label'=>strtoupper($scannerType),'color'=>'danger']; $scannerMeta = [ 'nmap' => ['label'=>'Nmap', 'ver'=>trim(shell_exec('nmap --version 2>/dev/null | head -1') ?: 'Latest'), 'toolColor'=>'#ef4444'], 'nikto' => ['label'=>'Nikto', 'ver'=>'2.1.5 (Docker)', 'toolColor'=>'#f59e0b'], ][$scannerType] ?? ['label'=>strtoupper($scannerType),'ver'=>'','toolColor'=>'#94a3b8']; $sec = $penTest->durationSeconds(); $duration = $sec ? ($sec>=60 ? floor($sec/60).'m '.($sec%60).'s' : $sec.'s') : '—'; if ($critical > 0) { $riskLevel='CRITICAL'; $riskClass='critical'; $riskDesc="本次滲透測試發現 {$critical} 個嚴重風險,目標系統面臨極高度被入侵風險,建議立即停止對外服務並進行全面修補。"; } elseif ($high > 0) { $riskLevel='HIGH'; $riskClass='high'; $riskDesc="本次測試發現 {$high} 個高風險問題,攻擊者可能利用這些弱點對目標造成資料洩漏或服務中斷。建議 7 天內完成修補。"; } elseif ($medium > 0) { $riskLevel='MEDIUM'; $riskClass='medium'; $riskDesc="本次測試發現 {$medium} 個中等風險,建議評估後於 30 天內修補,避免與其他弱點組合利用。"; } elseif ($low > 0) { $riskLevel='LOW'; $riskClass='low'; $riskDesc="本次測試整體風險偏低,僅發現 {$low} 個低風險設定問題,建議於例行維護時一併修復。"; } else { $riskLevel='SAFE'; $riskClass='info'; $riskDesc="本次滲透測試未發現明顯安全風險,目標系統暴露面控制良好,建議持續定期執行測試。"; } $owaspDetail = [ 'A01:2021' => ['name'=>'存取控制失效', 'desc'=>'使用者被允許執行超出其預期權限的操作,可能導致未授權的資料讀取、修改或刪除。'], 'A02:2021' => ['name'=>'加密機制失效', 'desc'=>'與加密相關的失敗,通常導致敏感資料暴露,包括明文傳輸、弱加密演算法、不安全的金鑰管理。'], 'A03:2021' => ['name'=>'注入式攻擊', 'desc'=>'攻擊者向直譯器發送惡意資料,如 SQL、OS 命令、XSS。可能導致資料竊取或系統入侵。'], 'A04:2021' => ['name'=>'不安全設計', 'desc'=>'設計階段缺乏安全考量,包括缺乏威脅建模、不安全的設計模式。'], 'A05:2021' => ['name'=>'安全設定錯誤', 'desc'=>'不安全的預設設定、不完整設定、錯誤的 HTTP 標頭、詳細的錯誤訊息等。'], 'A06:2021' => ['name'=>'易受攻擊與過時的元件', 'desc'=>'使用有已知漏洞的函式庫、框架或軟體模組,可能破壞應用程式防禦。'], 'A07:2021' => ['name'=>'身分驗證失效', 'desc'=>'與身分驗證和工作階段管理相關的弱點,允許攻擊者入侵密碼、金鑰或工作階段令牌。'], 'A08:2021' => ['name'=>'軟體及資料完整性失效', 'desc'=>'未驗證完整性的軟體更新、關鍵資料及 CI/CD 管道,如不安全的反序列化。'], 'A09:2021' => ['name'=>'安全記錄及監控失效', 'desc'=>'缺乏足夠的記錄和監控,導致無法偵測攻擊,使攻擊者能長期潛伏系統中。'], 'A10:2021' => ['name'=>'伺服器端請求偽造', 'desc'=>'應用程式在未驗證使用者提供 URL 的情況下發送請求,攻擊者可存取內部服務。'], ]; $owaspLabels = \App\Models\VulnScan::owaspLabels(); $sevColors = ['critical'=>'#dc2626','high'=>'#ea580c','medium'=>'#d97706','low'=>'#16a34a','info'=>'#475569']; $sevDescs = [ 'critical'=>'可直接被遠端利用,無需授權即可取得系統控制權。建議立即(24H內)修復。', 'high' =>'可能造成資料洩漏、身分驗證繞過等重大損害。建議 7 天內修復。', 'medium' =>'單獨利用危害有限,但可與其他漏洞組合使用。建議 30 天內修復。', 'low' =>'危害程度較低,通常為設定不當或資訊暴露。建議例行維護時修復。', 'info' =>'非直接威脅,主要為技術指紋識別,可輔助了解系統暴露面。', ]; @endphp {{-- ══════════════ 封面 ══════════════ --}}
@if($_pdfLogo) {{ config('app.company_name') }} @else @endif
@if(!$_pdfLogo)
{{ config('app.company_name') }}
@endif
資安檢測服務
CONFIDENTIAL
@if($scannerType === 'nikto') @else @endif
{{ $scannerMeta['label'] }}
{{ $scannerMeta['ver'] }}
{{ $scannerType === 'nikto' ? 'Web Server Security Assessment' : 'Network Penetration Testing' }}
滲透測試報告
Penetration Testing Report

Prepared for  ·  委託單位
{{ $penTest->project?->client?->name ?? $penTest->project?->name ?? '(未指定委託單位)' }}

Scan Target  ·  掃描目標
{{ $penTest->target }}
Scanner  ·  掃描工具
{{ $scannerMeta['label'] }}
{{ $modeInfo['label'] }}({{ $modeInfo['desc'] }})
Scan Date  ·  掃描日期
{{ $penTest->started_at?->format('Y-m-d') ?? '—' }}
Scan Time  ·  掃描時間
{{ $penTest->started_at?->format('H:i') ?? '—' }}@if($penTest->finished_at) – {{ $penTest->finished_at->format('H:i') }}@endif
@if($duration !== '—')
歷時 {{ $duration }}
@endif

Report Date  ·  報告產生日期
{{ now()->format('Y 年 m 月 d 日') }}
@if($hostsUp > 0)
存活主機:{{ $hostsUp }} 台  ·  開放埠:{{ $openPorts }} 個
@endif @if($pagesScanned !== null)
掃描頁面:{{ number_format($pagesScanned) }} 個
@endif
Overall Risk Level  ·  整體風險等級
{{ $riskLevel }}
共 {{ $total }} 筆   C {{ $critical }} H {{ $high }} M {{ $medium }} L {{ $low }} I {{ $info }}
{{-- ══════════════ 正文頁 ══════════════ --}}
{{-- 一、執行摘要 --}}
一、執行摘要
整體風險等級:{{ $riskLevel }}
{{ $riskDesc }}

本次使用 {{ $scannerMeta['label'] }} {{ $scannerMeta['ver'] }} 進行{{ $scannerType==='nikto'?'Web 伺服器安全檢測':'網路滲透測試' }}, 採用 {{ $modeInfo['label'] }} 模式,針對目標 {{ $penTest->target }} 進行自動化安全評估。 掃描作業於 {{ $penTest->started_at?->format('Y年m月d日 H:i') }} 開始,歷時 {{ $duration }} 完成。 @if($hostsUp > 0) 共掃描到 {{ $hostsUp }} 台存活主機,發現 {{ $openPorts }} 個開放埠。@endif @if($pagesScanned !== null) 共掃描 {{ number_format($pagesScanned) }} 個頁面。@endif

@if($openPorts > 0) @endif
{{ $critical }}
CRITICAL
嚴重
{{ $high }}
HIGH
高風險
{{ $medium }}
MEDIUM
中風險
{{ $low }}
LOW
低風險
{{ $info }}
INFO
資訊
{{ $openPorts }}
OPEN PORTS
開放埠
{{-- 二、風險等級說明 --}}
二、風險等級說明
Critical嚴重漏洞:可直接被遠端利用,無需授權即可取得系統控制權或存取敏感資料。常見如遠端程式碼執行(RCE)、遠端管理服務暴露等。建議立即修復(24 小時內)。
High高風險漏洞:可能造成重大損害,如高風險服務暴露(RDP/FTP/Telnet)、資料洩漏、身分驗證繞過等。建議 7 天內修復
Medium中等風險:單獨利用危害有限,但可能與其他弱點組合使用。常見如不安全服務設定、HTTP 標頭缺失等。建議 30 天內修復
Low低風險:危害程度較低,通常為標準服務(SSH/HTTP/HTTPS)開放或一般設定觀察。建議於例行維護時修復
Info資訊性:非直接安全威脅,主要為服務探測、技術指紋識別,可輔助了解系統暴露面。
{{-- 三、主要發現摘要 --}} @php $nonInfo = array_filter($findings, fn($f) => ($f['severity'] ?? 'info') !== 'info'); $topFindings = array_slice(array_values($nonInfo) ?: $findings, 0, 10); @endphp
三、主要發現摘要(Top {{ count($topFindings) }})
@if(empty($topFindings))

本次掃描未發現高風險問題。

@else @foreach($topFindings as $f) @php $sev = $f['severity'] ?? 'info'; @endphp
{{ strtoupper($sev) }}  {{ $f['name'] ?: ($f['template_id'] ?? '—') }} @if(!empty($f['matched_at']))  → {{ $f['matched_at'] }}@endif @if(!empty($f['description']))
{{ mb_strimwidth($f['description'], 0, 150, '…') }}
@endif
@endforeach @endif
{{-- 四、OWASP Top 10 分佈(Nikto/有 OWASP 對應時顯示)--}} @if(!empty($byOwasp))
四、OWASP Top 10 風險分佈

OWASP Top 10 是國際公認的十大 Web 應用程式安全風險清單,以下為本次掃描結果與 OWASP 分類的對應關係。

@foreach($owaspLabels as $oid => $olabel) @php $cnt = $byOwasp[$oid] ?? 0; @endphp @endforeach
分類 ID風險名稱發現數狀態
{{ $oid }} {{ $olabel }} {{ $cnt > 0 ? $cnt : '—' }} @if($cnt > 0)⚠ 發現 @else✓ 未發現@endif
@endif {{-- 五、修補建議優先順序 --}} @php $fixFindings = array_filter($findings, fn($f) => in_array($f['severity'] ?? '', ['critical','high','medium','low']) && !empty($f['remediation']) ); @endphp @if(!empty($fixFindings))
{{ !empty($byOwasp) ? '五' : '四' }}、修補建議優先順序
@php $rank = 1; @endphp @foreach($findings as $f) @php if (!in_array($f['severity'] ?? '', ['critical','high','medium','low'])) continue; if (empty($f['remediation'])) continue; @endphp @endforeach
優先嚴重度問題名稱建議修復措施
{{ $rank++ }} {{ strtoupper($f['severity']) }} {{ $f['name'] ?: ($f['template_id'] ?? '—') }} {{ mb_strimwidth($f['remediation'], 0, 150, '…') }}
@endif {{-- 六、詳細發現清單 --}} @php $secNum = (!empty($byOwasp) ? 6 : 5); $secLabel = ['','一','二','三','四','五','六','七'][$secNum] ?? $secNum; @endphp
{{ $secLabel }}、詳細發現清單(共 {{ $total }} 筆)
@forelse($findings as $i => $f) @php $sev = $f['severity'] ?? 'info'; $sevColor = $sevColors[$sev] ?? '#475569'; $fOwasp = (array)($f['owasp'] ?? []); $fCve = (array)($f['cve_id'] ?? []); $fRef = (array)($f['reference'] ?? []); $descText = $f['description'] ?? $f['name'] ?? ''; $remedText = $f['remediation'] ?? ''; // 補充參考連結 if (empty($fRef)) { foreach ($fOwasp as $oid) $fRef[] = 'https://owasp.org/Top10/'; if (!empty($f['nikto_id'])) $fRef[] = 'https://cirt.net/nikto2-docs/options.html'; } @endphp
{{ strtoupper($sev) }}
#{{ str_pad($i+1,3,'0',STR_PAD_LEFT) }}
{{ $f['name'] ?: ($f['template_id'] ?? '—') }}
{{ $f['template_id'] ?? '' }} @foreach($fCve as $cid){{ $cid }}@endforeach @foreach($fOwasp as $oid){{ $oid }}@endforeach
{{ $scannerType === 'nmap' ? '🔌 目標主機 / 埠' : '🌐 影響網址位置' }}
{{ $f['matched_at'] ?: '—' }} @if($scannerType === 'nmap' && !empty($f['port']))  埠 {{ $f['port'] }}/{{ $f['protocol'] ?? 'tcp' }} {{ $f['service'] ?? '' }}{{ $f['version'] ? ' ('.$f['version'].')' : '' }} @endif
{{-- 欄A:風險分類 --}}
⚠ 對應風險分類
{{ strtoupper($sev) }}
{{ $sevDescs[$sev] ?? '' }}
@if(!empty($fOwasp))
OWASP Top 10 2021
@foreach($fOwasp as $oid) @php $od = $owaspDetail[$oid] ?? null; @endphp
{{ $oid }} {{ $od['name'] ?? '' }}
@if($od)
{{ $od['desc'] }}
@endif
@endforeach
@endif @if(!empty($fCve))
@foreach($fCve as $cid){{ $cid }}@endforeach
@endif
{{-- 欄B:說明 + 建議解法 --}}
ℹ 問題說明
@if($descText)
{{ $descText }}
@else
(請參考右側參考資料)
@endif
🔧 建議解法
@if($remedText)
{{ $remedText }}
@else
確認服務是否需要對外開放,若非必要請透過防火牆規則限制存取來源。
@endif
{{-- 欄C:參考資料 + 技術資訊 --}}
🔗 參考資料
@foreach(array_slice($fRef, 0, 4) as $ref)
{{ $ref }}
@endforeach @if(empty($fRef))
@endif
📄 技術資訊
@if(!empty($f['template_id']))
ID:{{ $f['template_id'] }}
@endif @if(!empty($f['port']))
埠/協定:{{ $f['port'] }}/{{ $f['protocol'] ?? 'tcp' }}
@endif @if(!empty($f['service']))
服務:{{ $f['service'] }}
@endif @if(!empty($f['version']))
版本:{{ mb_strimwidth($f['version'],0,50,'…') }}
@endif @if(!empty($f['nikto_id']))
OSVDB:{{ $f['nikto_id'] }}
@endif
@if(!empty($f['tags']))
@foreach(array_slice((array)$f['tags'],0,6) as $tag){{ $tag }}@endforeach
@endif
@empty

未發現任何問題,系統安全狀態良好。

@endforelse