Grundlæggende om Java-sikkerhed

Java Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

I denne vejledning gennemgår vi det grundlæggende i sikkerhed på Java-platformen. Vi vil også fokusere på, hvad der er tilgængeligt for os til at skrive sikre applikationer.

Sikkerhed er et stort emne, der omfatter mange områder. Nogle af disse er en del af selve sproget, som adgangsmodifikatorer og klasselæssere. Desuden er andre tilgængelige som tjenester, der inkluderer datakryptering, sikker kommunikation, godkendelse og autorisation, til et par få navn.

Derfor er det ikke praktisk at få meningsfuld indsigt i alle disse i denne vejledning. Vi vil dog forsøge at få mindst et meningsfuldt ordforråd.

2. Sprogfunktioner

Først og fremmest, sikkerhed i Java begynder lige på niveau med sprogfunktioner. Dette giver os mulighed for at skrive sikker kode samt drage fordel af mange implicitte sikkerhedsfunktioner:

  • Statisk datatypning: Java er et statisk skrevet sprog, hvilket reducerer mulighederne for påvisning af kørselstid af type-relaterede fejl
  • Adgangsmodifikatorer: Java giver os mulighed for at bruge forskellige adgangsmodifikatorer som offentlige og private for at kontrollere adgang til felter, metoder og klasser
  • Automatisk hukommelsesstyring: Java har affaldsindsamlingsbaseret hukommelsesstyring, som frigør udviklere fra at administrere dette manuelt
  • Bytecode-verifikation: Java er et kompileret sprog, hvilket betyder, at det konverterer kode til platform-agnostisk bytecode, og runtime verificerer hver bytekode, den indlæses til udførelse

Dette er ikke en komplet liste over sikkerhedsfunktioner, som Java giver, men det er godt nok til at give os en vis sikkerhed!

3. Sikkerhedsarkitektur i Java

Før vi begynder at udforske specifikke områder, lad os bruge lidt tid på at forstå kernearkitekturen i sikkerhed i Java.

Kerneprincipperne for sikkerhed i Java er drevet af interoperabelt og udvideligt Udbyder implementeringer. En særlig implementering af Udbyder kan implementere nogle eller alle sikkerhedstjenesterne.

For eksempel er nogle af de typiske tjenester a Udbyder kan implementere er:

  • Kryptografiske algoritmer (såsom DSA, RSA eller SHA-256)
  • Nøglegenerering, konvertering og styringsfaciliteter (f.eks. Til algoritmespecifikke nøgler)

Java leveres med mange indbyggede udbydere. Det er også muligt for en applikation at konfigurere flere udbydere med en rækkefølge.

Derfor udbyderrammen i Java søger efter en specifik implementering af en tjeneste i alle udbydere i den rækkefølge, du foretrækker sæt dem på.

Desuden er det altid muligt at implementere brugerdefinerede udbydere med tilslutbare sikkerhedsfunktioner i denne arkitektur.

4. Kryptografi

Kryptografi er hjørnestenen i sikkerhedsfunktioner generelt og i Java. Dette refererer til værktøjer og teknikker til sikker kommunikation i nærværelse af modstandere.

4.1. Java-kryptografi

Java Cryptographic Architecture (JCA) giver en ramme for adgang til og implementering af kryptografiske funktioner i Java, herunder:

  • Digitale signaturer
  • Besked fordøjes
  • Symmetriske og asymmetriske cifre
  • Beskedgodkendelseskoder
  • Nøglegeneratorer og nøglefabrikker

Vigtigst er det, at Java gør brug af Udbyder-baserede implementeringer til kryptografiske funktioner.

Desuden inkluderer Java indbyggede udbydere til almindeligt anvendte kryptografiske algoritmer som RSA, DSA og AES, for at nævne nogle få. Vi kan Brug disse algoritmer til at tilføje sikkerhed til data i hvile, i brug eller i bevægelse.

4.2. Kryptografi i praksis

En meget almindelig anvendelse i applikationer er at gemme brugeradgangskoder. Vi bruger dette til godkendelse på et senere tidspunkt. Nu er det indlysende, at opbevaring af almindelig tekstadgangskoder kompromitterer sikkerheden.

Så en løsning er at kryptere adgangskoder på en sådan måde, at processen kan gentages, men alligevel kun envejs. Denne proces er kendt som den kryptografiske hash-funktion, og SHA1 er en sådan populær algoritme.

Så lad os se, hvordan vi kan gøre dette i Java:

MessageDigest md = MessageDigest.getInstance ("SHA-1"); byte [] hashedPassword = md.digest ("password" .getBytes ());

