Openvpn: MySQL-Auth

Hoeze

Lieutenant
Registriert
Juni 2010
Beiträge
696
Hi,
ich würde gerne einen VPN-Server auf user-pass Authentifizierung mit MySQL umstellen, um ein einfach und schnell zu verwaltendes VPN zu erstellen.
Dazu hab ich das hier gefunden.

Das Login-Script:
Code:
#!/bin/bash
. /etc/openvpn/script/config.sh
##Authentication
user_id=$(mysql -h$HOST -P$PORT -u$USER -p$PASS $DB -sN -e "select user_id from user where user_id = '$username' AND user_pass = '$password' AND user_enable=1 AND user_start_date != user_end_date AND TO_DAYS(now()) >= TO_DAYS(user_start_date) AND (TO_DAYS(now()) <= TO_DAYS(user_end_date) OR user_end_date='0000-00-00')")
##Check user
[ "$user_id" != '' ] && [ "$user_id" = "$username" ] && echo "user : $username" && echo 'authentication ok.' && exit 0 || echo 'authentication failed.'; exit 1


Ich traue diesem Script nicht ganz, da $username hier nicht überprüft wird.
Wäre hier nicht eine einfache SQL-Injection möglich?
Mich würde interessieren, wie ich das verhindern kann.

Die zweite Sache ist die: Ich muss ja auch das Passwort irgendwie in der Datenbank speichern.
md5 alleine reicht mir aber nicht, da es sich zu leicht knacken lässt.
Wäre da in etwa so etwas möglich:
sha2(<salt>sha2($password +<zweiter Salt>))
Wie stell ich das an?
 
Ja, bin ich auch nicht grad begeistert von. Du könntest im Minimum die Eingaben von hand Filtern. zB. so:

$escaped_username=${username//'/\\'}

und was das hashen anbelangt:

hash=$(echo -n "$moresalt"$(echo -n "$password$salt" | sha256sum) | sha256sum)

oder anstatt bash halt in einer "richtigen" sprache schreiben.
 
' durch \' ersetzen.

Was du aber eh auch noch machen müsstest: \ durch \\ ersetzen, und zwar vorher.
 
=>
Code:
$escaped_username=${${username//\/\\}//'/\\'}
So also?
(Was für ein Befehl :D :D )
Ergänzung ()

Könnte ich das nicht anders angehen?
Gibt es eine Möglichkeit, sämtliche Zeichen bis auf Zahlen, Buchstaben, '-' und '_' durch ein '_' zu ersetzen?
 
Ugh, nein, mindestens das dollarzeichen bei $escaped... ist definitiv am falschen ort, und so verschachtelt, klappt glaub nicht - müsstest du in zwei durchläufen nacheinander machen. Eher so:

Code:
escaped_username=${username//\\/\\\\}
escaped_username=${escaped_username//\'/\\\'}

Alle Zeichen ausser die von dir besagten ersetzen ist einfach machbar:

Code:
escaped_username=${username//[^a-zA-Z0-9-]/_}
 
Zuletzt bearbeitet:
Hi,

ich habe auch einen OpenVPN Dienst mit MySQL Auth am laufen.

Ich habe damals schon einmal Sonderzeichen eingegeben und ausprobiert, was denn da via "via-env" weitergegeben wird.

Im Script habe ich ein "echo $username >> /tmp/catch" eingebaut. Als Username habe ich dann "'\''"\;:#[]{}()|&^$@!?, .<>" benutzt, und geschaut, was in der Variable steht. Das Ergebnis ist/war: ___________________@____.__


Anschließend schrieb ich ein ganz einfaches Login-Script, mit dem ich dann die SQL Injection versuchte. Ging nicht.

Einzig E-Mail Adressen werden wohl als Benutzername nicht von OpenVPN escaped, daher bleiben auch das @ und der Punkt stehen.
 
Mein Ziel war es, zum einen eine sichere User/Pass Authemtifizierung zu bekommen und zum anderen IP's fest zu vergeben.

Dazu habe ich folgende Scripte erstellt.
Will sich ein user authentifizieren, wird zusätzlich überprüft, ob dieser nicht bereits online ist.
Sobald dann die Verbindung aufgebaut werden soll, wird überprüft, ob in der Datenbank bereits eine feste IP für diesen User eingetragen ist. Ist dem nicht so, wird für ihn eine IP aus dem Pool eingetragen. Anschließend wird ihm diese IP zugewiesen. Außerdem wird er in die Tabelle online eingetragen.
Beendet ein User die Verbindung, so wird dieser aus der Tabelle online gelöscht.
Das Startup-Script löscht beim Starten von Openvpn alle Einträge aus der Tabelle online heraus (falls diese mal wegen eines Server-Absturzes noch überflüssige Einträge enthält).

Jetzt hab ich nur noch ein Problem mit dieser Zeile:
Code:
echo "push \"ifconfig $ipAddress 255.255.255.0\"" > $1
Wie bekomm ich die in PHP-Form? :D

(Bitte nicht schlagen, ich habe eigentlich keine Ahnung von PHP :freaky: )

startup.sh
PHP:
#!/usr/bin/php

<?php

require_once 'configphp.sh';

$db_link = new MySQLi (MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_HOST_PORT);

$query = "DELETE FROM online";
$db_link->query($query);

$db_link->close();

?>
configphp.sh:
PHP:
#!/usr/bin/php

<?php

error_reporting(E_ALL);

define ( 'MYSQL_HOST', '127.0.0.1' );
define ( 'MYSQL_HOST_PORT', '' );
define ( 'MYSQL_USER',  '' );
define ( 'MYSQL_PASS',  '' );
define ( 'MYSQL_DB', '' );

function genhash($str) {
   /*
   
   Hier steht mein Hashzeugs drin
   
   */
    return $str;
}

?>
login.sh:
PHP:
#!/usr/bin/php 

<?php

// Read username / password from tmp file

$file = fopen("$argv[1]", "r") or exit(1); 

while( ! feof( $file )) { 
  $line = rtrim(fgets($file)); 
  if ( empty($username) && empty($password)) { 
    $username = "$line"; 
  } 
  elseif (isset($username) && empty($password)) { 
    $password = "$line"; 
  } 
} 

fclose($file); 

require_once 'configphp.sh';

$db_link = new MySQLi (MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_HOST_PORT);

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit(1);
}

//echo var_dump($db_link);

$username = $db_link->real_escape_string($username);

echo "$username is requesting authentication\n";

$query = "SELECT username FROM online WHERE username = (?)";

//$db_link->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

$cmd = $db_link->prepare($query);
$cmd->bind_param('s', $username);
$cmd->execute();
$cmd->bind_result($online);
$cmd->fetch();

if (isset($online)) {
  echo "User $username is already online\n";
  $db_link->close();
  exit (1);
}

$query = "SELECT password FROM users WHERE username = (?)";

$cmd = $db_link->prepare($query);
$cmd->bind_param('s', $username);
$cmd->execute();
$cmd->bind_result($pass);
$cmd->fetch();


$db_link->close();

if (isset ($pass) && genhash($password) == $pass) {
  echo "Password for $username accepted\n";
  exit (0);
}

exit (1);

?>
client-connect.sh:
PHP:
#!/usr/bin/php

<?php

require_once 'configphp.sh';

$db_link = new MySQLi (MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_HOST_PORT);

$username = $db_link->real_escape_string($common_name);

$query = "SELECT ipAddress FROM users WHERE username = (?)";

$cmd = $db_link->prepare($query);
$cmd->bind_param('s', $username);
$cmd->execute();
$cmd->bind_result($ipAddress);
$cmd->fetch();

if (isset($ipAddress)) {
  $query = "INSERT INTO online (username) VALUES (?)";
  $cmd = $db_link->prepare($query);
  $cmd->bind_param('s', $username);
  $cmd->execute();
  $db_link->close();
  echo "push \"ifconfig $ipAddress 255.255.255.0\"" > $1
  exit (0);
}

$query = "SELECT ipAddress FROM IPs WHERE used = 0 LIMIT 1";

$cmd = $db_link->prepare($query);
$cmd->execute();
$cmd->bind_result($ipAddress);
$cmd->fetch();

if (isset ($ipAddress) {
  $query = "UPDATE IPs SET used=1 WHERE ipAddress=(?)";
  $cmd = $db_link->prepare($query);
  $cmd->bind_param('s', $ipAddress);
  $cmd->execute();
  $query = "UPDATE users SET ipAddress = $ipAddress WHERE username = (?)"
  $cmd = $db_link->prepare($query);
  $cmd->bind_param('s', $username);
  $cmd->execute();
  
  $query = "INSERT INTO online (username) VALUES (?)";
  $cmd = $db_link->prepare($query);
  $cmd->bind_param('s', $username);
  $cmd->execute();
  $db_link_>close();
  echo "push \"ifconfig $ipAddress 255.255.255.0\"" > $1
  exit (0);
}

$db_link->close();

exit (1);

?>
client-disconnect.sh:
PHP:
#!/usr/bin/php

<?php

require_once 'configphp.sh';

$db_link = new MySQLi (MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_HOST_PORT);

$username = $db_link->real_escape_string($common_name);


$query = "DELETE FROM IPs WHERE username = $username";
$cmd = $db_link->prepare($query);
$cmd->bind_param('s', $username);
$cmd->execute();

$db_link->close();

?>
 
Zuletzt bearbeitet:
Zurück
Oben