{"id":798,"date":"2011-06-15T13:52:07","date_gmt":"2011-06-15T11:52:07","guid":{"rendered":"http:\/\/www.daniel-ritter.de\/blog\/?p=798"},"modified":"2024-05-13T01:17:21","modified_gmt":"2024-05-12T23:17:21","slug":"10-masnahmen-um-einen-root-lamp-server-abzusichern","status":"publish","type":"post","link":"https:\/\/www.daniel-ritter.de\/blog\/10-masnahmen-um-einen-root-lamp-server-abzusichern\/","title":{"rendered":"12 Ma\u00dfnahmen um einen Linux root LAMP Apache MySQL PHP Webserver abzusichern"},"content":{"rendered":"<p>Die Hacking-Frequenz ist in den letzten Monaten stark angestiegen. Besonders viele Daten werden abgegriffen durch Hacks auf Webserver. Sogar der SONY-PSN-Hack nutzte Schwachstellen in einem ungepatchten Apache-Webserver. Deshalb sammele ich hier Ma\u00dfnahmen, die den eigenen Server etwas sicherer gegen Angriffe von au\u00dfen machen k\u00f6nnen. Nat\u00fcrlich bieten auch diese keinen 100%igen Schutz, aber es ist besser, den b\u00f6sen Buben das Spiel ein wenig schwieriger zu machen. Einige der Ma\u00dfnahmen ben\u00f6tigen nur einen minimalen Installations- und Wartungsaufwand. Andere ben\u00f6tigen viel Zeit und Kenntnisse von PHP um zu greifen. Man sollte immer auf das Kosten-Nutzen-Verh\u00e4ltnis bei der Auswahl der Sicherheitsma\u00dfnahmen achten. Es macht keinen Sinn, eine kleine, private Website so abzusichern wie die Federal Reserve Bank. Allerdings k\u00f6nnen wenige gezielte \u00c4nderungen am System bereits ein gro\u00dfes Mehr an Sicherheit bedeuten. Und das sollte man sich schon g\u00f6nnen, bevor es zu sp\u00e4t ist&#8230;.<\/p>\n<p>Alle Tipps und Codesnips beziehen sich auf eine aktuelle Debian-Kiste.<\/p>\n<p><strong>1. Die Firewall &#8211; erst einmal alles verbieten<\/strong><\/p>\n<p>Die meisten Linux-Distributionen \u00f6ffnen in ihren Standardinstallationen keine Ports nach au\u00dfen, die nicht unbedingt notwendig sind. Diese Situation kann man jedoch schnell selbst \u00e4ndern, wenn man am Server<br \/>\nherumspielt und Dinge ausprobiert. Pl\u00f6tzlich lauscht auch der Mediaserver im Internet oder die Datenbank<br \/>\nnimmt Verbindungen aus dem Internet entgegen. Deshalb ist es nicht verkehrt sich selbst zu disziplinieren und eine sehr restriktive Firewall aufzusetzen, die grunds\u00e4tzlich erst einmal alle Verbindungen von au\u00dfen verbietet und nur (selbst) ausgew\u00e4hlte Verbindungen gestattet. Zum Gl\u00fcck ist das mit iptables schnell erledigt. Auf diese Art und Weise kann man nicht mehr aus versehen Dienste der Welt zug\u00e4nglich machen, die dort nichts zu suchen haben. Man bezahlt leider mit etwas Komfort &#8211; die Firewall muss jedes Mal angepasst werden, wenn man neue Dienste anbieten m\u00f6chte. Trotzdem ist der Aufwand klein und der Nutzen gro\u00df.<\/p>\n<pre>#!\/bin\/bash\r\n# Bestehende Tables l\u00f6schen\r\niptables -F\r\n\r\n# Alle eingehenden Verbindungen verbieten\r\niptables -P INPUT DROP\r\niptables -P FORWARD DROP\r\n\r\n# Alle ausgehenden erlauben\r\niptables -P OUTPUT ACCEPT\r\n\r\n# SSH erlauben\r\niptables -A INPUT -j ACCEPT -p tcp --dport 22\r\n\r\n# HTTP erlauben\r\niptables -A INPUT -j ACCEPT -p tcp --dport 80\r\n\r\n# Weiteren Dienst (UDP) erlauben, zum Beispiel Gameserver\r\niptables -A INPUT -j ACCEPT -p udp --dport 4534\r\n\r\n# Alles von Localhost erlauben. (Damit der Server selbst ungehindert auf seine Dienste zugreifen kann,\r\n# zum Beispiel PHP auf die lokale Datenbank\r\niptables -A INPUT -j ACCEPT -s 127.0.0.1\r\n\r\n# Bereits aufgebaute Verbindungen werden an jedem Port akzeptiert\r\n# (Damit Antworten auf Anfragen, die vom Server kommen immer zur\u00fcckkommen k\u00f6nnen)\r\niptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT\r\n\r\n<\/pre>\n<p>Dieses kleine Grundger\u00fcst kann man einfach weiter ausbauen und eigene Dienste hinzuf\u00fcgen. Bei Arbeiten an der Firewall sollte man immer f\u00fcr den Fall vorsorgen, dass man sich selbst aussperrt. Besonders bei Remote-Servern, auf die man keinen physischen Zugriff hat, ist es sehr \u00e4rgerlich, durch eine mi\u00dfgl\u00fcckte Firewallregel den eigenen Zugriff zu verlieren. Um diesem Problem aus dem Weg zu gehen, kann man bei Arbeiten an der Firewall einfach tempor\u00e4r einen Cronjob starten lassen, der die Firewall alle paar Minuten zur\u00fccksetzt oder den Server neu startet. Sind die Regeln sp\u00e4ter getestet und geliebt, kann der Cronjob wieder deaktiviert werden und die neuen Regeln bleiben permanent aktiv.<\/p>\n<p>Um herauszufinden, welche Dienste gerade auf dem eigenen Server herumlauschen, kann man netstat benutzen:<\/p>\n<pre>#F\u00fcr TCP-Sockets:\r\nnetstat -lpn | grep tcp\r\n\r\n#Analog f\u00fcr UDP:\r\nnetstat -lpn | grep udp\r\n<\/pre>\n<p>Um zu testen ob die Firewall wirklich funktioniert, kann man den eigenen Server von einem anderen Rechner aus portscannen. Hat alles geklappt, sollten im Ergebnis nur die selbst ge\u00f6ffneten Ports auftauchen:<\/p>\n<pre>#F\u00fcr TCP:\r\nnmap -p1-65535 meinserver.de\r\n#F\u00fcr UDP:\r\nnmap -sU -p1-65535 meinserver.de\r\n<\/pre>\n<p><strong>2. SSH Logins verbieten<\/strong><\/p>\n<p>Am eigenen root-Server hat man uneingeschr\u00e4nkten SSH-Zugriff. Das ist recht praktisch, da man von jedem SSH-Client aus mal eben auf den Server kann um an ihm zu arbeiten. Der Nachteil davon ist, dass das nat\u00fcrlich auch jeder andere kann, der ungl\u00fccklicher Weise irgendwie an das eigene Passwort gelangt ist. Es ist viel sicherer SSH-Logins nur mit einer g\u00fcltigen Schl\u00fcsseldatei zu erlauben. Daf\u00fcr wird der \u00f6ffentliche Schl\u00fcssel des Clients auf den Server kopiert und interaktive Logins per Passworteingabe werden deaktiviert.<\/p>\n<pre># Auf dem Client einen \u00f6ffentlichen Schl\u00fcssel erstellen\r\n# Wird bei der Generierung ein Passwort angegeben, ben\u00f6tigt man zum\r\n# einloggen sp\u00e4ter die Schl\u00fcsseldatei UND das Passwort. Ansonsten wird\r\n# nur der Schl\u00fcssel ben\u00f6tigt.\r\n\r\nssh-keygen -t rsa\r\n\r\n# Den erstellten Schl\u00fcssel danach auf den Server kopieren\r\n\r\nssh-copy-id -i ~\/.ssh\/id_rsa.pub root@meinserver.de\r\n\r\n# Danach auf dem Server \/etc\/ssh\/sshd_config anpassen\r\n.\r\n.\r\nPasswordAuthentication no\r\n.\r\n.\r\n\r\n# Danach SSh neu starten\r\n\/etc\/init.d\/ssh restart<\/pre>\n<p>Auch hier sollte man Vorkehrungen treffen, um sich nicht selbst auszusperren, falls etwas nicht funktioniert.<br \/>\nDer Public Key auf einem USB-Stick mit dem dazugeh\u00f6rigen Passwort im eigenen Kopf macht es sehr viel schwerer f\u00fcr b\u00f6se Buben eine Shell zu erhalten.<\/p>\n<p><strong>3. SSH Bruteforcing verhindern mit denyhosts <\/strong><\/p>\n<p>Falls Tipp 2 nicht praktikabel ist und man den Komfort von passwortgest\u00fctzten Logins nicht aufgeben will, kann man zumindest das automatisierte Passwortraten von Angreifern auf dem Server verhindern. Sehr viele Bots im Internet machen den ganzen Tag nichts anderes als nach SSH-Servern zu suchen und bei Ihnen verschiedenste Passw\u00f6rter durchzuprobieren. Mit einem halbwegs sicheren Passwort ist das kein gro\u00dfes Problem, trotzdem gibt es ein besseres Gef\u00fchl, wenn nicht einmal das m\u00f6glich ist. Au\u00dferdem sch\u00fctzt man so auch seine User, falls auf dem Server auch Useraccounts bestehen. Hier kann man sich nicht darauf verlassen, dass die Benutzer sichere Passw\u00f6rter verwenden. denyhosts \u00fcberpr\u00fcft st\u00e4ndig Logins auf dem ssh und sperrt Benutzer f\u00fcr eine gewisse Zeit, die ihr Passwort wiederholt falsch angegeben haben. Die IP&#8217;s dieser Nutzer landen tempor\u00e4r in \/etc\/hosts.deny, so dass f\u00fcr sie kein Zugriff mehr m\u00f6glich ist. Damit wird SSH-Bruteforcing zu einer sehr langwierigen und wenig erfolgversprechenden Aufgabe.<\/p>\n<pre>apt-get install denyhosts\r\n\r\n# denyhosts funktioniert direkt nach der Installation. Man kann es\r\n# in der Datei \/etc\/denyhosts.conf feintunen<\/pre>\n<p><strong>4. Blacklisten benutzen, um bekannte Problem-IPs auszusperren<\/strong><\/p>\n<p>Im Internet werden verschiedene Blacklisten gepflegt, die eine gro\u00dfe Anzahl von kriminellen\/gehackten\/spammenden\/betr\u00fcgerischen Servern auflisten. Diese IP-Listen k\u00f6nnen direkt in die Firewall eingetragen werden, so dass von diesen bekannterma\u00dfen nicht vertrauensw\u00fcrdigen Rechnern \u00fcberhaupt keine Verbindung mehr zum eigenen Server m\u00f6glich ist. So kann man das Spamaufkommen auf dem eigenen Server drastisch verringern und auch das eine oder andere Script-Kiddie aussperren, weil sein Russland-Proxy pl\u00f6tzlich nicht mehr funktioniert. Wie man das macht habe ich bereits <a href=\"https:\/\/www.daniel-ritter.de\/blog\/linux-server-mit-der-scamspamcrime-blacklist-von-infiltrated-net-absichern\">in einem anderen Blog-Artikel<\/a> am Beispiel der Blacklist von Infiltrated.net beschrieben.<\/p>\n<p><strong>5. Kein FTP benutzen f\u00fcr die Arbeit am Server<\/strong><\/p>\n<p>FTP ist ein Relikt aus besseren Zeiten in denen das Internet noch ein kleines vertrauensw\u00fcrdiges D\u00f6rfchen war. Viele Admins von Webseiten nutzen nach wie vor FTP um Dateien zum Server zu \u00fcbertragen oder um an der eigenen Website zu arbeiten. Das ist leider sehr unsicher, da FTP alle Daten ungesichert \u00fcbertragt. Passw\u00f6rter und Daten k\u00f6nnen an jedem Hop zwischen Server und Client ohne Probleme mitgelesen werden. Viel sicherer geht es mit sshfs. Hiermit kann man sich per SSH ein Verzeichnis des Remote-Servers in sein lokales Dateisystem mounten. Man kann danach auf dem Server so arbeiten, als sei er auf dem lokalen Rechner. Alle Dateizugriffe auf Dateien auf dem Server sind komplett transparant, man kann also auch mit dem lokalen Grafikprogramm ein Bild auf dem Server direkt \u00f6ffnen, bearbeiten und wieder speichern. Mehr Komfort und mehr Sicherheit ohne gro\u00dfen Aufwand.<\/p>\n<pre>#sshfs installieren\r\napt-get install sshfs\r\n\r\n#mountpoint im lokalen Dateisystem anlegen\r\nmkdir \/media\/meinserver\r\n\r\n#Server ins lokale Dateisystem mounten\r\nsshfs www-data@mein-server.de:\/var\/www \/media\/meinserver\r\n\r\n#Nun ist das Verzeichnis \/var\/www auf meinserver lokal unter \/media\/meinserver verf\u00fcgbar<\/pre>\n<p><strong>6. Updates installieren<\/strong><\/p>\n<p>Ein super abgesichertes System hilft nichts, wenn das System selbst fehlerhaft ist und eine bekannte Sicherheitsl\u00fccke ausgenutzt werden kann. Meist werden diese Sicherheitsl\u00fccken schnell geschlossen, oft vergessen Admins jedoch regelm\u00e4\u00dfige Updates des Systems zu machen. Ob man automatische Updates auf Linux-Servern aktivieren sollte oder nicht ist ein strittiges Thema. Einige w\u00fcrden es niemals tun, da es nat\u00fcrlich mit viel Pech auch sein kann, dass die Updates das System unbrauchbar machen. Dies ist mir in \u00fcber 10 Jahren Arbeit an Debian-Systemen allerdings niemals passiert und ich sch\u00e4tze den Nutzen von zeitnahen und regelm\u00e4ssigen Updates viel h\u00f6her ein, als die daraus entstehende Gefahr.<\/p>\n<pre>#Diese Zeile in der \/etc\/crontab aktualisiert das System t\u00e4glich um 6 Uhr morgens\r\n0 6 * * *       root    apt-get update &amp;&amp; apt-get -y upgrade<\/pre>\n<p>Diese Quick-and-dirty Methode funktionierte bei mir bisher immer gut. Vor kurzem habe ich gelesen, dass im Debian Repository auch das Paket unattended-upgrades existiert, das die Aufgabe wohl etwas eleganter l\u00f6st, ich habe es allerdings bisher nicht getestet.<\/p>\n<p>Auch bei diesen vollautomtischen Systemupdates ist man nicht komplett aus dem Schneider. Falls ein Kernel-Update ausgeliefert wurde, muss man das System trotzdem noch per Hand neu booten, da ansonsten die \u00c4nderungen nicht aktiv werden.<\/p>\n<p>Benutzt man fremden PHP-Code auf dem Server, wie zum Beispiel ein Open-Source CMS oder ein Forum, ist es nat\u00fcrlich absolut notwendig auch diesen Code mit neuen Versionen aktuell zu halten. Da Debian mit seinen Updates \u00c4nderungen an diesen Applikationen in der Regeln nicht abdeckt, ist hier Handarbeit n\u00f6tig. Am besten liest man die Mailinglisten der entsprechenden Produkte mit um immer auf dem Laufenden zu sein.<\/p>\n<p><strong>7. PHP einsperren mit open_basedir<\/strong><\/p>\n<p>Viele Hacks basieren darauf, dass eine Sicherheitsl\u00fccke im PHP-Code ausgenutzt wird, um auf Dateien im Dateisystem zuzugreifen, die nicht zur Website geh\u00f6ren, sondern zum System selbst. Deshalb sollte man PHP einsperren, so dass es nur in explizit erlaubten Verzeichnissen lesen und schreiben darf. Daf\u00fcr bietet die php.ini die Konfigurationsoption open_basedir. PHP hat nach setzten der Option nur noch Zugriff auf die dort erlaubten Verzeichnisse. Dateien wie \/etc\/passwd werden unerreichbar. Hostet man auf einem Server mehrere Webseiten sollte man open_basedir in der jeweiligen VirtualHost-Konfiguration pro Seite setzen.<\/p>\n<pre># Global per php.ini:\r\n# \/etc\/php5\/apache2\/php.ini\r\nopen_basedir = \/var\/www\/:\/tmp\/\r\n\r\n# Per Site in der VirtualHost Config:\r\nphp_value open_basedir \/var\/www\/site\/:\/tmp\/<\/pre>\n<p>Wichtig ist zu pr\u00fcfen ob wirklich alle Orte eingetragen wurden, auf die die Skripte normalerweise Zugriff haben m\u00fcssen, ansonsten kann es sein, dass man auch legitime Funktionen der PHP-Applikation behindert.<\/p>\n<p><strong>8. F\u00fcr Websites einen eigenen MySQL-Benutzer anlegen<\/strong><\/p>\n<p>Benutzt die eigene PHP-Applikation MySQL, sollte man unbedingt f\u00fcr die Apllikation einen eigenen MySQL-Benutzer anlegen und auf keinen Fall den MySQL-root-Benutzer f\u00fcr Zugriffe nutzen. Au\u00dferdem sollte man die Rechte des Benutzers so weit einschr\u00e4nken, dass wirklich nur noch Operationen erlaubt sind, die das PHP-Skript ben\u00f6tigt. CREATE TABLE und DROP TABLE werden zum Beispiel h\u00e4ufig bei SQL-Injections genutzt und werden in den meisten PHP-Applikationen nie ben\u00f6tigt. Hostet man mehrere Websites mit mehreren Datenbanken auf einem Server, sollte man f\u00fcr alle Datenbanken eigene Benutzer anlegen. So hat ein Angreifer nach einem erfolgreichen Angriff nur Zugriff auf eine der Datenbanken und nicht direkt auf alle. Wenn man nicht die Kommandozeile bem\u00fchen m\u00f6chte, um die MySQL-Useraccounts zu verwalten, funktioniert das Usermanagement auch recht einfach mit PHPmyAdmin unter der Registerkarte &#8222;Rechte&#8220;.<\/p>\n<p><strong>9. PHP Fehlermeldungen abschalten<\/strong><\/p>\n<p>PHP-Fehlermeldungen k\u00f6nnen einem Angreifer viel \u00fcber den eigenen Server verraten: Verzeichnisstrukturen, Datenbankstrukturen, Konfigurationsfehler, etc. Au\u00dferdem sehen sie f\u00fcr den Benutzer sehr unprofessionell aus. Aus diesem Grund sollte man sie auf einem Live-Webserver grunds\u00e4tzlich abschalten, da man sie ohnehin weiterhin in den Logs sehen kann.<\/p>\n<pre># Global per php.ini:\r\n# \/etc\/php5\/apache2\/php.ini\r\ndisplay_errors = Off\r\n\r\n# Per Site in der VirtualHost Config:\r\nphp_flag display_errors Off\r\n\r\n# Fehlermeldungen trotzdem lesen:\r\ncat \/var\/log\/apache2\/error.log | grep PHP<\/pre>\n<p><strong>10. Angriffsfl\u00e4che f\u00fcr SQL-Injections einschr\u00e4nken mit modSecurity <\/strong><\/p>\n<p>SQL-injections sind die wohl am h\u00e4ufigsten genutzte Angriffsmethode auf Webserver. Der Zugriff erfolgt direkt \u00fcber die Webapplikation und es gen\u00fcgt ein Browser um sie durchzuf\u00fchren. Dabei werden \u00fcber vom User \u00fcbermittelte Variablen geschickt SQL-Abfragen eingebaut, die mit den Rechten des Datenbankbenutzers alles an der eigenen Datenbank nach belieben auslesen, l\u00f6schen oder bearbeiten k\u00f6nnen. Ein wirklicher echter Schutz gegen SQL-Injections besteht nur, wenn der PHP-Code der Site im Hinblick auf diese Angriffe geschrieben wurde. Jede Variable aus Benutzereingaben, die in eine SQL-Abfrage gelangen k\u00f6nnte, muss gepr\u00fcft und escaped werden. PHP bietet daf\u00fcr die Funktion real_mysql_escape_string().<\/p>\n<p>Ist man nicht sicher, ob der Code sauber ist, kann mod_security f\u00fcr den Apache helfen eine gro\u00dfe Menge dieser Angriffe trotzdem abzuwehren. mod_security \u00fcberpr\u00fcft st\u00e4ndig alle Requests an den Webserver und reagiert auf vorgefertigte Muster mit denen viele SQL-Injection-Angriffe abgewehrt werden k\u00f6nnen. Leider funktioniert auch mod_security nur gut mit manuellem Aufwand. Oft blockt mod_security nach einer frischen Installation auch gew\u00fcnschte (normale) Funktionen des eigenen PHP-Codes, so dass einem nichts anderes \u00fcbrig bleibt, als die komplette Applikation nach der Installation einmal durchzutesten. Nur so findet man heraus, ob mod_security nicht eventuell auch gew\u00fcnscht Funktionen blockt. Ist das der Fall, muss die Filterliste angepasst werden, so dass die false-positives verschwinden.<\/p>\n<p>Die Konfiguration von mod_security ist etwas komplizierter und w\u00fcrde den Umfang dieses Artikels sprengen, es gibt aber massenweise gute Tutorials zu mod_security im Internet.<\/p>\n<p><strong>11. Ausweiskontrolle &#8211; Der Apache sagt nicht mehr, wer er ist <\/strong><br \/>\nDies ist keine wirklich wirkungsvolle Methode gegen einen Hack, sie macht es automatisierten Skripten, die nach Server-Versionen suchen aber etwas schwerer. Normalerweise zeigt der Apache auf Seiten mit Fehlermeldungen (z.B. 404 Not Found) seine Serversignatur.<\/p>\n<pre>Apache\/2.2.16 (Debian) Server at www.daniel-ritter.de Port 80<\/pre>\n<p>So erhalten potentielle Angreifer zumindest schon einmal Informationen \u00fcber den eigesetzten Webserver und den Versionsstand. Die Serversignatur ist schnell ausgeschaltet:<\/p>\n<pre>#\/etc\/apache2\/conf.d\/security\r\nServerSignature Off<\/pre>\n<p><strong>12. Nicht benutze Apache-Module deaktivieren<\/strong><\/p>\n<p>Per default hat der Apache einige Module geladen, die fast nie ben\u00f6tigt werden. Unter Debian findet man die geladenen Module<br \/>\nals Softlinks in \/etc\/apache2\/mods-enabled.<\/p>\n<p>Fast immer entfernt werden k\u00f6nnen:<\/p>\n<p><em>mod_cgi<\/em><\/p>\n<p>Dient dem ausf\u00fchren von CGI-Skripten. Diese Technik stammt noch aus den Urzeiten des Web und war der Vorvater der modernen Skriptsprachen um dynamische Webseiten zu erm\u00f6glichen. mod_cgi ist auf 99% der PHP-Websites unn\u00f6tig und bei einer fehlerhaften Apache-Config eine potentielle Sicherheitsl\u00fccke<\/p>\n<pre>a2dismod cgi<\/pre>\n<p><em>mod_status<\/em><\/p>\n<p>Erm\u00f6glicht es Browsern Statusinformationen \u00fcber den Apache auszulesen. Es wird so gut wie nie f\u00fcr &#8222;normale&#8220; Sites genutzt, bietet Angreifern aber Statusinformationen \u00fcber den Apache.<\/p>\n<pre>a2dismod status<\/pre>\n<p><em>mod_autoindex<\/em><\/p>\n<p>mod_autoindex sorgt daf\u00fcr, dass Verzeichnisse auf dem Webserver aufgelistet werden k\u00f6nnen, wenn es keine g\u00fcltige Index-Seite in dem entsprechenden Verzeichnis gibt. Falls diese Funktionalit\u00e4t nicht erw\u00fcnscht ist, sollte man sie abschalten, da durch sie ganze Verzeichnisb\u00e4ume auf dem Webserver nach aussen sichtbar werden k\u00f6nnen.<\/p>\n<pre>a2dismod autoindex<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Die Hacking-Frequenz ist in den letzten Monaten stark angestiegen. Besonders viele Daten werden abgegriffen durch Hacks auf Webserver. Sogar der SONY-PSN-Hack nutzte Schwachstellen in einem ungepatchten Apache-Webserver. Deshalb sammele ich hier Ma\u00dfnahmen, die den eigenen Server etwas sicherer gegen Angriffe von au\u00dfen machen k\u00f6nnen. Nat\u00fcrlich bieten auch diese keinen 100%igen Schutz, aber es ist besser, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1905,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[227,224],"tags":[125,128,123,122,124,127,126,29],"class_list":["post-798","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-network","tag-denyhosts","tag-display_errors","tag-firewall","tag-lamp","tag-mod_security","tag-open_basedir","tag-sql-injection","tag-ssh"],"_links":{"self":[{"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/posts\/798","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/comments?post=798"}],"version-history":[{"count":50,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/posts\/798\/revisions"}],"predecessor-version":[{"id":1908,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/posts\/798\/revisions\/1908"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/media\/1905"}],"wp:attachment":[{"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/media?parent=798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/categories?post=798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.daniel-ritter.de\/blog\/wp-json\/wp\/v2\/tags?post=798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}