Her, MessageDigest er en kryptografisk tjeneste, som vi er interesserede i. Vi er ved hjælp af metoden getInstance() at anmode om denne service fra en af ​​de tilgængelige sikkerhedsudbydere.

5. Offentlig nøgleinfrastruktur

Public Key Infrastructure (PKI) henviser til opsætning, der muliggør sikker udveksling af oplysninger over netværket ved hjælp af kryptering med offentlig nøgle. Denne opsætning er afhængig af tillid, der er opbygget mellem de parter, der er involveret i kommunikationen. Denne tillid er baseret på digitale certifikater udstedt af en neutral og betroet myndighed kendt som en Certificate Authority (CA).

5.1. PKI-support i Java

Java-platformen har API'er, der letter oprettelse, lagring og validering af digitale certifikater:

  • KeyStore: Java leverer KeyStore klasse til vedvarende lagring af kryptografiske nøgler og pålidelige certifikater. Her, KeyStore kan repræsentere både key-store og trust-store filer. Disse filer har lignende indhold, men varierer i deres brug.
  • CertStore: Derudover har Java CertStore klasse, der repræsenterer et offentligt lager med potentielt utroede certifikater og tilbagekaldelseslister. Vi er nødt til at hente certifikater og tilbagekaldelseslister til bygning af certifikatsti blandt andre anvendelser.

Java har en indbygget tillidsbutik kaldet “cacerts” der indeholder certifikater til velkendte CA'er.

5.2. Java-værktøjer til PKI

Java har nogle virkelig nyttige værktøjer til at lette pålidelig kommunikation:

  • Der er et indbygget værktøj kaldet “keytool” til at oprette og administrere key-store og trust-store
  • Der er også et andet værktøj "jarsigner", som vi kan bruge til at underskrive og verificere JAR-filer

5.3. Arbejde med certifikater i Java

Lad os se, hvordan vi kan arbejde med certifikater i Java for at etablere en sikker forbindelse ved hjælp af SSL. En gensidigt godkendt SSL-forbindelse kræver, at vi gør to ting:

  • Nuværende certifikat - Vi skal præsentere et gyldigt certifikat til en anden part i kommunikationen. Til det er vi nødt til at indlæse nøglelagerfilen, hvor vi skal have vores offentlige nøgler:
KeyStore keyStore = KeyStore.getInstance (KeyStore.getDefaultType ()); char [] keyStorePassword = "changeit" .toCharArray (); prøv (InputStream keyStoreData = ny FileInputStream ("keystore.jks")) {keyStore.load (keyStoreData, keyStorePassword); }
  • Bekræft certifikat - Vi skal også bekræfte certifikatet, der præsenteres af en anden part i kommunikationen. Til dette er vi nødt til at indlæse tillidsbutikken, hvor vi tidligere skal have tillid til certifikater fra andre parter:
KeyStore trustStore = KeyStore.getInstance (KeyStore.getDefaultType ()); // Indlæs trust-store fra filsystemet som før

Vi er sjældent nødt til at gøre dette programmatisk og normalt videregive systemparametre til Java under kørsel:

-Djavax.net.ssl.trustStore = truststore.jks -Djavax.net.ssl.keyStore = keystore.jks

6. Godkendelse

Godkendelse er proces til verificering af den præsenterede identitet for en bruger eller maskine baseret på yderligere data som adgangskode, token eller en række andre legitimationsoplysninger, der er tilgængelige i dag.

6.1. Godkendelse i Java

Java API'er bruger plugbare login-moduler til at give forskellige og ofte flere godkendelsesmekanismer til applikationer. LoginContext giver denne abstraktion, som igen henviser til konfiguration og indlæser en passende LoginModul.

Mens flere udbydere stiller deres login-moduler til rådighed, Java har nogle standard tilgængelige til brug:

  • Krb5LoginModuletil Kerberos-baseret godkendelse
  • JndiLoginModule, til brugernavn og adgangskodebaseret godkendelse bakket op af en LDAP-butik
  • KeyStoreLoginModule, til kryptografisk nøglebaseret godkendelse

6.2. Login ved eksempel

En af de mest almindelige mekanismer til godkendelse er brugernavnet og adgangskoden. Lad os se, hvordan vi kan opnå dette igennem JndiLoginModule.

Dette modul er ansvarlig for at hente brugernavnet og adgangskoden fra en bruger og kontrollere det mod en bibliotektjeneste konfigureret i JNDI:

LoginContext loginContext = ny LoginContext ("Sample", ny SampleCallbackHandler ()); loginContext.login ();

