Skip to content

4.2.5 · Security analysis

บทนี้เจาะลึก finding ด้าน security ของ vtrc-rc-backoffice — ทั้ง code-level และ architecture


Security scorecard

Dimensionสถานะเหตุผล
Token storage🔴localStorage (XSS accessible)
SSO bypass route🔴/pathLogin/:token/:refreshToken — token in URL
XSS protection🔴หลายสิบไฟล์ dangerouslySetInnerHTML
Committed secrets🔴.env มี MSSQL conn string + AES key
CSP🔴ไม่มี Content-Security-Policy header
Bundle integrity🔴ไม่มี SRI hash
Auth gate🟡route-level conditional render
ErrorBoundary🔴ไม่มี
HTTPS enforcement🟢nginx + cert-manager
Login password🔴Plaintext (no RSA — V1 ผิด)

Severity: Critical (🔴)

SEC-VTRC-RC-01 · .env committed — MSSQL conn string + AES key

ที่: /Users/tnd/Documents/I3/vtrc/vtrc-rc-backoffice/.env

Evidence.env (committed to repo):

REACT_APP_STIMUL_CONN_STRING=Server=xxx.database.windows.net;Database=xxx;User Id=xxx;Password=xxx;
REACT_APP_PRIVATE_KEY=<AES-256 key ที่ใช้ encrypt localStorage data>
REACT_APP_PMS_API_END_POINT=https://...
REACT_APP_AI_RECRUITMENT_API=https://...

Exploit: ใครก็ clone repo จาก Bitbucket แล้วเห็น secret ทั้งหมด

Reproduction:

bash
git clone https://bitbucket.org/.../vtrc-rc-backoffice.git
cat vtrc-rc-backoffice/.env
# → เห็น MSSQL username/password + AES key

Impact:

  • MSSQL direct access — attacker เชื่อมต่อ database ได้โดยตรง (bypass vtrc-api)
  • AES key exposed — ถ้า client encrypt ข้อมูล sensitive ใน localStorage, attacker ที่ hijack localStorage สามารถ decrypt ได้

Remediation:

  1. เพิ่ม .env เข้า .gitignore (ด่วนที่สุด)
  2. Rotate ทุก secret ที่อยู่ใน .env (MSSQL password, AES key)
  3. ลบ .env ออกจาก git history ด้วย git filter-repo
  4. ใช้ secret manager (Vault, AWS Secrets Manager) หรือ CI/CD inject env ตอน build

SEC-VTRC-RC-02 · /pathLogin/:token/:refreshToken SSO bypass — token in URL

ที่: vtrc-rc-backoffice/src/containers/App/index.js:24

EvidenceApp/index.js:24:

javascript
<Route path="/pathLogin/:token/:refreshToken" exact component={PathLogin}/>

Exploit: token ทั้งคู่ปรากฏใน browser history, server access log, referer header

Reproduction:

  1. Attacker share URL https://vtrcbackoffice.redcross.or.th/pathLogin/{stolen-token}/{stolen-refresh} กับเหยื่อ
  2. เหยื่อคลิก → token ถูกเก็บลง localStorage ของเหยื่อ
  3. ถ้า attacker มี token คนอื่นอยู่แล้ว — ส่งให้เหยื่อเปิดเพื่อ plant token ของ attacker ใน browser ของเหยื่อ (session fixation)

Impact: session fixation, token theft via shared link, audit log confusion

Remediation:

  1. เปลี่ยนเป็น POST body SSO
  2. หรือใช้ one-time exchange token (TTL 30s)
  3. หรืออย่างน้อย — fragment #token= แทน path

SEC-VTRC-RC-03 · Login password ไม่มี encryption ฝั่ง client

ที่: vtrc-rc-backoffice/src/pages/Login/index.js:55-66

EvidenceLogin/index.js:55-66:

javascript
const { data, errors } = await client.mutate({
    mutation: Mutations.loginBackoffice,
    variables: {
        empCode: username,
        password: password,  // ← plaintext
        appVersion: "v1.0",
        apiKey: API_DEVICE_KEY,
        organization: getOrganization(),
    }
})

Impact: ถ้า HTTPS termination อยู่ที่ reverse proxy (เช่น CloudFlare) — password อาจปรากฏใน intermediate log

Remediation: ใช้ HTTPS end-to-end และ/หรือเพิ่ม client-side hashing (Argon2) ก่อนส่ง

หมายเหตุ: V1 (docs-v1-archive) ระบุผิดว่ามี RSA encryption — จริง ๆ ไม่มี RSA library ใด ๆ ใน repo นี้ (no JSEncrypt, no node-forge, no jsencrypt package)


