Domanda:
Perché memorizzare le password nel controllo della versione è una cattiva idea?
d33tah
2018-08-15 16:05:52 UTC
view on stackexchange narkive permalink

Il mio amico mi ha appena chiesto: "perché in realtà è così brutto mettere varie password direttamente nel codice sorgente del programma, quando le memorizziamo solo nel nostro server Git privato?"

Gli ho dato una risposta che ha evidenziato un paio di punti, ma ha ritenuto che non fosse abbastanza organizzato e ha deciso che poteva avere senso creare una domanda canonica per.

Inoltre, il modo in cui non memorizzare le password nel codice sorgente si riferisce al principio di privilegio minimo e altri fondamenti della sicurezza delle informazioni?

A cosa servono queste password?
La risposta è piuttosto breve, perché non dovresti mai memorizzare una password in chiaro.Nemmeno su un file chiamato TotallyNotMyPasswords.txt.Da nessuna parte.
Buona fortuna a @EpicKip nell'implementazione di qualsiasi tipo di server web senza password in testo normale memorizzate in alcun file.
È più un concetto di settore, il turn over dello sviluppatore, la separazione del ruolo delle operazioni di sviluppo, il controllo generale e la presenza di più ambienti per un'applicazione sono tutti motivi per cui non sono presenti password nel codice (sorgente se lo si desidera).
Perché non vuoi una fattura AWS di [$ 14.000] (https://dev.to/juanmanuelramallo/i-was-billed-for-14k-usd-on-amazon-web-services-17fn).
Correlato su SO: https://stackoverflow.com/a/1197512/5419599
Una buona ragione è che significa che avresti bisogno di due processi diversi per i prodotti open source e closed source.Non è possibile memorizzare le password nel controllo del codice sorgente per i prodotti open source.Più semplice se si utilizza un processo comune
@DaveCarruthers Ci sono configurazioni in cui ciò è possibile (ad esempio con Windows e autenticazione AD) oltre a questo, le password possono essere salvate in [configurazione protetta] (https://stackoverflow.com/questions/4155187/securing-a-password-nel codice sorgente)
Vorrei un piccolo chiarimento: le risposte a questa domanda dovrebbero essere focalizzate sul lato della sicurezza dell'archiviazione delle password nel controllo della versione?(Penso di sì, perché è pubblicato su "sicurezza delle informazioni".) Ho riflettuto su questa domanda e penso che ci siano ragioni per non memorizzare la password insieme al codice sorgente che vanno oltre la sicurezza.
Cosa c'è di sbagliato nell'usare [controllo della versione per le password?] (Https://www.passwordstore.org/) / interpretazione deliberata
@DaveCarruthers Puoi memorizzare un file di configurazione di esempio nel tuo repository e aggiungere manualmente quel file di configurazione alla prima distribuzione, oppure puoi memorizzare le password in chiaro in variabili CI come Gitlab e generare quei file di configurazione + distribuire in uno script CI, che nascondequelle informazioni dall'uso quotidiano, a meno che tu non abbia diritti di amministratore / abbia violato il server git privato.
Uber [recentemente capito nel modo più duro] (https://arstechnica.com/information-technology/2015/03/in-major-goof-uber-stored-sensitive-database-key-on-public-github-page/) che questa è una cattiva idea.
Perché gli sviluppatori dovrebbero anche * conoscere * le password per qualsiasi ambiente oltre a dev / test?
@DaveCarruthers Molte configurazioni utilizzano invece variabili di ambiente.Vengono compilati manualmente (ad es. Per il lavoro di sviluppo) o da un valore crittografato (ad es. [Travis CI] (https://docs.travis-ci.com/user/encryption-keys/)) o tramite undatabase crittografato (es. [HashiCorp Vault] (https://www.hashicorp.com/products/vault)) o tramite un servizio sicuro (es. Heroku).L'idea è di ridurre la superficie di attacco a una singola chiave memorizzata in un daemon (come Vault) o in un servizio (come Heroku o Travis).
A questo punto ho pensato che fosse ampiamente apprezzato il fatto che solo le password _hashed_ (magari con "salt", ecc.) Debbano essere memorizzate ovunque ...?
Otto risposte:
#1
+142
d33tah
2018-08-15 16:09:37 UTC
view on stackexchange narkive permalink

Per come la vedo io, non memorizzare le password in Git (o in altri controlli di versione) è una convenzione . Suppongo che si possa decidere di non applicarlo con vari risultati, ma ecco perché questo è generalmente disapprovato:

  1. Git rende doloroso rimuovere le password dalla cronologia del codice sorgente, il che potrebbe dare alle persone un falso idea che la password fosse già stata rimossa nella versione corrente.
  2. Mettendo la password nel controllo del codice sorgente, in pratica decidi di condividere la password con chiunque abbia accesso al repository, inclusi gli utenti futuri. Ciò complica la definizione dei ruoli all'interno di un team di sviluppatori, che potrebbe avere privilegi diversi.
  3. Il software di controllo del codice sorgente tende a diventare piuttosto complicato, specialmente i sistemi "all-in-one". Ciò significa che esiste il rischio che questo sistema possa eventualmente essere compromesso, con conseguente perdita di password.
  4. Altri sviluppatori potrebbero non essere a conoscenza del fatto che la password è archiviata e potrebbero gestire in modo errato il repository: avere le chiavi nel sorgente significa prestare particolare attenzione dovrebbe essere preso quando si condivide il codice (anche all'interno dell'azienda; questo potrebbe creare la necessità di canali crittografati).

Non posso dire che ogni modello relativo a infosec sia buono, ma prima di romperli è sempre una buona idea considerare il modello di minaccia e i vettori di attacco. Se questa particolare password venisse divulgata, quanto sarebbe difficile per un utente malintenzionato utilizzarla per danneggiare l'azienda?

Non sono sicuro che sia giusto chiamare un noto anti-pattern di "password brevi" una "convenzione infosec".
@Adonalsium Quello che volevo dire è che si tratta di un modello relativo a infosec che non rientra nelle migliori pratiche e non si dovrebbero seguire senza pensare i modelli di altre persone.
È una cosa giusta.
Sono con @Adonalsium: la convenzione non riesce a portare il tuo significato e sono disponibili termini molto migliori: pessima idea.inutilmente rischioso.eccetera
Inoltre, e in misura minore, viene esposta la * cronologia * della password.Se la password è stata modificata nel tempo, conoscere le password precedenti può essere utile per indovinare le password future in caso di revoca dell'accesso.
Intendo per "cose che fanno altre persone" lavori di convenzione, ma può anche significare "cose che altre persone (informate) pensano sia una buona idea ed è un luogo comune per una ragione".
"Convenzione", per me, implica "tutti generalmente sono d'accordo a farlo in questo modo, nonostante non abbia alcun vantaggio particolarmente significativo, tranne che tutti concordano che deve essere fatto in questo modo", ma stai dando alcunivantaggi, che tende maggiormente a "questa è una cattiva idea".Rimuovere le parti sulla convenzione migliorerebbe un po 'la risposta IMO.
Si noti che quando si rimuovono le password dal controllo del codice sorgente, non è necessario eliminarle dalla cronologia: è sufficiente modificare le password.
@OrangeDog a meno che la cronologia delle password non sia un buon indicatore per le password future (che non è vero se le tue password sono sicure e casuali, ma non è sempre così).
Oltre all'elemento 4, git è un sistema di repo distribuito.Chiunque possa clonare il repository su, ad esempio, un laptop di sviluppo potrebbe perdere quel laptop e ora le password fanno parte di quella violazione dei dati.
@NotThatGuy No, convenzione significa semplicemente "tutti generalmente accettano di farlo in questo modo".È importante notare, perché seguire le convenzioni è generalmente molto importante e prezioso di per sé.
Inoltre, potrebbero esserci dipendenti che occasionalmente lavorano da casa.Alcuni di questi (e ne ho conosciuti alcuni) utilizzano il PC di casa per lo sviluppo, invece del laptop aziendale.Ciò significa fare affidamento sulla sicurezza del PC di casa anziché di quella dell'azienda.
Aggiungerei che in molti ambienti, agli sviluppatori non è consentito l'accesso ai sistemi di produzione e gli operatori / amministratori dovranno mantenere tutte le password.Poiché le password scadono tra 45/60/90/180 giorni su molti sistemi, gli sviluppatori ** non possono ** mantenere le password e non vuoi che gli operatori debbano entrare nel codice, quindi metti tutte le credenziali in una configurazione separatae quando gli operatori distribuiscono la build, inseriscono le password di produzione correnti nel file di configurazione e aggiornano quel file quando le password scadono.È possibile che gli sviluppatori che non conoscono le password di produzione siano legalmente obbligatori sui sistemi federali.
Concordo sul fatto che chiamare questa convenzione sia inaccurato e fuorviante.Le convenzioni sono solo usanze, o "norme sociali" in cui potresti farlo in modo completamente diverso e andrebbe bene finché tutti gli altri lo facessero in quel modo.L'esempio classico è su quale lato della strada guidiamo.Siamo tutti d'accordo su quale lato e lo seguiamo.Ma sinistra / destra è arbitraria e funzionerebbe (e funziona) ugualmente bene indipendentemente dalla società scelta.Non è questo il caso qui.Se tutti mettessero le password nel controllo della versione, sarebbe comunque un male.
#2
+93
Brandon
2018-08-15 18:57:11 UTC
view on stackexchange narkive permalink

Primo, il motivo non relativo alla sicurezza:

Flusso di lavoro per la modifica della password

Le password cambiano indipendentemente dal codice dell'applicazione software. Se un DBA cambia una password del database, ha senso che gli sviluppatori debbano aggiornare il codice, ottenere una nuova build e rilasciarlo in produzione e provare a cronometrare tutto? Le password sono un artefatto di configurazione del runtime, non un artefatto di sviluppo. Devono essere iniettati tramite file di configurazione, variabili di ambiente o qualsiasi paradigma di configurazione in uso.

Ambito di autorizzazione

In genere, i sistemi di controllo della versione forniscono il controllo delle autorizzazioni quindi solo gli utenti autorizzati possono accedervi. Ma all'interno di un repository, le autorizzazioni sono generalmente di lettura / scrittura o di sola lettura, o forse alcuni campanelli e fischietti come GitHub fornisce. È improbabile trovare vincoli di sicurezza che consentano agli sviluppatori di ottenere il codice sorgente, ma non le password. Se puoi clonare un repo, puoi clonare un repo. Periodo. In molti ambienti, gli sviluppatori non hanno pieno accesso alla produzione. A volte hanno accesso in sola lettura ai database di produzione, a volte nessun accesso. E se gli sviluppatori in genere hanno accesso, ma non vuoi che tutti gli stagisti, i nuovi assunti, ecc. Abbiano accesso?

Ambienti

E se disponi di più ambienti, come un ambiente di sviluppo, un ambiente di controllo qualità, una gestione temporanea e una produzione? Conserveresti tutte le loro password nel controllo della versione? Come farebbe l'app a sapere quale usare? L'app dovrebbe avere un modo per conoscere l'ambiente, che finirebbe per essere un'impostazione di configurazione. Se puoi rendere il nome ambiente un'impostazione di configurazione, puoi rendere la password del database un'impostazione di configurazione (insieme alla stringa di connessione, al nome utente, ecc.)

Cronologia

Come altri hanno già detto, il controllo della versione è progettato per preservare la cronologia. Quindi le password più vecchie saranno ancora recuperabili, il che potrebbe non essere la cosa migliore.

Quante volte abbiamo visto i titoli delle notizie sul codice sorgente di alcuni prodotti trapelati nel mondo? Il codice sorgente è tutto ciò che è nel controllo della versione. Questo è probabilmente il motivo principale per non mettere le password nel controllo della versione!

Tuttavia ...

Detto questo, le password devono essere memorizzate da qualche parte . Ciò a cui alludono le preoccupazioni di cui sopra non è necessariamente che non dovrebbero essere archiviate affatto nel controllo della versione, piuttosto che non dovrebbero essere archiviate nel repository del codice sorgente del prodotto nel controllo della versione. Avere un repository separato per la gestione della configurazione, le operazioni, ecc. È molto ragionevole. La chiave è separare le operazioni dallo sviluppo quando si tratta di credenziali di sicurezza, non necessariamente per evitare del tutto il controllo della versione.

Inoltre, per gli ambienti non di produzione, ho memorizzato password e chiavi API per sistemi esterni in file di configurazione all'interno del codice sorgente del prodotto come predefiniti. Perché? Per rendere indolore quando uno sviluppatore controlla il codice, può semplicemente crearlo ed eseguirlo e non è necessario andare a prendere file di configurazione aggiuntivi. Queste sono credenziali che cambiano raramente e non portano a segreti commerciali. Ma non lo farei mai con i segreti di produzione.

Quindi il risultato finale è ... dipende.

Il tuo primo punto è più grande di quanto sembri: avere password legate al controllo delle versioni del codice sorgente può rendere impossibile trovare in modo affidabile con git-bisect quando i bug hanno avuto origine, per esempio.
@TobySpeight Dobbiamo avere definizioni molto diverse di "impossibile".In un ambiente di sviluppo sarebbe piuttosto strano cambiare le password comunque - dopotutto per definizione non sono un segreto - quindi raramente c'è un motivo per cambiarle.E se c'è, dovrebbe essere banale sostituire i vecchi file di configurazione con quelli nuovi come parte del tuo script bisect.Voglio dire che questa è di gran lunga la parte più semplice dello script che deve costruire l'intero progetto e poi ospitarlo.
+1 per aver suggerito un repository separato con un accesso più granulare.
#3
+25
Conor Mancone
2018-08-15 17:28:41 UTC
view on stackexchange narkive permalink

È sempre importante tenere presente che i suggerimenti devono essere personalizzati per adattarsi al tuo caso d'uso. Le misure di sicurezza adottate, ad esempio, dalla NSA per proteggere tutti gli zero-giorni che tengono in giro per un giorno di pioggia dovrebbero essere molto più rigorose delle misure di sicurezza adottate per proteggere i voti positivi su un sito di pubblicazione di immagini di gatti. Ad un estremo, posso pensare a un esempio in cui mantenere password / token / ecc. In un repository git privato potrebbe essere ragionevole:

Se a quel repository si accede solo una persona e l'applicazione non ne memorizza informazioni di qualsiasi valore.

In tal caso, vai in città! Tieni a mente quello che ha detto @ d33tah nella sua risposta: pulire le cose da un repository git può essere sorprendentemente difficile (il punto, dopotutto, è mantenere una cronologia di tutto per sempre) quindi se lungo la strada decidi di collaborare con più persone ma non vuoi che abbiano pieno accesso a tutti i tuoi sistemi, allora avrai un po 'di mal di testa tra le mani.

Questo è ciò che realmente si riduce per. Il tuo repository di codice è in qualche modo "pubblico", anche se condiviso solo con i collaboratori. Solo perché vuoi collaborare con qualcuno non significa che vuoi dare loro pieno accesso alla tua infrastruttura (che è effettivamente ciò che accade quando metti password / token nel tuo repository di codice). È facile pensare "sì, ma mi fido delle persone con cui collaboro!", Ma questo è semplicemente il modo sbagliato di guardare lo scenario, per una serie di motivi:

  1. Nella pratica, gran parte delle fughe di dati inizia con attori interni (collaboratori, dipendenti). Secondo uno studio, circa il 43% delle violazioni dei dati è iniziata con un attore interno. Metà di questi erano intenzionali e metà accidentali.
  2. Quest'ultimo punto è importante e spiega perché non si tratta solo di fiducia. Circa il 20% delle violazioni dei dati è accidentale e causato da persone interne. Sono abbastanza intelligente da sapere che non sono abbastanza intelligente da fare sempre tutto bene. E se rendo pubblico il mio repository per fare spazio a qualche divertente strumento di integrazione e dimentico di avere le credenziali al suo interno? Cosa succede se ho un disco rigido di backup che ho dimenticato di crittografare e esce dal mio ufficio? Cosa succede se una delle mie password viene trapelata e qualcuno la usa per indovinare la password dell'account nel mio repository git ( cough gentoo github repository cough )? Ci sono un certo numero di errori accidentali che io posso fare che potrebbero comportare l'esposizione del mio repository git e, se ciò accade e ho le credenziali lì e la persona che li trova sa cosa stanno guardando, potrei benissimo essere inghiottito. Sembra un sacco di e ma la realtà è che è così che avvengono le violazioni.
  3. Anche se mi fido di qualcuno, ciò non significa che devo dare loro pieno accesso a tutto [inserire una citazione banale su come il potere corrompe]. Ancora una volta, l'inserimento delle credenziali in un repository git significa che sto potenzialmente dando pieno accesso a tutta la mia infrastruttura a tutti i miei collaboratori. C'è sempre la possibilità che tu non conosca quella persona così come pensi, e potrebbe decidere di fare qualcosa che non dovrebbe. Anche se conosci personalmente e ti fidi di ognuno dei tuoi collaboratori con la tua vita, ciò non significa che non faranno alcuni degli errori di cui sopra (o nessuna delle infinite opzioni che non ho menzionato) per rilasciare accidentalmente il tuo codice.

In breve, una buona sicurezza consiste nell'avere difese a più livelli. La maggior parte degli hack avviene perché gli hacker trovano punti deboli in un'area che consente loro di sfruttare i punti deboli in un'altra area, il che porta da qualche altra parte, il che alla fine li porta al grande vantaggio. Disporre di tutte le protezioni di sicurezza che ha senso per la tua situazione è ciò che mantiene il tutto al sicuro. In questo modo, quando un disco rigido di backup esce dal tuo ufficio e ti rendi conto che non era crittografato, non devi chiedere "Era un attacco mirato e ora devo cambiare ogni singola credenziale che ho ovunque perché erano tutti nel repository git su quell'unità di backup? ". Ancora una volta, a seconda della tua situazione questo potrebbe non essere applicabile a te, ma si spera che questo aiuti a spiegare in quali scenari potrebbe essere importante.

+1 per "... ecco come avvengono le violazioni".La vita è caoticamente casuale ed è assolutamente sorprendente quante volte una lunga serie di atti apparentemente casuali possa colludere insieme per formare l'incidente perfetto (brecce, incendi, collisioni di veicoli).Mantenere la password fuori dal repository elimina la possibilità che una violazione esponga la password.
#4
+13
user1763251
2018-08-16 05:31:35 UTC
view on stackexchange narkive permalink

Tenere i segreti (password, certificati, chiavi) separati dal codice sorgente rende possibile gestire sorgenti e segreti in base a diverse politiche. Ad esempio, tutti gli ingegneri possono leggere il codice sorgente, solo le persone che sono direttamente responsabili dei server di produzione possono accedere ai segreti.

Ciò semplifica la vita agli sviluppatori perché non sono vincolati dalle rigide politiche di sicurezza che sono necessari per proteggere i segreti. Le politiche di controllo del codice sorgente possono essere rese molto più convenienti per loro.

In qualità di persona direttamente responsabile dei server di produzione, posso dirti che in nessuna circostanza desidero che gli sviluppatori dispongano di credenziali per il QA o per l'ambiente di produzione.Se li hanno, allora "risolveranno" un problema modificando le cose fino a quando non inizieranno a funzionare, non documenteranno le loro modifiche, e l'intera cosa andrà in pezzi perché il rapporto tra Wolfsbane e Eye of Newt è spento.Fai quello che vuoi nel tuo ambiente Dev, ma dammi un pacchetto di codice pulito da distribuire, con la documentazione di ciò che devo fare per farlo funzionare, e l'unico accesso che potrei concederti è di sola lettura ai log.
@MontyHarder Ciò è sicuramente dovuto alla tensione tra l'obiettivo operativo di "non rompere e non perdere" e l'obiettivo dello sviluppo "aggiustare le cose ora".
@WayneWerner Non è solo "non rompere e non perdere", è "assicurati di poterlo replicare in modo affidabile".La separazione dei ruoli tra dev e ops li costringe a comunicare in modo esplicito le dipendenze in modo da poter eseguire una replica affidabile.Risolvilo ora in dev, documentami cosa hai fatto per risolverlo in modo che io possa aggiustarlo in QA e, se non ha funzionato, non l'hai documentato abbastanza bene.Riprova.
#5
+12
Tom
2018-08-16 12:55:13 UTC
view on stackexchange narkive permalink

Questa convenzione, come molte altre "best practice" sulla sicurezza, è un modo pratico per assicurarsi che le cose non vadano storte a causa di cattive abitudini o routine.

Se ti ricordi sempre che le tue password sensibili sono nel tuo sistema di controllo delle versioni e se non dai mai a nessuno che non dovrebbe avere la password di accedere al repository e se il tuo repository è memorizzato con la massima sicurezza richiesta da questi segreti e se il tuo processo di distribuzione è allo stesso modo sicuro, protetto e protetto da persone non autorizzate e se puoi essere certo che tutti i backup e le copie del tuo repository sono e ... probabilmente puoi aggiungere un altro paio di "if" specifici per il tuo contesto.

... allora puoi ben memorizzare le tue password nel tuo sistema di controllo della versione.

Nella maggior parte dei casi, almeno uno di questi "se" non è sufficientemente conforme alle tue condizioni o è fuori dal tuo controllo.

Ad esempio, in molte impostazioni i tuoi sviluppatori non dovrebbero avere accesso al database di produzione. Oppure il sistema di backup viene esternalizzato a un altro reparto. Oppure il tuo processo di compilazione è esternalizzato al cloud.

Ecco perché in generale , non memorizzare le tue password nel tuo sistema di controllo della versione è una best practice che ti assicura di non cadere in una di quelle trappole perché non ci hai pensato. "nessuna password in git" è più facile da ricordare di un lungo elenco di condizioni che è necessario soddisfare per archiviare in modo sicuro le password sotto il controllo della versione.

#6
+6
Ben
2018-08-16 20:38:49 UTC
view on stackexchange narkive permalink

Altre risposte sono ottime, ma considera anche il problema dei backup. Hai molta più flessibilità su dove, come e per quanto tempo conservi i backup del tuo repository di codice se non contengono informazioni sensibili su come accedere al tuo server o agli account amministratore.

Da un altro più sicurezza- angolo mirato, solo il backup del codice potrebbe essere un obiettivo interessante per i concorrenti non etici nella tua azienda. A seconda della tua attività, la maggior parte dei concorrenti in un paese di "stato di diritto" non la toccherebbe comunque. Un backup del codice con password sarà un obiettivo per qualsiasi organizzazione criminale interessata ai dati dei tuoi utenti o interessata a ricattare la tua azienda.

Il danno da una violazione del repository di codice sarebbe maggiore con le password per motivi simili. Preferiresti che il tuo codice sorgente venisse rubato e pubblicato o che tutti i tuoi utenti fossero esposti a furti di identità, con una potenziale causa legale o addirittura un procedimento penale contro di te per non aver protetto i loro dati privati ​​(pensa al GDPR)?

#7
+2
Santiago Blanco
2018-08-18 12:29:01 UTC
view on stackexchange narkive permalink

"perché è davvero così brutto mettere le chiavi direttamente nella porta principale, quando viviamo lontano dalla civiltà?"

Perché le persone che vogliono fare cose cattive, lo faranno facilmente e il il costo del duro lavoro per loro non è troppo alto. Tieni le chiavi con te non vicino alla porta. Buon senso.

Repo privato? Quante persone hanno accesso per scaricarlo? E quante persone sono collegate ai suoi computer? E poi ... Sono tutti esenti da pericoli?

Per estendere la metafora: facciamo una copia delle chiavi della porta dell'ufficio per ogni dipendente o semplicemente le distribuiamo in base alle necessità?
#8
  0
gnasher729
2018-08-19 16:34:11 UTC
view on stackexchange narkive permalink

Dipende anche dal sistema di controllo del codice sorgente.

Git ha l'attitudine che il sistema di controllo del codice sorgente dovrebbe darti una cronologia affidabile del progetto. Che non è un cattivo atteggiamento da avere. Ma c'è l'effetto che se hai controllato una password in git, è molto difficile rimuoverla dal tuo repository.

Perforce ha un comando "cancella" per quello scopo. Se hai registrato una password, o qualcuno ha archiviato un file video non compresso da 8 gigabyte, o qualcuno ha registrato un codice di terze parti che viola il copyright di qualcuno e non avrebbe mai dovuto essere registrato, o qualcuno che è stato licenziato ha registrato un sacco di porno su il loro ultimo giorno di lavoro, puoi "cancellarlo". È completamente sparito dal repository e dalla cronologia.

facile possibile rimuovere le password dalla cronologia di Git] (http://www.davidverhasselt.com/git-how-to-remove-your-password-from-a-repository/) e [riscrivi la cronologia a tuo piacimento] (https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 4.0 con cui è distribuito.
Loading...