Her er vi ved hjælp af en forekomst af LoginContext for at udføre login. LoginContext tager navnet på en post i login-konfigurationen - i dette tilfælde er det “Sample”. Vi er også nødt til at give en forekomst af CallbackHandler, bruger LoginModul der interagerer med brugeren for detaljer som brugernavn og adgangskode.

Lad os se på vores login-konfiguration:

Eksempel på {com.sun.security.auth.module.JndiLoginModule krævet; };

Enkelt nok antyder det, at vi bruger JndiLoginModule som obligatorisk LoginModul.

7. Sikker kommunikation

Kommunikation over netværket er sårbar over for mange angrebsvektorer. For eksempel kan nogen trykke på netværket og læse vores datapakker, når de overføres. I årenes løb har branchen etableret mange protokoller for at sikre denne kommunikation.

7.1. Java-support til sikker kommunikation

Java leverer API'er til sikker netværkskommunikation med kryptering, beskedintegritet og både klient- og servergodkendelse:

  • SSL / TLS: SSL og dens efterfølger, TLS, giver sikkerhed over utroværdig netværkskommunikation gennem datakryptering og offentlig nøgleinfrastruktur. Java understøtter SSL / TLS igennem SSLSocket defineret i pakken “java.security.ssl“.
  • SASL: Simple Authentication and Security Layer (SASL) er en standard til godkendelse mellem klient og server. Java understøtter SASL som en del af pakken “java.security.sasl“.
  • GGS-API / Kerberos: Generic Security Service API (GSS-API) tilbyder ensartet adgang til sikkerhedstjenester over en række sikkerhedsmekanismer som Kerberos v5. Java understøtter GSS-API som en del af pakken “java.security.jgss“.

7.2. SSL-kommunikation i aktion

Lad os nu se, hvordan vi kan åbne en sikker forbindelse med andre parter i Java ved hjælp af SSLSocket:

SocketFactory fabrik = SSLSocketFactory.getDefault (); prøv (Socket forbindelse = fabrik.createSocket (vært, port)) {BufferedReader input = ny BufferedReader (ny InputStreamReader (forbindelse.getInputStream ())); returner input.readLine (); }

Her bruger vi SSLSocketFactory at skabe SSLSocket. Som en del af dette kan vi indstille valgfri parametre som krypteringssuiter og hvilken protokol der skal bruges.

For at dette kan fungere ordentligt, vi skal have oprettet og indstillet vores nøglelager og tillidsbutik som vi så tidligere.

8. Adgangskontrol

Adgangskontrol refererer til beskytte følsomme ressourcer som et filsystem eller kodebase fra uberettiget adgang. Dette opnås typisk ved at begrænse adgangen til sådanne ressourcer.

8.1. Adgangskontrol i Java

Vi kan opnå adgangskontrol i Java ved hjælp af klasser Politik og Tilladelse formidlet gennem SecurityManager klasse. SecurityManager er en del af “java.lang”-Pakke og er ansvarlig for håndhævelse af adgangskontrolchecks i Java.

Når klasselæsseren indlæser en klasse i løbetiden, giver den automatisk nogle standardtilladelser til klassen indkapslet i Tilladelse objekt. Ud over disse standardtilladelser kan vi give mere klasse til en klasse gennem sikkerhedspolitikker. Disse er repræsenteret af klassen Politik.

Hvis runtime støder på en anmodning om en beskyttet ressource under sekvensen af ​​kodeudførelse, SecurityManager bekræfter det anmodede Tilladelse mod det installerede Politik gennem opkaldstakken. Derfor giver den enten tilladelse eller kaster Sikkerhedsundtagelse.

8.2. Java-værktøjer til politik

Java har en standardimplementering af Politik der læser autorisationsdata fra egenskabsfilen. Politikposterne i disse politikfiler skal dog være i et specifikt format.

Java leveres med "policytool", et grafisk værktøj til at komponere politikfiler.

8.3. Adgangskontrol gennem eksempel

Lad os se, hvordan vi kan begrænse adgangen til en ressource som en fil i Java:

SecurityManager securityManager = System.getSecurityManager (); hvis (securityManager! = null) {securityManager.checkPermission (ny FilePermission ("/ var / logs", "read")); }

Her bruger vi SecurityManager for at validere vores læseanmodning om en fil, pakket ind FilePermission.

Men, SecurityManager delegerer denne anmodning til AccessController. AccessController bruger internt det installerede internt Politik at nå frem til en beslutning.

Lad os se et eksempel på politikfilen:

give {tilladelse java.security.FilePermission <>, "læs"; };