SEC-VTRC-RC-04 · dangerouslySetInnerHTML — XSS risk

ที่: กระจายทั่ว src/pages/ — News, Policy, Notification detail pages

Evidence — pattern:

javascript
<div dangerouslySetInnerHTML={{ __html: news.content }} />

Exploit: เหมือน vtrc-web — admin ที่สร้าง news สามารถ inject <script> tag

Impact: XSS → token theft → admin impersonation

Remediation:

  1. dompurify สำหรับ sanitize HTML
  2. CSP script-src 'self'
  3. Markdown renderer แทน HTML raw

SEC-VTRC-RC-05 · Token ใน localStorage — XSS accessible

ที่: vtrc-rc-backoffice/src/utils/auth.js

Evidence — pattern เดียวกับ vtrc-web:

javascript
export const setToken = (token) => {
  localStorage.setItem('token', token.accessToken)
  localStorage.setItem('refreshToken', token.refreshToken)
}

Impact: XSS → token theft → admin impersonation

Remediation: HttpOnly cookie + SameSite=Strict + Secure


Severity: High (🟡)

SEC-VTRC-RC-06 · ไม่มี CSP + SRI

ที่: nginx config + public/index.html

เหมือน vtrc-web — ไม่มี Content-Security-Policy และไม่มี Subresource Integrity hash บน bundle


SEC-VTRC-RC-07 · console.log ปิดทั้งหมด — debug ยาก

ที่: vtrc-rc-backoffice/src/containers/App/index.js:17

EvidenceApp/index.js:17:

javascript
console.log = console.warn = console.error = () => { };

Impact: ไม่ใช่ security issue โดยตรง แต่ทำให้ debug production issue ยากมาก (ต้องใช้ debugger หรือ React DevTools)

Remediation: gate ด้วย process.env.NODE_ENV === 'production' แทนการปิด hard


SEC-VTRC-RC-08 · showModalErrors อาจกลืน error

ที่: src/pages/Login/index.js:75-78

Evidence:

javascript
if (errors && errors[0].extensions.code === 'INTERNAL_SERVER_ERROR') {
    await this.setState({
        showModalErrors: true
    })
}

Impact: ถ้า INTERNAL_SERVER_ERROR เกิดจาก backend bug ที่ส่งผลกับ security (เช่น timing attack ระหว่าง login) — user เห็นแค่ modal ทั่วไป ไม่รู้ว่าเกิดอะไรขึ้น

Remediation: log error แบบ structured ก่อน show modal


Severity: Medium (🟢)

SEC-VTRC-RC-09 · No CSRF protection

เหมือน vtrc-web — ใช้ Authorization: Bearer header ไม่ใช่ cookie

SEC-VTRC-RC-10 · No ErrorBoundary

เหมือน vtrc-web — crash = white screen

SEC-VTRC-RC-11 · checkLinkURL() env branching ที่ client

เหมือน vtrc-web — endpoint URL ปรากฏใน bundle

SEC-VTRC-RC-12 · appVersion: "v1.0" hardcoded

ที่: Login/index.js:61

Impact: backend ไม่รู้ว่า client ใช้เวอร์ชั่นไหน ทำให้ส่ง migration warning หรือ force update ไม่ได้


Modernization priority (ROI-weighted)

  1. ลบ .env ออกจาก git + rotate secret — fix SEC-VTRC-RC-01, investment เล็ก, impact ใหญ่ที่สุด
  2. POST body SSO แทน /pathLogin/:token — fix SEC-VTRC-RC-02, investment ปานกลาง
  3. dompurify สำหรับ dangerouslySetInnerHTML — fix SEC-VTRC-RC-04, investment เล็ก
  4. CSP header — fix SEC-VTRC-RC-06, investment นิดเดียว
  5. HttpOnly cookie สำหรับ token — fix SEC-VTRC-RC-05, investment ใหญ่ (เปลี่ยนทั้ง frontend + backend)
  6. ErrorBoundary — fix SEC-VTRC-RC-10, investment เล็ก

สรุป

vtrc-rc-backoffice มี security issues ที่รุนแรงกว่า vtrc-web เพราะ:

  1. .env committed — leak secret ทั้งหมด รวมถึง MSSQL password ที่ใช้ตรง ๆ
  2. SSO bypass route — token ใน URL เปิดช่อง session fixation
  3. เป็น admin backoffice — impact ของ token theft สูงกว่า (admin มีสิทธิ์มากกว่า)

Priority สูงสุด: ลบ .env ออกจาก git และ rotate secret — ทำได้ภายใน 1 ชั่วโมง แต่ลด risk ได้มากที่สุด


ขั้นตอนถัดไป

ไป บท 4.2.6 Performance + Build pipeline