Apache SSL Cipher Suites einschränken

Um den Einsatz der unsicheren Cipher Suiten RC4 und SSLv2/3 zu deaktivieren, damit Poodle Attacken etc. nicht mehr wirksam sind, müssen folgende Einstellungen im mod_ssl des Apache Webservers angepasst werden:

nano /etc/apache2/mods-enabled/ssl.conf

Den Eintrag “SSLCipherSuite” auskommentieren und wie folgt abändern:

[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”]

#Secure SSL
SSLProtocol ALL -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

Ein Test der Ergebnisse kann bei SSL Labs durchgeführt werden

vorher:

gradeC

nachher:

gradeA[/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

Advertisements

Apache SSL Zertifikat mit letsencrypt

Diese Anleitung behandelt das Einrichten eines TLS/SSL Zertifikats von Let’s Encrypt auf einem Ubuntu 14.04 Server mit einem Apache Webserver. Dieses Zertifikat soll anschließend automatisch erneuert werden.

Installation Git Client

apt-get install git

Download des Let’S Encrypt Clients


git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

SSL Zertifikat erstellen

Um das Zertifikat für eine einzelne Domain zu erzeugen, führt man folgenden Befehl aus:

cd /opt/letsencrypt ./letsencrypt-auto --apache -d tj-braun.de;

Sollten mehrere Domains mit einem Zertifikat versehen werden, so sind sie jeweils einzeln anzugeben:

./letsencrypt-auto --apache -d tj-braun.de -d http://www.tj-braun.de

Automatische Erneuerung des Zertifikats

Zertifikate von Let’s Encrypt laufen alle 3 Monate aus und müssen aktiv erneuert werden.

./letsencrypt-auto renew;

Die Ausgabe sieht in etwa so aus

Checking for new version... Requesting root privileges to run letsencrypt... /root/.local/share/letsencrypt/bin/letsencrypt renew Processing /etc/letsencrypt/renewal/www.tj-braun.de.conf The following certs are not due for renewal yet: /etc/letsencrypt/live/tj-braun.de/fullchain.pem (skipped) No renewals were attempted.

Der Befehl kann in der Crontab des Systems hinterlegt werden:

crontab -e

Folgenden Inhalt einfügen:

30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log

Der Cronjob wird jeden Montag um 2:30 Uhr morgens das Kommando ausführen und die Ausgabe in die Datei /var/log/le-renew.log schreiben.

Client erneuern

Der Client kann manuell erneuert werden, allerdings wird ein Update auch bei jedem Aufruf des o.g. Cronjobs ausgeführt.

cd /opt/letsencrypt
sudo git pull

Apache mit dem Zertifikat ausstatten

In folgendem Fall wird davon ausgegangen, dass noch keine Konfigurationsdatei für eine Webseite vorliegt.
Daher muss zunächst eine neue Konfiguration angelegt werden:

nano /etc/apache2/sites-available/SEITENNAME.conf
nano/etc/apache2/sites-available/cloud.tj-braun.de.conf

Anlegen eines Virtual Hosts für Port 80 (http) und 443 (https). Es soll eine Umleitung auf eine sichere Verbindung erfolgen, wenn die Seite via http aufgerufen wird.

<VirtualHost *:80>
ServerName cloud.tj-braun.de
#immer auf https ausweichen
Redirect permanent / https://cloud.tj-braun.de/
</VirtualHost>

Die Direktive “ServerName” gibt an, dass die Konfiguration nur greifen soll, wenn die URL damit übereinstimmt. Mit “Redirect permanent” wird das Root-Verzeichnis permanent umgelenkt.

Wenn mod_ssl aktiviert ist, greifen folgende Einstellungen:

<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin MAILADRESSE
ServerName cloud.tj-braun.de
DocumentRoot /var/www/nextcloud/

ErrorLog ${APACHE_LOG_DIR}/cloud-error.log
CustomLog ${APACHE_LOG_DIR}/cloud-access.log combined

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.tj-braun.de/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.tj-braun.de/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/www.tj-braun.de/chain.pem

<IfModule mod_headers.c>
#Nextcloud STS Policy
Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
</IfModule>

<Directory "/var/www/nextcloud/data">
#Nextcloud aktivieren der .htaccess Files
AllowOverride All
</Directory>

 

</VirtualHost>
</IfModule>

Der SSL… Teil gibt an, dass SSL aktiviert sein soll und welches Zertifikat genutzt werden soll.

Beide Konfigurationen stehen in der gleichen Apache Config Datei. Datei speichern und schließen mit strg+o und strg+x

Anschließend wird die Seite aktiviert

a2ensite NAMEDERKONFIGDATEI

und der Webserver neugestartet

service apache2 restart

Sollte Cloudflare aktiv sein, so muss die Zertifikatsvalidierung anderweitig erfolgen.

Datenbank Backup – Powershell

PS> .backup.ps1 -serverName “localhostSQLEXPRESS” -backupTempDirectory “C:tmp” -daysToStoreBackups 1 -copyDirectory “pfadzumDatenbank_Backup”

[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”]

param(
$serverName,
$backupTempDirectory,
$daysToStoreBackups,
$copyDirectory
)

&nbsp;
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null

$server = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $serverName
$dbs = $server.Databases
foreach ($database in $dbs | where { $_.IsSystemObject -eq $False })
{
write-host "Backup Database" $database.Name -foregroundcolor green
$dbName = $database.Name

$timestamp = Get-Date -format yyyy-MM-dd-HHmmss
$targetPath = $backupTempDirectory + "" + $dbName + "_" + $timestamp + ".bak"

$smoBackup = New-Object ("Microsoft.SqlServer.Management.Smo.Backup")
$smoBackup.Action = "Database"
$smoBackup.BackupSetDescription = "Full Backup of " + $dbName
$smoBackup.BackupSetName = $dbName + " Backup"
$smoBackup.Database = $dbName
$smoBackup.MediaDescription = "Disk"
$smoBackup.Devices.AddDevice($targetPath, "File")
$smoBackup.SqlBackup($server)

"backed up $dbName ($serverName) to $targetPath"
}

Get-ChildItem "$backupTempDirectory*.bak" |? { $_.lastwritetime -le (Get-Date).AddDays(-$daysToStoreBackups)} |% {Remove-Item $_ -force }
"removed all previous backups older than $daysToStoreBackups days"

Write-Host "Move the $dbName database(s): $backupTempDirectory$dbName*.bak to $copyDirectory"
mv $backupTempDirectory$dbName*.bak $copyDirectory -force

[/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

Dateien im Ordner zippen, löschen und archivieren – Powershell

Dateien, die älter sind als x Tage, sollen innerhalb eines Ordner gezippt, gelöscht und archiviert werden.


<#
.SYNOPSIS
.
.DESCRIPTION
Find, delete and zip files in a folder.
.PARAMETER days
Check the last write time of a file. File is older than x days
.PARAMETER path
Path of the root folder of the files to be deleted.
.PARAMETER zip
Makes an archive containing all the files that were found.
.PARAMETER delete
Deletes the files that were found.
.PARAMETER archivePath
Specifies the path of the archive file. Standard path: C:tmparchive-"DATE".zip
.EXAMPLE
C:PS> .delete_old_files.ps1 -days 5 -path C:tmp -zip yes -delete yes -archivepath C:archives
Files that are older than 5 days from now on, root folder C:tmp, files will be zipped and deleted, the archive for the zip files will be in C:archives
Note that 7zip is a must have for zipping the files!
.NOTES
Author: Jens Braun
Date: Feb 04, 2016
#>

param(
[parameter(Mandatory=$true)]
[int]$days,
[parameter(Mandatory=$true)]
[string]$path,
[parameter(Mandatory=$false)]
[string]$zip,
[parameter(Mandatory=$false)]
[string]$delete,
[parameter(Mandatory=$false)]
[string]$archivePath
)

$sz="C:Program Files (x86)7-Zip7z.exe"
$z=1
$date = get-date -uformat "%Y-%m-%d"
#Soll gezippt werden?
if($zip -eq "yes"){
if(test-path "C:Program Files (x86)7-Zip7z.exe"){
Write-Host "7zip found"
Write-Host "Files will be zipped"
if($archivePath){
if(test-path $archivePath){
$archivePath= -join ($archivePath,"archive-",$date,".","zip")
Write-Host "archive to $archive"
}else{
$archivePath = "C:tmparchive-$date.zip"
Write-Host "Archive Path not found, using Standardarchive: $archivePath"
}
}else{
$archivePath = "C:tmparchive-$date.zip"
Write-Host "Archive Path not found, using Standardarchive: $archivePath"
}
}else{
Write-Warning "7zip not found"
$zip = "no"
}
}else{
Write-Host "Files will not be zipped"
$zip = "no"
}

#Soll gelöcht werden?
if($delete -eq "yes"){
Write-Host "Files will be deleted"
}else{
Write-Host "Files will not be deleted"
$delete="no"
}

#weder noch
if(($delete -eq "no") -and ($zip -eq "no")){
Write-Warning "Neither delete nor zipping, exiting!"
break
}

#path vorhanden?
if(!(test-path $path)){
write-warning "Archive Path not found"
break
}
#Nur Dateien, keine Ordner!
$files2delete = gci -path $path -recurse -force | ? -FilterScript {(($_.LastWriteTime -lt (get-date).adddays(-$days)) -and (! $_.PSIsContainer)) }

$Files2Remove = $files2delete.Count
foreach ($file in $files2delete){
Write-Progress -Activity "Working..." -status ("Files Processed $z of "+$Files2Remove.ToString()) -percentComplete ($z / $Files2Remove*100)
if($zip -eq "yes"){
& $sz a $archivePath $file.fullname -ssc >$null 2>&1
}

if($delete -eq "yes"){
remove-item $file.fullname -force -whatif
}

$z++
}

Massenkonvertierung .doc nach .pdf – Powershell

Mit diesem Powershell Skript ist es möglich, alle Word Dokumente (.doc und .docx) automatisch in ein PDF umzuwandeln.
Dazu muss der Code als .ps1 Datei gespeichert werden.
Entweder wird danach das Skript direkt aufgerufen oder in der Powershell gestartet und der Pfad eingegeben.

powershell-console

Anschließend befinden sich neben den Word Dokumenten ebenfalls PDF Dokumente im Verzeichnis.

explorer-docs

[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”]

$documents_path = Read-Host "Pfad eingeben "
$word_app = New-Object -ComObject Word.Application
# This filter will find .doc as well as .docx documents
Get-ChildItem -Path $documents_path -Filter *.doc? | ForEach-Object {
$document = $word_app.Documents.Open($_.FullName)
$pdf_filename = "$($_.DirectoryName)$($_.BaseName).pdf"
$document.SaveAs([ref] $pdf_filename, [ref] 17)
$document.Close()
}
$word_app.Quit()

Alternativ gibt es das Skripte hier als Download.[/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

Fail2Ban: Block Apache 404 file not found

Um Bots auszusperren, die z.B. versuchen auf nicht bestehende Webseiten/Dienste (phpMyAdmin etc.) zuzugreifen, wird das Intrusion Prevention System Fail2Ban erweitert.

Es wird eine neue Filterdatei erstellt (/etc/fail2ban/filter.d/apache-fileNotFound.conf)

Sie beinhaltet die RegEx, um das Apache Log auszuwerten:

[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”]

[Definition]
failregex = [[]client &lt;HOST&gt;[]] (File does not exist)
igignoreregex = [[]client &lt;HOST&gt;[]] (File does not exist: /var/www/favicon.ico)

Danach kann in der jail.conf die entsprechende Direktive hinterlegt werden:

[/fusion_builder_column][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”]

[apache-fileNotFound]
enabled = true
filter = apache-fileNotFound
port = http,https
logpath = /var/log/apache*/*error.log
maxretry = 3

Danach den Dienst neu starten.

tail /var/log/fail2ban.log:
fail2ban.actions: WARNING [/fusion_builder_column][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”][apache-fileNotFound] Ban 1.2.3.4

iptables -L
Chain fail2ban-apache-fileNotFound (1 references)
target prot opt source destination DROP all — 1.2.3.4 anywhere[/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

WinSCP ohne SSH – Root Zugriff

Da die Protokolle SFTP, FTP und SCP es nicht erlauben innerhalb einer Sitzung den Benutzer zu wechseln, muss man die Sitzung mit dem korrekten Benutzer starten.

Das geht entweder über einen direkten Login oder via sudo bei der Anmeldung.

Nutzen von sudo bei der Anmeldung mit SFTP

Über das SFTP Protokoll kann man die SFTP Server Option unter dem SFTP Menü nutzen. Dort muss man den Nutzer angeben, unter dem das Binary ausgeführt werden soll. Bei einem OpenSSH Server kann man folgendes definieren:

sudo /usr/lib/openssh/sftp-server

2016-05-30-12_32_02-Erweiterte-Einstellungen-für-Verbindungsziele

Dies kann allerdings nur ausgeführt werden, wenn der jeweilige Benutzer den Befehl ohne Passworteingabe ausführen kann. Dazu muss die sudoers Berechtigung angepasst werden.

via “visudo” folgendes hinzufügen:

USERNAME ALL=NOPASSWD: /usr/lib/openssh/sftp-server

visudo

Da in der Liste immer der letzte Eintrag greift, sollte die Zeile am Ende auftauchen.

weitere Infos gibt es hier