Vi giver i det væsentlige læsetilladelse til alle filer for alle. Men, vi kan levere meget mere finkornet kontrol gennem sikkerhedspolitikker.

Det er værd at bemærke, at en SecurityManager er muligvis ikke installeret som standard i Java. Vi kan sikre dette ved altid at starte Java med parameteren:

-Djava.security.manager -Djava.security.policy = / sti / til / sample.policy

9. XML-signatur

XML-signaturer er nyttigt til sikring af data og tilvejebringelse af dataintegritet. W3C giver anbefalinger til styring af XML-signatur. Vi kan bruge XML-signatur til at sikre data af enhver type, såsom binære data.

9.1. XML-signatur i Java

Java API understøtter generering og validering af XML-signaturer i henhold til de anbefalede retningslinjer. Java XML Digital Signature API er indkapslet i pakken “java.xml.crypto“.

Selve signaturen er kun et XML-dokument. XML-signaturer kan være af tre typer:

  • Uafhængig: Denne type signatur er over de data, der er eksterne for Signatur-elementet
  • Konvolut: Denne type signatur går ud over de data, der er interne i Signatur-elementet
  • Indhyllet: Denne type signatur er over de data, der indeholder selve Signatur-elementet

Bestemt understøtter Java oprettelse og verificering af alle ovennævnte typer XML-signaturer.

9.2. Oprettelse af en XML-signatur

Nu bretter vi ærmerne op og genererer en XML-signatur til vores data. For eksempel kan vi være ved at sende et XML-dokument over netværket. Derfor, Vi ønsker, at vores modtager skal kunne verificere dens integritet.

Så lad os se, hvordan vi kan opnå dette i Java:

XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance ("DOM"); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance (); documentBuilderFactory.setNamespaceAware (true); Dokumentdokument = documentBuilderFactory .newDocumentBuilder (). Parse (nyt FileInputStream ("data.xml")); DOMSignContext domSignContext = ny DOMSignContext (keyEntry.getPrivateKey (), document.getDocumentElement ()); XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature (signeret Info, keyInfo); xmlSignature.sign (domSignContext);

For at afklare genererer vi en XML-signatur til vores data, der er til stede i filen “Data.xml”. I mellemtiden er der et par ting at bemærke om dette stykke kode:

  • For det første, XMLSignatureFactory er fabriksklassen til generering af XML-signaturer
  • XMLSigntaure kræver en SignedInfo objekt, som det beregner signaturen over
  • XMLSigntaure også behov KeyInfo, som indkapsler signaturnøglen og certifikatet
  • Langt om længe, XML-signatur underskriver dokumentet ved hjælp af den private nøgle indkapslet som DOMSignContext

Som resultat, XML-dokumentet indeholder nu signaturelementet, som kan bruges til at kontrollere dets integritet.

10. Sikkerhed ud over Core Java

Som vi har set nu, giver Java-platformen meget af den nødvendige funktionalitet til at skrive sikre applikationer. Imidlertid er disse nogle gange ret lave og gælder ikke direkte for f.eks. Standardsikkerhedsmekanismen på nettet.

For eksempel når du arbejder på vores system, vi ønsker generelt ikke at skulle læse den fulde OAuth RFC og implementere det selv. Vi har ofte brug for hurtigere måder på højere niveau for at opnå sikkerhed. Det er her applikationsrammer kommer ind i billedet - disse hjælper os med at nå vores mål med langt mindre kedelpladekode.

Og på Java-platformen - generelt betyder det forårssikkerhed. Rammen er en del af Spring-økosystemet, men den kan faktisk bruges uden for ren Spring-applikation.

Enkelt sagt hjælper det med at opnå godkendelse, autorisation og andre sikkerhedsfunktioner på en enkel, deklarativ måde på højt niveau.

Selvfølgelig er Spring Security omfattende dækket af en række tutorials såvel som på en guidet måde i Learn Spring Security-kurset.

11. Konklusion

Kort sagt, i denne vejledning gik vi igennem den høje sikkerhedsarkitektur i Java. Vi forstod også, hvordan Java giver os implementeringer af nogle af de standard kryptografiske tjenester.

Vi så også nogle af de almindelige mønstre, som vi kan anvende for at opnå udvidelig og tilslutbar sikkerhed i områder som autentificering og adgangskontrol.

For at opsummere giver dette os kun et smugkig ind i Java's sikkerhedsfunktioner. Derfor fortjener hvert af de områder, der er diskuteret i denne vejledning, yderligere udforskning. Men forhåbentlig skulle vi have nok indsigt til at komme i gang i denne retning!

Java bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN