Apgūstiet JavaScript drošību ar šo visaptverošo rokasgrāmatu. Uzziniet, kā ieviest stabilu drošības infrastruktūru, kas aptver CSP, CORS, drošu kodēšanu, autentifikāciju un daudz ko citu.
Digitālā cietokšņa būvniecība: pilnīga rokasgrāmata JavaScript drošības infrastruktūras ieviešanai
Mūsdienu digitālajā ekosistēmā JavaScript ir neapstrīdama tīmekļa lingua franca. Tas nodrošina visu, sākot no dinamiskām lietotāja saskarnēm klienta pusē līdz spēcīgiem, augstas veiktspējas serveriem aizmugurē. Tomēr šī visuresamība padara JavaScript lietojumprogrammas par galveno mērķi ļaunprātīgiem dalībniekiem. Viena ievainojamība var izraisīt postošas sekas, tostarp datu noplūdes, finansiālus zaudējumus un reputācijas bojājumus. Ar funkcionāla koda rakstīšanu vien vairs nepietiek; stabilas, noturīgas drošības infrastruktūras izveide ir neapspriežama prasība jebkuram nopietnam projektam.
Šī rokasgrāmata sniedz visaptverošu, uz ieviešanu vērstu soli pa solim aprakstu par modernas JavaScript drošības infrastruktūras izveidi. Mēs virzīsimies tālāk par teorētiskiem konceptiem un iedziļināsimies praktiskos soļos, rīkos un labākajā praksē, kas nepieciešama, lai stiprinātu jūsu lietojumprogrammas no paša sākuma. Neatkarīgi no tā, vai esat front-end izstrādātājs, back-end inženieris vai full-stack profesionālis, šī rokasgrāmata nodrošinās jums zināšanas, lai ap jūsu kodu izveidotu digitālu cietoksni.
Mūsdienu JavaScript draudu vides izpratne
Pirms mēs veidojam savus aizsardzības mehānismus, mums vispirms jāsaprot, no kā mēs aizsargājamies. Draudu vide pastāvīgi attīstās, taču vairākas galvenās ievainojamības joprojām ir izplatītas JavaScript lietojumprogrammās. Veiksmīgai drošības infrastruktūrai sistemātiski jānovērš šie draudi.
- Starpvietņu skriptošana (XSS): Šī, iespējams, ir vislabāk zināmā tīmekļa ievainojamība. XSS notiek, kad uzbrucējs ievieto ļaunprātīgus skriptus uzticamā vietnē. Pēc tam šie skripti tiek izpildīti upura pārlūkprogrammā, ļaujot uzbrucējam nozagt sesijas pilnvaras, nokasīt sensitīvus datus vai veikt darbības lietotāja vārdā.
- Starpvietņu pieprasījumu viltošana (CSRF): CSRF uzbrukumā uzbrucējs pievilina pierakstījušos lietotāju iesniegt ļaunprātīgu pieprasījumu tīmekļa lietojumprogrammai, ar kuru viņi ir autentificēti. Tas var izraisīt neatļautas stāvokļa maiņas darbības, piemēram, e-pasta adreses maiņu, līdzekļu pārskaitīšanu vai konta dzēšanu.
- Piegādes ķēdes uzbrukumi: Mūsdienu JavaScript izstrāde lielā mērā ir atkarīga no atvērtā pirmkoda pakotnēm no reģistriem, piemēram, npm. Piegādes ķēdes uzbrukums notiek, kad ļaunprātīgs dalībnieks apdraud vienu no šīm pakotnēm, ievietojot ļaunprātīgu kodu, kas pēc tam tiek izpildīts katrā lietojumprogrammā, kas to izmanto.
- Nedroša autentifikācija un autorizācija: Nepilnības lietotāju identificēšanas (autentifikācijas) un tā, ko viņiem ir atļauts darīt (autorizācija), var piešķirt uzbrucējiem neatļautu piekļuvi sensitīviem datiem un funkcionalitātei. Tas ietver vājas paroļu politikas, nepareizu sesijas pārvaldību un bojātu piekļuves kontroli.
- Sensitīvu datu atklāšana: Sensitīvas informācijas, piemēram, API atslēgu, paroļu vai personisku lietotāju datu atklāšana klienta puses kodā, izmantojot nedrošus API galapunktus vai žurnālos, ir kritiska un izplatīta ievainojamība.
Mūsdienu JavaScript drošības infrastruktūras pīlāri
Visaptveroša drošības stratēģija nav viens rīks vai tehnika, bet gan daudzslāņu aizsardzības pieeja. Mēs varam organizēt savu infrastruktūru sešos galvenajos pīlāros, katrs no tiem risinot atšķirīgu lietojumprogrammu drošības aspektu.
- Aizsardzība pārlūkprogrammas līmenī: Mūsdienu pārlūkprogrammas drošības funkciju izmantošana, lai izveidotu spēcīgu pirmo aizsardzības līniju.
- Lietojumprogrammas līmeņa droša kodēšana: Koda rakstīšana, kas ir raksturīgi izturīgs pret izplatītākajiem uzbrukumu vektoriem.
- Stabila autentifikācija un autorizācija: Droša lietotāja identitātes un piekļuves kontroles pārvaldība.
- Droša datu apstrāde: Datu aizsardzība gan pārsūtīšanas laikā, gan miera stāvoklī.
- Atkarību un būvēšanas cauruļvada drošība: Programmatūras piegādes ķēdes un izstrādes dzīves cikla aizsardzība.
- Žurnalēšana, uzraudzība un reaģēšana uz incidentiem: Drošības notikumu atklāšana, reaģēšana uz tiem un mācīšanās no tiem.
Izpētīsim, kā sīkāk ieviest katru no šiem pīlāriem.
1. pīlārs: Aizsardzības ieviešana pārlūkprogrammas līmenī
Mūsdienu pārlūkprogrammas ir aprīkotas ar spēcīgiem drošības mehānismiem, kurus varat kontrolēt, izmantojot HTTP galvenes. To pareiza konfigurēšana ir viens no visefektīvākajiem soļiem, ko varat spert, lai mazinātu plašu uzbrukumu klāstu, īpaši XSS.Satura drošības politika (CSP): Jūsu galvenā aizsardzība pret XSS
Satura drošības politika (CSP) ir HTTP atbildes galvene, kas ļauj norādīt, kuriem dinamiskajiem resursiem (skriptiem, stiliem, attēliem utt.) ir atļauts ielādēt pārlūkprogrammu. Tā darbojas kā baltā saraksta veids, efektīvi neļaujot pārlūkprogrammai izpildīt ļaunprātīgus skriptus, ko ievietojis uzbrucējs.
Īstenošana:
Jūsu mērķis ir stingra CSP. Labs sākumpunkts izskatās šādi:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://api.yourapp.com; frame-ancestors 'none'; report-uri /csp-violation-report-endpoint;
Sadaliet šīs direktīvas:
default-src 'self'
: Pēc noklusējuma atļaujiet ielādēt resursus tikai no viena avota (jūsu paša domēna).script-src 'self' https://trusted-cdn.com
: Atļaujiet skriptus tikai no sava domēna un uzticama satura piegādes tīkla.style-src 'self' 'unsafe-inline'
: Atļaujiet stilu lapas no sava domēna. Piezīme:'unsafe-inline'
bieži ir nepieciešams mantotajam CSS, bet, ja iespējams, no tā vajadzētu izvairīties, pārveidojot iekļautos stilus.img-src 'self' data:
: Atļaujiet attēlus no sava domēna un no datu URI.connect-src 'self' https://api.yourapp.com
: Ierobežo AJAX/Fetch pieprasījumus ar jūsu paša domēnu un jūsu konkrēto API galapunktu.frame-ancestors 'none'
: Neļauj jūsu vietnei tikt iegultai elementā<iframe>
, tādējādi mazinot klikšķu nolaupīšanas uzbrukumus.report-uri /csp-violation-report-endpoint
: Norāda pārlūkprogrammai, kur sūtīt JSON ziņojumu, kad tiek pārkāpta politika. Tas ir ļoti svarīgi, lai uzraudzītu uzbrukumus un precizētu savu politiku.
Pro padoms: Par katru cenu izvairieties no 'unsafe-inline'
un 'unsafe-eval'
vietnei script-src
. Lai droši apstrādātu iekļautos skriptus, izmantojiet uz nonce balstītu vai uz hash balstītu pieeju. Nonce ir unikāla, nejauši ģenerēta pilnvara katram pieprasījumam, ko pievienojat CSP galvenei un skripta tagam.
Starpvietņu resursu koplietošana (CORS): piekļuves kontroles pārvaldība
Pēc noklusējuma pārlūkprogrammas nodrošina vienas izcelsmes politiku (SOP), kas neļauj tīmekļa lapai veikt pieprasījumus uz citu domēnu nekā to, kas apkalpoja lapu. CORS ir mehānisms, kas izmanto HTTP galvenes, lai ļautu serverim norādīt jebkuru citu izcelsmi, izņemot savu, no kuras pārlūkprogrammai vajadzētu atļaut ielādēt resursus.Īstenošana (Node.js/Express piemērs):
Nekad neizmantojiet aizstājējzīmi (*
) priekš Access-Control-Allow-Origin
ražošanas lietojumprogrammās, kas apstrādā sensitīvus datus. Tā vietā uzturiet stingru atļauto izcelsmju balto sarakstu.
const cors = require('cors');
const allowedOrigins = ['https://yourapp.com', 'https://staging.yourapp.com'];
const corsOptions = {
origin: function (origin, callback) {
if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true // Important for handling cookies
};
app.use(cors(corsOptions));
Papildu drošības galvenes pastiprināšanai
- HTTP Strict Transport Security (HSTS):
Strict-Transport-Security: max-age=31536000; includeSubDomains
. Tas norāda pārlūkprogrammām sazināties ar jūsu serveri tikai izmantojot HTTPS, novēršot protokola pazemināšanas uzbrukumus. - X-Content-Type-Options:
X-Content-Type-Options: nosniff
. Tas neļauj pārlūkprogrammām MIME-šņaukt atbildi prom no deklarētā satura veida, kas var palīdzēt novērst noteiktus XSS uzbrukumu veidus. - Referrer-Policy:
Referrer-Policy: strict-origin-when-cross-origin
. Tas kontrolē, cik daudz novirzītāja informācijas tiek nosūtīts kopā ar pieprasījumiem, novēršot iespējamu datu noplūdi URL.
2. pīlārs: Lietojumprogrammas līmeņa drošas kodēšanas prakse
Pat ar spēcīgu aizsardzību pārlūkprogrammas līmenī, nedroši kodēšanas modeļi var ieviest ievainojamības. Drošai kodēšanai jābūt pamatpraksei katram izstrādātājam.
XSS novēršana: ievades sanitizācija un izvades kodēšana
Zelta likums XSS novēršanai ir: nekad neuzticieties lietotāja ievadei. Visi dati, kas nāk no ārēja avota, jāapstrādā uzmanīgi.
- Ievades sanitizācija: Tas ietver lietotāja ievades tīrīšanu vai filtrēšanu, lai noņemtu potenciāli ļaunprātīgas rakstzīmes vai kodu. Bagātinātam tekstam izmantojiet stabilu bibliotēku, kas paredzēta šim nolūkam.
- Izvades kodēšana: Šis ir vissvarīgākais solis. Renderējot lietotāja sniegtos datus savā HTML, tie jākodē atbilstoši konkrētajam kontekstam, kurā tie parādīsies. Mūsdienu front-end ietvari, piemēram, React, Angular un Vue, to dara automātiski lielākajai daļai satura, bet jums jābūt uzmanīgiem, izmantojot tādas funkcijas kā
dangerouslySetInnerHTML
.
Īstenošana (DOMPurify sanitizācijai):
Kad jāatļauj daļa HTML no lietotājiem (piemēram, emuāra komentāru sadaļā), izmantojiet bibliotēku, piemēram, DOMPurify.
import DOMPurify from 'dompurify';
let dirtyUserInput = '<img src="x" onerror="alert('XSS')">';
let cleanHTML = DOMPurify.sanitize(dirtyUserInput);
// cleanHTML will be: '<img src="x">'
// The malicious onerror attribute is removed.
document.getElementById('content').innerHTML = cleanHTML;
CSRF mazināšana ar sinhronizācijas pilnvaru modeli
Visstabilākā aizsardzība pret CSRF ir sinhronizācijas pilnvaru modelis. Serveris ģenerē unikālu, nejaušu pilnvaru katrai lietotāja sesijai un pieprasa, lai šī pilnvara būtu iekļauta jebkurā stāvokļa maiņas pieprasījumā.
Īstenošanas koncepcija:
- Kad lietotājs piesakās, serveris ģenerē CSRF pilnvaru un saglabā to lietotāja sesijā.
- Serveris iegulda šo pilnvaru slēptā ievades laukā veidlapās vai nodrošina to klienta puses lietojumprogrammai, izmantojot API galapunktu.
- Katram stāvokļa maiņas pieprasījumam (POST, PUT, DELETE) klientam ir jānosūta šī pilnvara atpakaļ, parasti kā pieprasījuma galvene (piemēram,
X-CSRF-Token
) vai pieprasījuma pamattekstā. - Serveris pārbauda, vai saņemtā pilnvara atbilst sesijā saglabātajai. Ja tā neatbilst vai trūkst, pieprasījums tiek noraidīts.
Bibliotēkas, piemēram, csurf
priekš Express, var palīdzēt automatizēt šo procesu.
3. pīlārs: Stabla autentifikācija un autorizācija
Droša pārvaldība par to, kas var piekļūt jūsu lietojumprogrammai un ko viņi var darīt, ir drošības pamats.
Autentifikācija ar JSON tīmekļa pilnvarām (JWT)
JWT ir populārs standarts piekļuves pilnvaru izveidei. JWT satur trīs daļas: galveni, slodzi un parakstu. Paraksts ir ļoti svarīgs; tas apstiprina, ka pilnvaru izdevis uzticams serveris un tā nav viltojusi.
Labākā prakse JWT ieviešanai:
- Izmantojiet spēcīgu parakstīšanas algoritmu: Izmantojiet asimetriskus algoritmus, piemēram, RS256, nevis simetriskus, piemēram, HS256. Tas neļauj klientam vērstam serverim arī iegūt slepeno atslēgu, kas nepieciešama pilnvaru parakstīšanai.
- Saglabājiet slodzes liesas: Neuzglabājiet sensitīvu informāciju JWT slodzē. Tas ir base64 kodēts, nevis šifrēts. Uzglabājiet nesensitīvus datus, piemēram, lietotāja ID, lomas un pilnvaras derīguma termiņu.
- Iestatiet īsus derīguma termiņus: Piekļuves pilnvarām jābūt īsam darbības laikam (piemēram, 15 minūtes). Izmantojiet ilgstošu atsvaidzes pilnvaru, lai iegūtu jaunas piekļuves pilnvaras, nepieprasot lietotājam atkārtoti pierakstīties.
- Droša pilnvaru glabāšana: Šis ir kritisks strīdus punkts. JWT glabāšana vietējā atmiņā
localStorage
padara tās neaizsargātas pret XSS. Visdrošākā metode ir to glabātHttpOnly
,Secure
,SameSite=Strict
sīkfailos. Tas neļauj JavaScript piekļūt pilnvarai, mazinot zādzību, izmantojot XSS. Atsvaidzes pilnvara jāuzglabā šādā veidā, savukārt īslaicīgu piekļuves pilnvaru var turēt atmiņā.
Autorizācija: Mazākās privilēģijas princips
Autorizācija nosaka, ko autentificētam lietotājam ir atļauts darīt. Vienmēr ievērojiet mazākās privilēģijas principu: lietotājam jābūt tikai minimālajam piekļuves līmenim, kas nepieciešams savu uzdevumu veikšanai.
Īstenošana (starpprogrammatūra Node.js/Express):
Ieviesiet starpprogrammatūru, lai pārbaudītu lietotāja lomas vai atļaujas, pirms atļaut piekļuvi aizsargātam maršrutam.
function authorizeAdmin(req, res, next) {
// Assuming user information is attached to the request object by an auth middleware
if (req.user && req.user.role === 'admin') {
return next(); // User is an admin, proceed
}
return res.status(403).json({ message: 'Forbidden: Access is denied.' });
}
app.get('/api/admin/dashboard', authenticate, authorizeAdmin, (req, res) => {
// This code will only run if the user is authenticated and is an admin
res.json({ data: 'Welcome to the admin dashboard!' });
});
4. pīlārs: Atkarību un būvēšanas cauruļvada aizsardzība
Jūsu lietojumprogramma ir tik droša, cik droša ir tās vājākā atkarība. Programmatūras piegādes ķēdes aizsardzība vairs nav obligāta.
Atkarību pārvaldība un auditēšana
NPM ekosistēma ir plaša, bet tā var būt ievainojamību avots. Proaktīva atkarību pārvaldība ir būtiska.
Īstenošanas soļi:
- Auditējiet regulāri: Izmantojiet iebūvētos rīkus, piemēram,
npm audit
vai `yarn audit`, lai skenētu zināmas ievainojamības jūsu atkarībās. Integrējiet to savā CI/CD cauruļvadā, lai būvējumi neizdotos, ja tiek atrastas augstas smaguma pakāpes ievainojamības. - Izmantojiet bloķēšanas failus: Vienmēr iesniedziet savu failu
package-lock.json
vaiyarn.lock
. Tas nodrošina, ka katrs izstrādātājs un būvēšanas vide izmanto tieši tādu pašu katras atkarības versiju, novēršot neparedzētas izmaiņas. - Automatizējiet uzraudzību: Izmantojiet tādus pakalpojumus kā GitHub Dependabot vai trešo pušu rīkus, piemēram, Snyk. Šie pakalpojumi nepārtraukti uzrauga jūsu atkarības un automātiski izveido vilkšanas pieprasījumus, lai atjauninātu pakotnes ar zināmām ievainojamībām.
Statiskā lietojumprogrammu drošības testēšana (SAST)
SAST rīki analizē jūsu pirmkodu, to neizpildot, lai atrastu iespējamus drošības trūkumus, piemēram, bīstamu funkciju izmantošanu, cietkoda noslēpumus vai nedrošus modeļus.
Īstenošana:
- Linters ar drošības spraudņiem: Lielisks sākumpunkts ir ESLint izmantošana ar uz drošību vērstiem spraudņiem, piemēram,
eslint-plugin-security
. Tas nodrošina reāllaika atsauksmes jūsu koda redaktorā. - CI/CD integrācija: Integrējiet jaudīgāku SAST rīku, piemēram, SonarQube vai CodeQL, savā CI/CD cauruļvadā. Tas var veikt dziļāku analīzi par katru koda izmaiņu un bloķēt apvienošanas, kas ievieš jaunus drošības riskus.
Drošu vides mainīgo nodrošināšana
Nekad, nekad neuzlieciet noslēpumus (API atslēgas, datubāzes akreditācijas dati, šifrēšanas atslēgas) tieši savā pirmkodā. Šī ir izplatīta kļūda, kas noved pie smagiem pārkāpumiem, kad kods tiek netīšām publiskots.
Labākā prakse:
- Izmantojiet failus
.env
vietējai izstrādei un pārliecinieties, vai.env
ir norādīts jūsu failā.gitignore
. - Ražošanā izmantojiet slepeno pārvaldības pakalpojumu, ko nodrošina jūsu mākoņpakalpojumu sniedzējs (piemēram, AWS Secrets Manager, Azure Key Vault, Google Secret Manager) vai īpašu rīku, piemēram, HashiCorp Vault. Šie pakalpojumi nodrošina drošu uzglabāšanu, piekļuves kontroli un auditēšanu visiem jūsu noslēpumiem.
5. pīlārs: Droša datu apstrāde
Šis pīlārs koncentrējas uz datu aizsardzību, kad tie pārvietojas pa jūsu sistēmu un kad tie tiek uzglabāti.
Šifrējiet visu pārsūtīšanas laikā
Visa saziņa starp klientu un jūsu serveriem, kā arī starp jūsu iekšējiem mikropakalpojumiem jāšifrē, izmantojot Transport Layer Security (TLS), kas pazīstams kā HTTPS. Tas nav apspriežams. Izmantojiet HSTS galveni, kas apspriesta iepriekš, lai nodrošinātu šo politiku.
API drošības labākā prakse
- Ievades validācija: Stingri validējiet visus ienākošos datus savā API serverī. Pārbaudiet pareizus datu veidus, garumus, formātus un diapazonus. Tas novērš plašu uzbrukumu klāstu, tostarp NoSQL injekciju un citas datu korupcijas problēmas.
- Ātruma ierobežošana: Ieviesiet ātruma ierobežošanu, lai aizsargātu savu API no pakalpojuma atteices (DoS) uzbrukumiem un brute-force mēģinājumiem pieteikšanās galapunktos.
- Pareizas HTTP metodes: Izmantojiet HTTP metodes atbilstoši to mērķim. Izmantojiet
GET
drošai, idempotentu datu izgūšanai un izmantojietPOST
,PUT
unDELETE
darbībām, kas maina stāvokli. Nekad neizmantojietGET
stāvokļa maiņas operācijām.
6. pīlārs: Žurnalēšana, uzraudzība un reaģēšana uz incidentiem
Jūs nevarat aizsargāties pret to, ko nevarat redzēt. Stabils žurnalēšanas un uzraudzības sistēma ir jūsu drošības nervu sistēma, kas reāllaikā brīdina par iespējamiem draudiem.
Ko reģistrēt
- Autentifikācijas mēģinājumi (gan veiksmīgi, gan neveiksmīgi)
- Autorizācijas atteices (piekļuves atteikuma notikumi)
- Servera puses ievades validācijas atteices
- Augstas smaguma pakāpes lietojumprogrammu kļūdas
- CSP pārkāpumu ziņojumi
Būtiski, ko NEREĢISTRĒT: Nekad nereģistrējiet sensitīvus lietotāju datus, piemēram, paroles, sesijas pilnvaras, API atslēgas vai personiski identificējamu informāciju (PII) vienkāršā tekstā.
Reāllaika uzraudzība un brīdināšana
Jūsu žurnāli jāapvieno centralizētā sistēmā (piemēram, ELK stekā - Elasticsearch, Logstash, Kibana - vai pakalpojumā, piemēram, Datadog vai Splunk). Konfigurējiet informācijas paneļus, lai vizualizētu galvenos drošības rādītājus, un iestatiet automātiskus brīdinājumus par aizdomīgiem modeļiem, piemēram:
- Pēkšņs neveiksmīgu pieteikšanās mēģinājumu pieaugums no vienas IP adreses.
- Vairākas autorizācijas atteices vienam lietotāja kontam.
- Liels skaits CSP pārkāpumu ziņojumu, kas norāda uz iespējamu XSS uzbrukumu.
Izveidojiet incidentu reaģēšanas plānu
Kad notiek incidents, ļoti svarīgi ir iepriekš noteikts plāns. Tam jānorāda soļi, lai: Identificētu, Ierobežotu, Likvidētu, Atgūtu un Mācītos. Ar ko jāsazinās? Kā jūs atsaucat apdraudētos akreditācijas datus? Kā jūs analizējat pārkāpumu, lai novērstu tā atkārtošanos? Šo jautājumu pārdomāšana pirms incidenta ir bezgalīgi labāka nekā improvizēšana krīzes laikā.
Secinājums: Drošības kultūras veicināšana
JavaScript drošības infrastruktūras ieviešana nav vienreizējs projekts; tas ir nepārtraukts process un kultūras domāšanas veids. Seši pīlāri, kas šeit aprakstīti — Aizsardzība pārlūkprogrammā, Droša kodēšana, AuthN/AuthZ, Atkarību drošība, Droša datu apstrāde un Uzraudzība — veido holistisku ietvaru noturīgu un uzticamu lietojumprogrammu veidošanai.
Drošība ir kopīga atbildība. Tam nepieciešama sadarbība starp izstrādātājiem, operācijām un drošības komandām — prakse, kas pazīstama kā DevSecOps. Integrējot drošību katrā programmatūras izstrādes dzīves cikla posmā, sākot no projektēšanas un kodēšanas līdz izvietošanai un operācijām, jūs varat pāriet no reaktīvas drošības pozīcijas uz proaktīvu.
Digitālā vide turpinās attīstīties, un parādīsies jauni draudi. Tomēr, balstoties uz šo spēcīgo, daudzslāņu pamatu, jūs būsiet labi aprīkots, lai aizsargātu savas lietojumprogrammas, savus datus un savus lietotājus. Sāciet būvēt savu JavaScript drošības cietoksni jau šodien.