Web անվտանգություն և OWASP Top 10
Ամենատարածված web խոցելիությունները՝ իրական օրինակներով, և պաշտպանության միջոցներ, որոնք իսկապես աշխատում են։
30 վայրկյանում
OWASP Top 10-ը web հավելվածների անվտանգության ամենակրիտիկական ռիսկերի լայնորեն օգտագործվող ցուցակ է. ընթացիկ հրատարակությունը 2025 թվականից է։ Իրական արտահոսքերի մեծ մասը գալիս է սխալների կարճ ցուցակից. բացակայող հասանելիության ստուգումներ, injection, սխալ կոնֆիգուրացիա, խոցելի կախվածություններ և արտահոսած գաղտնիքներ։ Լավ անվտանգությունը սովորությունների համակարգ է, որը ներդրված է նախագծման, code review-ի, կոնֆիգուրացիայի և deployment-ի մեջ, ոչ թե վերջնական audit։
Ինչու եմ օգտագործում
- Ես OWASP Top 10-ն օգտագործում եմ որպես checklist, որովհետև այն ընդգրկում է այն սխալները, որոնք իսկապես արտահոսքեր են առաջացնում բիզնես հավելվածներում։
- Իմ կառուցած պրոդուկտները գործ ունեն վճարումների, անձնական տվյալների և tenant-ների տվյալների հետ, որտեղ access control-ի մեկ բագը վերածվում է լուրջ միջադեպի։
- Անվտանգ լռելյայն կարգավորումները framework-երում, header-ներում և սերվերներում կանխում են բագերի ամբողջ դասեր գրեթե առանց ծախսի։
- Հաճախորդներն ու աուդիտորներն ավելի ու ավելի հաճախ են հարցնում, թե ինչպես է ապահովվում անվտանգությունը, և հստակ, կոնկրետ պատասխանը վստահություն է ստեղծում։
Ինչպես է աշխատում
01OWASP Top 10-ը պարզ բառերով
OWASP-ը (Open Worldwide Application Security Project) հրապարակում է Top 10-ը՝ հիմնվելով խոցելիությունների իրական տվյալների և համայնքային հարցումների վրա։ 2025-ի հրատարակությունը հետևյալն է. A01 Broken Access Control (օգտատերերը հասնում են տվյալների կամ գործողությունների, որոնց չպետք է հասնեին. SSRF-ն այժմ այս կատեգորիայի մաս է). A02 Security Misconfiguration. A03 Software Supply Chain Failures (խոցելի կամ վտանգված կախվածություններ, build գործիքներ և pipeline-ներ). A04 Cryptographic Failures. A05 Injection (SQL, command, ինչպես նաև XSS). A06 Insecure Design. A07 Authentication Failures. A08 Software or Data Integrity Failures. A09 Security Logging and Alerting Failures. A10 Mishandling of Exceptional Conditions (սխալներ, որոնք «բաց» են ձախողվում կամ մանրամասներ են արտահոսեցնում)։ Օգտագործեք այն իրազեկության և review-ի checklist-ի համար, ոչ թե որպես ամբողջական ստանդարտ. մանրամասն պահանջների համար OWASP-ի Application Security Verification Standard-ը (ASVS) և API Security Top 10-ը ավելի խորն են գնում։
02Broken access control, SSRF և CSRF
Broken access control-ը ամենատարածված լուրջ թերությունն է։ Դասական օրինակ. GET /api/orders/1043-ը վերադարձնում է ցանկացած պատվեր, որովհետև կոդը ստուգում է, որ օգտատերը մուտք է գործել, բայց ոչ այն, որ պատվերը իրենն է։ Սա կոչվում է IDOR (insecure direct object reference)։ Լուծումը սերվերում յուրաքանչյուր request-ի ժամանակ սեփականության կամ իրավունքի ստուգումն է, իդեալում՝ կենտրոնացված policy-ների միջոցով, լռելյայն մերժելով և վերադարձնելով 404 այն օբյեկտների համար, որոնք օգտատերը չի կարող տեսնել։ Server-side request forgery-ն (SSRF) տեղի է ունենում, երբ ձեր սերվերը բերում է օգտատիրոջ տրամադրած URL, օրինակ՝ պատկերի import-ի ժամանակ, և հարձակվողն այն ուղղում է ներքին հասցեների կամ cloud metadata endpoint-ների։ Allow-list արեք host-երն ու scheme-ները, resolve արեք և արգելափակեք private IP տիրույթները և անջատեք redirect-ները։ Cross-site request forgery-ն (CSRF) խաբում է մուտք գործած browser-ին, որպեսզի այն ուղարկի վիճակը փոխող request. պաշտպանվեք SameSite cookie-ներով, CSRF token-ներով և Origin header-ի ստուգմամբ։
- Յուրաքանչյուր օբյեկտի հասանելիություն թույլատրեք սերվերում, ոչ թե UI-ում։
- Լռելյայն մերժեք. թեստավորեք երկրորդ օգտատիրոջ հաշվով։
- URL-ներ բերելու համար. allow-list, private տիրույթների արգելափակում, առանց redirect-ների։
03Injection և XSS
Injection-ը տեղի է ունենում, երբ օգտատիրոջ input-ը մշակվում է որպես կոդ։ SQL injection-ի դեպքում որոնման դաշտը, որը պարունակում է ' OR 1=1 --, փոխում է string concatenation-ով կառուցված query-ի իմաստը՝ արտահոսեցնելով կամ ջնջելով տվյալներ։ Լուծումը պարամետրացված query-ներն են, որտեղ տվյալներն ուղարկվում են SQL-ից առանձին, ինչը աջակցում է յուրաքանչյուր ժամանակակից driver և ORM. զգույշ եղեք raw query helper-ների և դինամիկ սյունակների անունների հետ, որոնց allow-list է պետք։ Նույն սկզբունքը վերաբերում է shell հրամաններին, LDAP-ին և template engine-ներին։ Cross-site scripting-ը (XSS) injection է HTML-ի մեջ. հարձակվողը script է պահում կարծիքում կամ պրոֆիլի անվան մեջ, և այն աշխատում է այլ օգտատերերի browser-ներում՝ գողանալով session-ներ կամ գործողություններ կատարելով։ React-ի նման framework-երը լռելյայն escape են անում output-ը. վտանգավոր գոտիներն են dangerouslySetInnerHTML-ը, v-html-ը, Blade-ի unescaped output-ը և href ատրիբուտների URL-ները։ Հարուստ HTML-ը sanitize արեք ստուգված գրադարանով և որպես երկրորդ շերտ ավելացրեք Content Security Policy։
import { Pool } from "pg";
const db = new Pool();
// Vulnerable: input becomes part of the SQL text
// db.query("SELECT * FROM users WHERE email = '" + email + "'");
// Safe: input is sent as a parameter, never parsed as SQL
export async function findUser(email: string) {
const { rows } = await db.query(
"SELECT id, email FROM users WHERE email = $1",
[email],
);
return rows[0] ?? null;
}
04Սխալ կոնֆիգուրացիա և անվտանգ header-ներ
Շատ արտահոսքերի համար խելացի exploit պետք չէ. production-ում միացված թողնված debug mode, public storage bucket, լռելյայն admin գաղտնաբառեր, stack trace-երով մանրամասն սխալի էջեր, directory listing, բաց .env կամ .git պանակ, ինտերնետին բաց բազայի port։ Կանխեք դրանք configuration as code-ով, ըստ միջավայրի կարգավորումներով և deploy pipeline-ում ստուգումներով։ Անվտանգության header-ները պաշտպանություն են ավելացնում browser-ի կողմից։ HTTP Strict Transport Security-ն ստիպում է օգտագործել HTTPS։ Content Security Policy-ն (CSP) browser-ին ասում է, թե script-ների, style-երի և պատկերների որ աղբյուրներն են թույլատրված, ինչը արգելափակում է ներարկված script-ների մեծ մասը. սկսեք report-only ռեժիմից, հետո enforce արեք և 'unsafe-inline'-ի փոխարեն նախընտրեք nonce-ներ կամ hash-եր։ X-Content-Type-Options-ը կանգնեցնում է MIME sniffing-ը, CSP-ի frame-ancestors-ը կանխում է clickjacking-ը, իսկ Referrer-Policy-ն և Permissions-Policy-ն սահմանափակում են, թե ինչ է արտահոսում կամ ինչ է թույլատրված։ Cookie-ները նշեք Secure, HttpOnly և SameSite։
# nginx: baseline security headers (adapt CSP sources to your app)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https://cdn.example.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
server_tokens off;
05Գաղտնիքներ, կախվածություններ և supply chain
Գաղտնիքների (API key-եր, բազայի գաղտնաբառեր, ստորագրման բանալիներ) տեղը environment variable-ներում կամ secrets manager-ում է, երբեք repository-ում, կլիենտային bundle-ներում, լոգերում կամ սխալի հաղորդագրություններում։ Յուրաքանչյուր գաղտնիքի տվեք իրեն անհրաժեշտ նվազագույն իրավունքները, բաժանեք դրանք ըստ միջավայրի և ռոտացիա արեք ժամանակացույցով և անմիջապես ցանկացած կասկածելի արտահոսքից հետո. արտահոսած key-ը, որը հնարավոր չէ արագ ռոտացիա անել, նախագծման թերություն է։ Ավելացրեք secret scanning repository-ում և CI-ում, որպեսզի սխալները բռնվեն մինչև push-ը։ Ժամանակակից հավելվածները հիմնականում երրորդ կողմի կոդ են, ահա թե ինչու supply-chain ձախողումներն այժմ առաջին եռյակում են։ Commit արեք lockfile-երը, աշխատեցրեք կախվածությունների audit-ներ (npm audit, composer audit, Dependabot կամ Renovate), ամրագրեք (pin) և վերանայեք CI action-ները, հեռացրեք չօգտագործվող package-ները և կասկածանքով վերաբերվեք նոր package-ներին, որոնք ունեն շատ քիչ download-ներ կամ install script-եր։ Framework-երն ու runtime-երը պահեք աջակցվող տարբերակներում։
06Rate limiting, բոտեր, review-ներ և pentest-եր
Յուրաքանչյուր endpoint, որը կարելի է չարաշահել, սահմանաչափեր է պահանջում. login, OTP և գաղտնաբառի վերականգնման request-ներ, որոնում, կոնտակտային ձևեր, ֆայլերի upload և public API-ներ։ Rate limit արեք ըստ օգտատիրոջ, IP-ի և API key-ի՝ authentication-ի վրա ավելի խիստ սահմաններով. կրկնվող ձախողումներից հետո արգելափակեք կամ դանդաղեցրեք հաշիվները և CAPTCHA կամ proof-of-work challenge ավելացրեք միայն այնտեղ, որտեղ չարաշահումն իրական է։ Առջևում դրված CDN-ը կամ WAF-ը կլանում է ծավալային հարձակումները և արգելափակում հայտնի վատ պատտերնները։ Upload-ները հատուկ ուշադրություն են պահանջում. տիպը ստուգեք ըստ բովանդակության, ոչ թե ընդլայնման, սահմանափակեք չափերը, պաշտպանվեք decompression bomb-երից և ֆայլերը մատուցեք առանձին domain-ից կամ signed հղումներով։ Հետո անվտանգությունը դարձրեք գործընթաց։ Threat model արեք նոր ֆունկցիաները («ի՞նչ կարող է անել այստեղ չարամիտ tenant-ը»), անվտանգության կետեր ներառեք code review-ում, CI-ում աշխատեցրեք SAST և կախվածությունների scan-եր, և խոշոր թողարկումներից առաջ ու պարբերաբար պատվիրեք արտաքին penetration test՝ գտածոները շտկելով ըստ severity-ի։
- Խիստ սահմաններ login-ի, OTP-ի և reset-ի հոսքերի վրա։
- Լոգավորեք անվտանգության իրադարձությունները (ձախողված login-ներ, իրավունքների մերժումներ) և alert ուղարկեք թռիչքների դեպքում։
- Pentest-երը գտնում են այն, ինչ բաց եք թողել. դրանք չեն փոխարինում անվտանգ սովորություններին։
Օգտագործեք, երբ
- Միշտ. յուրաքանչյուր web հավելվածի և API-ի այս հիմունքները պետք են առաջին թողարկումից։
- Վճարումների, անձնական տվյալների, upload-ների կամ իրավունքների հետ կապված ֆունկցիաներ թողարկելուց առաջ։
- Նոր endpoint-ների code review-ի և ճարտարապետական review-ի ժամանակ։
- Արտաքին audit-ներից, enterprise վաճառքներից և compliance գնահատումներից առաջ։
Մի՛ օգտագործեք, երբ
- Top 10-ը մի համարեք ամբողջական ստանդարտ. մանրամասն պահանջների համար օգտագործեք ASVS-ը։
- Մի հենվեք obscurity-ի վրա (թաքնված URL-ներ, անջատված introspection) որպես ձեր միակ պաշտպանություն։
- Մի գրեք ձեր սեփական կրիպտոգրաֆիան կամ գաղտնաբառերի hashing-ը. օգտագործեք ստուգված գրադարաններ։
Այլընտրանքներ
- OWASP ASVS
Անվտանգության պահանջների մանրամասն, մակարդակներով checklist՝ ստուգման համար։
- OWASP API Security Top 10
Կենտրոնացած է API ռիսկերի վրա, ինչպիսիք են object-level authorisation-ը և ռեսուրսների սպառումը։
- Managed WAF և բոտերից պաշտպանություն
Edge պաշտպանություն, որը արգելափակում է տարածված հարձակումները և չարաշահող տրաֆիկը նախքան ձեզ հասնելը։
- Bug bounty ծրագրեր
Շարունակական արտաքին թեստավորում, լավագույնն է հիմունքներից և pentest-ից հետո։
Լավագույն պրակտիկաներ
- Authorisation-ը ստուգեք սերվերում յուրաքանչյուր օբյեկտի և գործողության համար՝ լռելյայն մերժելով։
- Օգտագործեք պարամետրացված query-ներ և framework-ի escaping-ը. sanitize արեք ցանկացած հարուստ HTML։
- Ուղարկեք անվտանգության header-ներ, այդ թվում՝ enforce արված Content Security Policy։
- Գաղտնիքները պահեք կոդից դուրս, տվեք նվազագույն scope և ռոտացիա արեք։
- Ավտոմատացրեք կախվածությունների և գաղտնիքների scanning-ը CI-ում և runtime-երը պահեք աջակցվող տարբերակներում։
- Rate limit արեք authentication-ը, OTP-ն և չարաշահման ենթակա endpoint-ները։
- Լոգավորեք անվտանգության իրադարձությունները և ստուգեք ձեր պաշտպանությունը review-ներով և pentest-երով։
Տարածված սխալներ
- Կոճակը թաքցնել UI-ում՝ սերվերում իրավունքը կիրառելու փոխարեն։
- SQL կամ shell հրամաններ կառուցել string concatenation-ով։
- Production-ում բաց թողնել debug mode-ը, stack trace-երը կամ admin panel-ները։
- Գաղտնիքները commit անել Git և դրանք ջնջել միայն հետագա commit-ում։
- Անտեսել կախվածությունների alert-ները, մինչև ակտիվորեն exploit արվող խոցելիությունը արտակարգ իրավիճակ ստեղծի։
Խորը վերլուծություն
07Գաղտնաբառեր, սեսիաներ և token-ներ՝ ճիշտ ձևով
Գաղտնաբառերը պահիր դանդաղ, memory-hard hash-ով։ OWASP-ի Password Storage Cheat Sheet-ը խորհուրդ է տալիս Argon2id՝ առնվազն 19 MiB հիշողությամբ, 2 իտերացիայով և 1 parallelism-ով, scrypt՝ երբ Argon2id-ն հասանելի չէ, bcrypt՝ միայն legacy համակարգերի համար՝ 10 կամ ավելի work factor-ով և հաշվի առնելով նրա 72 բայթանոց մուտքի սահմանը։ Նոր գաղտնաբառերը ստուգիր հայտնի արտահոսած ցուցակների դեմ՝ տարօրինակ կազմության կանոններ պարտադրելու փոխարեն։ Սեսիաների համար սերվերում պահվող անթափանց պատահական ID-ները պարզ են և ակնթարթորեն չեղարկելի։ Եթե օգտագործում ես JWT-ներ, սերվերում ամրագրիր ընդունելի ալգորիթմը (երբեք մի վստահիր token-ի alg header-ին), վալիդացրու issuer-ը, audience-ը և ժամկետը, access token-ները պահիր կարճակյաց, իսկ refresh token-ները փոխիր ամեն օգտագործման ժամանակ՝ հին refresh token-ի կրկնակի օգտագործումը դիտարկելով որպես գողություն և չեղարկելով ամբողջ «ընտանիքը»։ Login-ից և արտոնությունների փոփոխություններից հետո վերագեներացրու սեսիայի ID-ները՝ session fixation-ը կանխելու համար։
import argon2 from "argon2";
// OWASP minimum: Argon2id, 19 MiB memory, 2 iterations, parallelism 1
export function hashPassword(password: string) {
return argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // KiB
timeCost: 2,
parallelism: 1,
});
}
export function verifyPassword(hash: string, password: string) {
return argon2.verify(hash, password); // parameters are read from the hash
}
08Խիստ Content Security Policy և Trusted Types
Allow-list policy-ները (script-src՝ բազմաթիվ CDN host-երով) հաճախ շրջանցելի են, որովհետև թույլատրված host-երից մեկը կարող է սպասարկել JSONP endpoint կամ հին գրադարան, որը հարձակվողը կարող է չարաշահել։ Խիստ policy-ն փոխարենը հենվում է nonce-ների կամ hash-երի վրա․ սերվերը յուրաքանչյուր պատասխանի համար գեներացնում է նոր պատահական nonce, դնում այն յուրաքանչյուր օրինական script tag-ի վրա և header-ում։ 'strict-dynamic'-ի ավելացումը թույլ է տալիս աշխատել նաև վստահելի script-ի կողմից բեռնված script-ներին, այնպես որ tag manager-ներն ու bundler-ները շարունակում են աշխատել, իսկ առանց nonce-ի ներարկված markup-ը արգելափակվում է։ Համադրիր այն object-src 'none'-ի և base-uri 'none'-ի կամ 'self'-ի հետ։ DOM-based XSS-ի համար Trusted Types-ը (require-trusted-types-for 'script') ստիպում է բրաուզերին մերժել raw տողերը վտանգավոր sink-երում, օրինակ՝ innerHTML-ում, և կոդը անցկացնել վերանայված sanitising policy-ով։ Նախ թողարկիր report-only ռեժիմում և շտկիր խախտումները։
Content-Security-Policy:
script-src 'nonce-r4nd0mBase64Value' 'strict-dynamic';
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
require-trusted-types-for 'script';
report-to csp-endpoint
09SSRF խորությամբ․ DNS rebinding և cloud metadata
URL տողում մասնավոր IP-ներն արգելափակելը բավարար չէ։ Հարձակվողներն օգտագործում են այլընտրանքային գրառումներ (տասական կամ IPv6-mapped հասցեներ), redirect-ներ դեպի ներքին host-եր և DNS rebinding, երբ hostname-ը քո ստուգման ժամանակ resolve է լինում հանրային IP-ի, իսկ մի պահ անց, երբ միանում ես, 127.0.0.1-ի կամ 169.254.169.254-ի։ Ամուր պաշտպանությունը hostname-ը resolve է անում մեկ անգամ, յուրաքանչյուր resolve արված հասցե ստուգում արգելված տիրույթների դեմ (loopback, private, link-local, unique local IPv6), հետո միանում է հենց այդ IP-ին՝ ուղարկելով սկզբնական Host header-ը, և նորից ստուգում ամեն redirect-ի ժամանակ կամ անջատում է redirect-ները։ Ավելի լավ է՝ օգտատիրոջ նախաձեռնած բոլոր fetch-երն անցկացրու egress proxy-ով, որը կենտրոնացված կիրառում է policy-ն և հասանելիություն չունի ներքին ցանցերին։ AWS-ում պահանջիր IMDSv2, որի session token-ը պետք է ստացվի PUT հարցմամբ, ինչը արգելափակում է instance credentials-ի դեմ SSRF-ի պարզ փորձերի մեծ մասը։
- Ստուգիր resolve արված IP-ները, ոչ թե URL-ի տեքստը, և միացումն ամրագրիր դրանց։
- Արգելափակիր loopback, RFC 1918, link-local և IPv6 unique-local տիրույթները։
- Օգտատիրոջ նախաձեռնած fetch-երն անցկացրու մեկուսացված egress proxy-ով։
10Cookie-ներ, CORS և բրաուզերի մեկուսացում
Cookie-ի ատրիբուտները էժան, բայց ուժեղ շերտ են։ Secure-ը և HttpOnly-ն սեսիայի cookie-ները հեռու են պահում պարզ HTTP-ից և JavaScript-ից։ SameSite=Lax-ը, որը ժամանակակից բրաուզերներում լռելյայն է, երբ նշված չէ, արգելափակում է cross-site POST-երի մեծ մասը․ Strict-ն օգտագործիր բարձր զգայուն cookie-ների համար, իսկ None; Secure-ը՝ միայն երբ իսկապես cross-site օգտագործման կարիք ունես։ __Host- prefix-ը ստիպում է Secure, Path=/ և Domain ատրիբուտի բացակայություն, այնպես որ կոտրված subdomain-ը չի կարող վերագրել cookie-ն։ CORS-ը հաճախ սխալ է հասկացվում․ այն մեղմացնում է same-origin policy-ն, այլ ոչ թե պաշտպանում քո API-ն։ Երբեք մի արտացոլիր կամայական Origin արժեքներ Access-Control-Allow-Credentials: true-ի հետ միասին․ պահիր բացահայտ allow-list։ Ավելի ուժեղ մեկուսացման համար Cross-Origin-Opener-Policy: same-origin-ը քո պատուհանը առանձնացնում է cross-origin popup-ներից, իսկ Cross-Origin-Resource-Policy-ն սահմանափակում է, թե որ կայքերը կարող են ներդնել քո ռեսուրսները։
Set-Cookie: __Host-session=9f1c...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=3600
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Vary: Origin
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Իրական իրավիճակներ
API key-ը push է արվել հանրային repository
Խնդիր
Ծրագրավորողը commit արեց վճարային provider-ի գաղտնի key-ը հանրային repository-ում։ Այն հեռացվեց հաջորդ commit-ով մեկ ժամ անց։
Ինչպես լուծել
Ենթադրիր, որ այն կոմպրոմետացված է․ բոտերը սկանավորում են հանրային repository-ները րոպեների ընթացքում։ Անմիջապես չեղարկիր կամ փոխիր key-ը provider-ի dashboard-ում, նոր key-ը դեպլոյ արա environment variable-ների կամ secrets manager-ի միջոցով և ստուգիր provider-ի լոգերը անհայտ IP-ներից ակտիվության համար բացահայտման պատուհանում։ Հետո մաքրիր պատմությունը, եթե repository-ն պետք է հանրային մնա՝ իմանալով, որ դա չի վերացնում բացահայտումը։ Ավելացրու secret scanning՝ push protection-ով, pre-commit hook և ավելի նեղ սահմանափակված key-եր ըստ ծառայության, որպեսզի ապագա արտահոսքն ունենա ավելի փոքր blast radius։
Pentest-ում հայտնաբերված IDOR
Խնդիր
Penetration test-ը ցույց է տալիս, որ /api/invoices/{id}/pdf-ում invoice ID-ն փոխելով կարելի է ներբեռնել այլ հաճախորդների հաշիվ-ապրանքագրերը։ Endpoint-ը արագ էր ավելացվել մոբայլ հավելվածի համար։
Ինչպես լուծել
Նախ շտկիր endpoint-ը․ invoice-ը բեռնիր ընթացիկ օգտատիրոջ account-ով սահմանափակված query-ով, չգտնվելու դեպքում վերադարձրու 404 և դեպլոյ արա։ Հետո codebase-ում փնտրիր նույն պատերնը՝ ցանկացած handler, որը բեռնում է ըստ ID-ի առանց scope-ի, և դրանք անցկացրու policy-ի կամ scoped repository-ի միջով։ Ավելացրու ավտոմատ authorisation թեստերի հավաքածու, որը կանչում է յուրաքանչյուր endpoint երկրորդ օգտատիրոջ անունից և սպասում 404 կամ 403։ Վերանայիր access log-երը այն ժամանակահատվածի համար, երբ endpoint-ը գոյություն ուներ, տեսնելու համար՝ արդյոք այն շահագործվել է, և եթե այո, տեղեկացրու տուժած հաճախորդներին։
CSP-ի ներդրում գոյություն ունեցող կայքում
Խնդիր
Մարքեթինգային կայքը՝ analytics-ով, chat widget-ով և inline script-ներով, չունի CSP։ Policy-ն մեկ քայլով կիրառելը կկոտրի ֆունկցիոնալությունը։
Ինչպես լուծել
Սկսիր Content-Security-Policy-Report-Only-ով և reporting endpoint-ով՝ օգտագործելով nonce-ի վրա հիմնված policy 'strict-dynamic'-ով։ Յուրաքանչյուր պատասխանի nonce-ը ավելացրու օրինական inline և արտաքին script-ներին framework-ի միջոցով (Next.js middleware-ը կամ սերվերային template-ները կարող են դա անել)։ Մեկ շաբաթ հավաքիր report-ներ, շտկիր կամ հեռացրու այն խախտող script-ները և inline event handler-ները տեղափոխիր script ֆայլեր։ Հետո կիրառիր policy-ն, reporting-ը թող միացված և ավելացրու CI ստուգում կամ code review կանոն ցանկացած նոր third-party script-ի համար։
Արագ ուղեցույց
- Գաղտնաբառերի hash
Argon2id, m=19 MiB, t=2, p=1 (OWASP-ի նվազագույնը)- Սեսիայի cookie
__Host-session=...; Path=/; Secure; HttpOnly; SameSite=Lax- Խիստ CSP-ի միջուկ
script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none'- Փորձարկել CSP-ն առանց կոտրելու
Content-Security-Policy-Report-Only: ...- Արգելափակել DOM XSS sink-երը
require-trusted-types-for 'script'- Node կախվածությունների աուդիտ
npm audit --omit=dev- PHP կախվածությունների աուդիտ
composer audit- Գտնել գաղտնիքները Git-ի պատմության մեջ
gitleaks detect --source .- Պահանջել IMDSv2 AWS-ում
aws ec2 modify-instance-metadata-options --instance-id i-0abc --http-tokens required- Արագ ստուգել header-ները
curl -sI https://example.com
Իմ իրական նախագծերում
- POS SaaS-ում authentication-ը օգտագործում է RS256 JWT-ներ, որոնք յուրաքանչյուր request-ի ժամանակ վերստուգվում են denylist-ով, 2FA աշխատակիցների և օպերատորների համար, և scope արված API key-եր՝ live/test ռեժիմներով, rate limit-երով և ռոտացիայով։
- Այնտեղ մեդիա upload-ները ստուգվում են ըստ բովանդակության (content-sniffing), պաշտպանված են decompression bomb-երից և մատուցվում են signed private հղումներով, իսկ ելքային webhook-ները HMAC-ով ստորագրված են։
- Իմ սերվերային բազային մակարդակը. միայն SSH key-եր, firewall, որը թույլ է տալիս միայն 22, 80 և 443 port-երը, բազաներ, որոնք երբեք public չեն բացվում, fail2ban և unattended upgrades, և HTTPS ամենուր։
- Կենդանիների ապրանքների պլատֆորմում որոնումը rate limit արված է, իսկ admin login-ը օգտագործում է OTP. ընդհանուր package-ներում քարտի հում տվյալները դուրս են պահված persisted cart store-ից։
Հարցեր և պատասխաններ
Q1Ո՞րն է web հավելվածների ամենատարածված լուրջ խոցելիությունը։
Broken access control-ը, որն առաջինն է OWASP Top 10-ում։ Սովորաբար API-ն ստուգում է, որ օգտատերը authenticated է, բայց ոչ այն, որ նրան թույլատրված է հասանելիություն կոնկրետ օբյեկտին, ուստի URL-ում ID-ն փոխելը վերադարձնում է ուրիշի պատվերը կամ հաշիվ-ապրանքագիրը։ Այն տարածված է, որովհետև framework-երը ձեր փոխարեն կարգավորում են authentication-ը, բայց չեն կարող իմանալ ձեր բիզնես կանոնները։ Ես կանխում եմ այն կենտրոնացված authorisation policy-ներով, որոնք կանչվում են յուրաքանչյուր request-ի ժամանակ, query-ների scope-ով ըստ օգտատիրոջ կամ tenant-ի, լռելյայն մերժելով և անհասանելի օբյեկտների համար վերադարձնելով 404, գումարած ավտոմատ թեստեր, որոնք երկրորդ հաշվով փորձում են արգելված հասանելիություն։
Q2Ինչպե՞ս եք կանխում SQL injection-ը։
Երբեք SQL չկառուցելով օգտատիրոջ input-ի string concatenation-ով։ Օգտագործեք պարամետրացված query-ներ կամ prepared statement-ներ, որտեղ SQL տեքստը և արժեքները ճանապարհորդում են առանձին, ուստի input-ը չի կարող փոխել query-ի կառուցվածքը։ ORM-ները և query builder-ները դա անում են լռելյայն, բայց դրանց raw-query helper-ները և դինամիկ identifier-ները, օրինակ՝ տեսակավորման սյունակները, այն տեղերն են, որտեղ բագերը վերադառնում են. դրանց allow-list է պետք։ Որպես defence in depth, բազայի օգտատերը պետք է ունենա միայն այն իրավունքները, որոնք հավելվածին պետք են, և սխալները չպետք է բացահայտեն SQL-ի մանրամասները։ Code review-ն և ստատիկ անալիզը բռնում են մնացած դեպքերի մեծ մասը։
Q3Ի՞նչ է Content Security Policy-ն, և ինչպե՞ս եք այն ներդնում։
CSP-ն HTTP header է, որը browser-ին ասում է, թե script-ների, style-երի, պատկերների, frame-երի և կապերի որ աղբյուրներն են թույլատրված։ Եթե հարձակվողը script tag է ներարկում, browser-ը հրաժարվում է այն աշխատեցնել, եթե այն չի համապատասխանում policy-ին, ինչը CSP-ն դարձնում է ուժեղ երկրորդ շերտ XSS-ի դեմ։ Ես այն ներդնում եմ աստիճանաբար. սկսում եմ Content-Security-Policy-Report-Only-ով և collector-ով, շտկում եմ օրինական աղբյուրներից եկող խախտումները, հետո enforce եմ անում։ Inline script-ների համար 'unsafe-inline'-ի փոխարեն նախընտրեք nonce-ներ կամ hash-եր, ավելացրեք object-src 'none', base-uri 'self' և frame-ancestors՝ clickjacking-ը կանխելու համար, և վերանայեք այն ամեն անգամ, երբ երրորդ կողմի script-երը փոխվում են։
Q4XSS vs CSRF. ո՞րն է տարբերությունը։
XSS-ը՝ cross-site scripting-ը, նշանակում է, որ հարձակվողը իր script-ն աշխատեցնում է ձեր կայքի ներսում, օրինակ՝ unescaped մեկնաբանության միջոցով։ Այդ script-ն աշխատում է օգտատիրոջ իրավունքներով ձեր origin-ում, ուստի կարող է կարդալ էջը և request-ներ անել։ CSRF-ը՝ cross-site request forgery-ն, նշանակում է, որ այլ կայք ստիպում է օգտատիրոջ browser-ին request ուղարկել ձեր կայքին՝ օգտվելով նրա cookie-ներից, առանց ձեր origin-ում կոդ աշխատեցնելու։ XSS-ը կանխվում է output escaping-ով, sanitize անելով և CSP-ով։ CSRF-ը կանխվում է SameSite cookie-ներով, anti-CSRF token-ներով և Origin-ի ստուգմամբ։ Նկատի ունեցեք, որ XSS-ը հաղթահարում է CSRF պաշտպանությունը, որովհետև script-ը կարող է կարդալ token-ները։
Q5Ինչպե՞ս եք կառավարում գաղտնիքները նախագծում։
Գաղտնիքները երբեք չեն հայտնվում repository-ում, կլիենտային bundle-ում կամ լոգերում։ Դրանք ապրում են environment variable-ներում, որոնք ներարկվում են deploy-ի ժամանակ, կամ, ավելի լավ, secrets manager-ում՝ access control-ով և audit լոգերով։ Յուրաքանչյուր միջավայր ունի իր գաղտնիքները, յուրաքանչյուր գաղտնիք ունի իրեն անհրաժեշտ նվազագույն իրավունքները, և ռոտացիան սովորական, փաստաթղթավորված գործողություն է։ Secret scanning-ը աշխատում է pre-commit hook-երում և CI-ում։ Եթե գաղտնիքն արտահոսում է, նախ ռոտացիա եմ անում, հետո ուսումնասիրում, որովհետև այն Git-ի պատմությունից հեռացնելը չի օգնում, երբ այն արդեն push է արվել. ցանկացած մեկը կարող է արդեն պատճենած լինել այն։
Q6Ի՞նչ կստուգեիք web հավելվածի արագ անվտանգության review-ի ժամանակ։
Սկսում եմ access control-ից. կարո՞ղ է A օգտատերը հասնել B օգտատիրոջ ռեսուրսներին՝ ID-ները փոխելով, և արդյո՞ք admin endpoint-ները պաշտպանված են սերվերում։ Հետո authentication. գաղտնաբառերի hashing, login-ի և OTP-ի rate limiting, session-ների և token-ների մշակում։ Հետո input-ի մշակում. պարամետրացված query-ներ, output escaping, ֆայլերի upload-ի validation և սերվերի կողմից URL-ների ցանկացած բերում։ Հաջորդը կոնֆիգուրացիան է. debug mode, սխալի էջեր, բաց ֆայլեր, անվտանգության header-ներ, CORS և cookie-ների flag-եր։ Հետո գաղտնիքները repository-ում և կախվածությունների audit-ի արդյունքները։ Եվ վերջապես լոգավորումը. գրանցվո՞ւմ են արդյոք ձախողված login-ները և իրավունքների մերժումները, և alert ուղարկվո՞ւմ է։ Սա արագ ընդգրկում է Top 10-ի մեծ մասը։
Սենիոր մակարդակի հարցեր
S1JWT-ներ, թե՞ սերվերային սեսիաներ․ ի՞նչ կընտրեիր և ինչու։
First-party վեբ հավելվածի համար սերվերային սեսիաները՝ __Host- cookie-ում անթափանց ID-ով, սովորաբար ավելի անվտանգ default են․ ակնթարթային չեղարկում, փոքր cookie-ներ և token-ների parsing-ի թակարդների բացակայություն։ JWT-ները օգնում են, երբ շատ ծառայություններ պետք է ստուգեն ինքնությունը՝ առանց կենտրոնական պահոց կանչելու, կամ third-party API հասանելիության համար։ Դրանց ծախսերը․ չեղարկումը պահանջում է կարճ ժամկետ գումարած denylist կամ ամեն հարցման վերավալիդացիա, ալգորիթմի և key-երի կառավարումը պետք է խիստ լինի, իսկ դրանք localStorage-ում պահելը բացահայտում է դրանք XSS-ի առաջ։ Տարածված հիբրիդ է կարճակյաց access token-ները՝ մոտ րոպեներ, պտտվող refresh token-ներով, որոնք պահվում են HttpOnly cookie-ներում՝ կրկնակի օգտագործման հայտնաբերմամբ։ Ինչ էլ ընտրես, ստորագրիր ասիմետրիկ key-երով, երբ մի քանի ծառայություն են ստուգում, key-երը փոխիր key ID-ով և լոգավորիր authentication իրադարձությունները հայտնաբերման համար։
S2Ինչպե՞ս ես անվտանգությունը ներդնում delivery pipeline-ում՝ առանց թիմերին դանդաղեցնելու։
Ավտոմատացրու էժան և ճշգրիտ ստուգումները, իսկ մարդկային ուշադրությունը պահիր դիզայնի համար։ Pipeline-ում․ secret scanning՝ push protection-ով, կախվածությունների աուդիտներ, որոնք ձախողվում են միայն բարձր խստության խնդիրների վրա, որոնց համար շտկում կա, SAST՝ կարգավորված փոքր, վստահելի կանոնների հավաքածուի վրա, lockfile և ամրագրված CI action-ներ, ինչպես նաև container image-ների սկանավորում։ Merge-ը արգելափակիր կարևոր արդյունքների դեպքում, մնացածն ուղարկիր backlog՝ պատասխանատուներով։ Կոդավորելուց առաջ անցկացրու կարճ threat-modelling սեսիա auth-ին, վճարումներին, upload-ներին կամ tenant-ների սահմաններին դիպչող ֆիչերի համար։ Ընդհանուր գրադարաններում տրամադրիր անվտանգ default-ներ, օրինակ՝ scoped repository-ներ, SSRF պաշտպանությամբ HTTP կլիենտ և header middleware, որպեսզի անվտանգ ճանապարհը լինի հեշտ ճանապարհը։ Փոխզիջումը կարգավորման և tuning-ի ջանքն է․ չկարգավորված գործիքները ստեղծում են աղմուկ, որը ծրագրավորողները սովորում են անտեսել։
S3Ինչպե՞ս կարձագանքեիր քո օգտագործած կախվածությունում հրապարակված կրիտիկական խոցելիությանը։
Դիտարկիր այն որպես ժամանակի դեմ մրցող ինցիդենտ։ Նախ որոշիր բացահայտվածությունը․ արդյոք խոցելի փաթեթը կա պրոդակշն build-երում, տուժած տարբերակով, և արդյոք խոցելի կոդի ուղին հասանելի է հարձակվողի վերահսկած մուտքով։ Software bill of materials-ը կամ lockfile-ում որոնումը առաջին երկուսին պատասխանում է րոպեների ընթացքում։ Եթե բացահայտված ես, մեղմացրու ամենաարագ ձևով․ թարմացրու կամ patch արա, կամ կիրառիր ժամանակավոր հսկողություն, օրինակ՝ WAF կանոն, ֆիչի անջատում կամ մուտքի պատերնի արգելափակում։ Դեպլոյ արա սովորական pipeline-ով, բայց արագացված, և ստուգիր շտկումը։ Լոգերում փնտրիր շահագործման փորձեր հրապարակումից ի վեր և փոխիր գաղտնիքները, եթե կոդի կատարումը հնարավոր էր։ Դրանից հետո վերանայիր, թե ինչու հայտնաբերումն այդքան երկար տևեց, և արդյոք թարմացումների ավտոմատ գործիքները այն ավելի շուտ կբռնեին։
Բառարան
- IDOR
- Insecure direct object reference․ այլ օգտատիրոջ օբյեկտին հասանելիություն՝ նույնացուցիչը փոխելով։
- SSRF
- Server-side request forgery․ սերվերին խաբելով ստիպել ներբեռնել ներքին կամ չնախատեսված URL-ներ։
- CSRF
- Կեղծված cross-site հարցում, որը օգտվում է զոհի cookie-ներից՝ վիճակը փոխելու համար։
- XSS
- Cross-site scripting․ հարձակվողի վերահսկած script, որն աշխատում է քո կայքի էջերում։
- CSP nonce
- Յուրաքանչյուր պատասխանի համար պատահական արժեք, որը նշում է, թե որ script-ները կարող է բրաուզերը կատարել։
- Trusted Types
- Բրաուզերի հնարավորություն, որն արգելափակում է raw տողերը վտանգավոր DOM sink-երում, եթե դրանք չեն անցել policy-ով։
- Argon2id
- Memory-hard գաղտնաբառերի hashing ալգորիթմ, որը OWASP-ը խորհուրդ է տալիս գաղտնաբառեր պահելու համար։
- DNS rebinding
- Hostname-ի resolve-ը ստուգման պահին անվտանգ IP-ի, իսկ ավելի ուշ՝ ներքին IP-ի։
- Supply chain attack
- Ծրագրի կոմպրոմետացում նրա կախվածությունների, build գործիքների կամ առաքման pipeline-ի միջոցով։
Շարունակեք սովորել
Պրոդուկտի գաղափար ունե՞ք։Եկեք ստեղծենք այն։
Պատմեք ձեր գաղափարի, պրոդուկտի կամ թիմի մասին։ Սովորաբար պատասխանում եմ մեկ աշխատանքային օրվա ընթացքում։