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:
git clone https://bitbucket.org/.../vtrc-rc-backoffice.git
cat vtrc-rc-backoffice/.env
# → เห็น MSSQL username/password + AES keyImpact:
- MSSQL direct access — attacker เชื่อมต่อ database ได้โดยตรง (bypass vtrc-api)
- AES key exposed — ถ้า client encrypt ข้อมูล sensitive ใน localStorage, attacker ที่ hijack localStorage สามารถ decrypt ได้
Remediation:
- เพิ่ม
.envเข้า.gitignore(ด่วนที่สุด) - Rotate ทุก secret ที่อยู่ใน
.env(MSSQL password, AES key) - ลบ
.envออกจาก git history ด้วยgit filter-repo - ใช้ 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
Evidence — App/index.js:24:
<Route path="/pathLogin/:token/:refreshToken" exact component={PathLogin}/>Exploit: token ทั้งคู่ปรากฏใน browser history, server access log, referer header
Reproduction:
- Attacker share URL
https://vtrcbackoffice.redcross.or.th/pathLogin/{stolen-token}/{stolen-refresh}กับเหยื่อ - เหยื่อคลิก → token ถูกเก็บลง localStorage ของเหยื่อ
- ถ้า attacker มี token คนอื่นอยู่แล้ว — ส่งให้เหยื่อเปิดเพื่อ plant token ของ attacker ใน browser ของเหยื่อ (session fixation)
Impact: session fixation, token theft via shared link, audit log confusion
Remediation:
- เปลี่ยนเป็น POST body SSO
- หรือใช้ one-time exchange token (TTL 30s)
- หรืออย่างน้อย — fragment
#token=แทน path
SEC-VTRC-RC-03 · Login password ไม่มี encryption ฝั่ง client
ที่: vtrc-rc-backoffice/src/pages/Login/index.js:55-66
Evidence — Login/index.js:55-66:
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:
<div dangerouslySetInnerHTML={{ __html: news.content }} />Exploit: เหมือน vtrc-web — admin ที่สร้าง news สามารถ inject <script> tag
Impact: XSS → token theft → admin impersonation
Remediation:
dompurifyสำหรับ sanitize HTML- CSP
script-src 'self' - Markdown renderer แทน HTML raw
SEC-VTRC-RC-05 · Token ใน localStorage — XSS accessible
ที่: vtrc-rc-backoffice/src/utils/auth.js
Evidence — pattern เดียวกับ vtrc-web:
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
Evidence — App/index.js:17:
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:
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)
- ลบ
.envออกจาก git + rotate secret — fix SEC-VTRC-RC-01, investment เล็ก, impact ใหญ่ที่สุด - POST body SSO แทน
/pathLogin/:token— fix SEC-VTRC-RC-02, investment ปานกลาง dompurifyสำหรับdangerouslySetInnerHTML— fix SEC-VTRC-RC-04, investment เล็ก- CSP header — fix SEC-VTRC-RC-06, investment นิดเดียว
- HttpOnly cookie สำหรับ token — fix SEC-VTRC-RC-05, investment ใหญ่ (เปลี่ยนทั้ง frontend + backend)
- ErrorBoundary — fix SEC-VTRC-RC-10, investment เล็ก
สรุป
vtrc-rc-backoffice มี security issues ที่รุนแรงกว่า vtrc-web เพราะ:
.envcommitted — leak secret ทั้งหมด รวมถึง MSSQL password ที่ใช้ตรง ๆ- SSO bypass route — token ใน URL เปิดช่อง session fixation
- เป็น admin backoffice — impact ของ token theft สูงกว่า (admin มีสิทธิ์มากกว่า)
Priority สูงสุด: ลบ .env ออกจาก git และ rotate secret — ทำได้ภายใน 1 ชั่วโมง แต่ลด risk ได้มากที่สุด