Sisteme giriş için nasıl test yazabilirim?


9

bashKomutları çağıran bir Python CGI betiği yazdım ve ana bilgisayarda başarılı bir giriş için test etmesi gerekiyor.

Bunun için nasıl test yazabilirim?

Örneğin, bashbelirli bir kullanıcı adı ve şifre kombinasyonunu ana bilgisayarda kayıtlı kullanıcıya karşı test eden bir komut dosyası oluşturabilir miyim ?


1
Belki de loginprogramın arkasındaki koda bakabilirsiniz .
Kevin

Soru ile ilgili değil, ancak umarım kullanıcı girişleri kablodan çekilemez, böylece web sunucunuza trafik şifrelemek.
jw013

Yanıtlar:


8

PAM kullanmak en iyi çözümdür. Küçük C kodu yazabilir veya python-pam paketini kurabilir ve python-pam paketiyle birlikte gelen bir python betiği kullanabilirsiniz. Görmek/usr/share/doc/python-pam/examples/pamtest.py


PAM deniyorum ama işe yaramadı. Ama bu örneği tekrar deniyorum ve işe yarıyor.
jcubic

1
OpenSUSE 12.3 (python-pam 0.5.0-84.1.1) ve 13.1'de (0.5.0-87.1.2) pamtest.py /usr/share/doc/packages/python-pam/examples/pamtest.pydosyasının tam yolu pamtest.py komut dosyasıdır. PAM kullanan sistemlerde kimlik bilgilerini test etmek için kullanılabilir. kimlik doğrulama için, python-pam paketine (python gerektirir) dahil edilir ve bazı dağıtımlarda tam yol vardır /usr/share/doc/python-pam/examples/pamtest.py.
ShadSterling

5

Bir kullanıcının giriş yapıp yapamayacağını test etmek için doğru yaklaşım, o kullanıcı olarak giriş yapmaktır.

Bu yüzden tavsiye ettiğim, CGI betiğinin expectçalıştırılması su, bir parola geçirilmesi ve yürütülmesi gereken komutu çalıştırmasıdır. İşte sadece bunu yapan bir beklenti komut dosyası taslağı (uyarı: kesinlikle test edilmemiş ve beklemekte akıcı değilim). (Yazdığım nerede kullanıcı adı, parola ve komuta değiştirin bob, swordfishve somecommand); doğru alıntı yaptığınızdan emin olun.

spawn "/bin/su" "bob"
expect "Password:"
send "swordfish\r"
expect "^\\$"
send "somecommand"
expect -re "^\\$"
send "exit\r"
expect eof

Komutu bir katman üzerinden gerçekten yürütmek istemiyorsanız su(örneğin, yaptığınız şey CGI işleminin kendisi tarafından gerçekleştirilmesi gerektiğinden), komutu çalıştırmak trueiçin return komutunu kullanın ve dönüş durumunun 0 olup olmadığını kontrol edin.

Başka bir yaklaşım, PAM'yi Python'un PAM bağlaması yoluyla doğrudan uygulamanızda kullanmak olacaktır .


Bu harika, Kök erişimi olmayan tek çözüm.
jcubic

bu su -c true bob && echo successsu argüman olarak şifre kabul etmiyoruz utanç verici
jcubic

suCGI betiğinden test ettim ve çalışması için bir terminale ihtiyacı var.
jcubic

3
@jcubic Komut satırı bağımsız değişkenlerine bir parola koymak gerçekten aptalca bir fikirdir, çünkü komut satırı bağımsız değişkenleri bir Unix sisteminde herkese açıktır. Parolanın kaldırılması, komut satırına koymakla aynı düzeyde güvenlik sağlar. Ve kontrol etmek çok daha kolay /bin/trueolurdu : yeterli olurdu.
ceving

2

Daha spesifik olarak cevaplamak için: "Belirli bir kullanıcı adı ve şifre kombinasyonunu ana bilgisayarda kayıtlı kullanıcıya karşı test edecek bir bash betiği oluşturmak mümkün mü?"

Evet.

#!/bin/bash
uid=`id -u`

if [ $uid -ne 0 ]; then 
    echo "You must be root to run this"
    exit 1
fi

if [ $# -lt 1 ]; then
    echo "You must supply a username to check - ($# supplied)"
    exit 1
fi

username=$1
salt=`grep $username /etc/shadow | awk -F: ' {print substr($2,4,8)}'`

if [ "$salt" != "" ]; then

        newpass=`openssl passwd -1 -salt $salt`
        grep $username  /etc/shadow | grep -q  $newpass && echo "Success" || echo "Failure"

fi

2
Bu senin için işe yaradı mı? Gölge parolasına karşı mevcut bir gölge parolasını kontrol ettiğinizi görüyorum, ancak karma burada nereye dahil?
Nikhil Mulley

Test ettim ve çalışmıyor
jcubic

3
Kötü bir fikir! Programınızın kök olarak veya en azından shadowbir CGI için şiddetle tavsiye edilmeyen grup olarak çalıştığını varsayıyorsunuz : başka bir ayrıcalık yükseltme katmanına ihtiyacınız olacak. Ve belirli bir şifre karma algoritması (biri openssl tarafından desteklenen) ve şifre saklama konumu ( /etc/shadowörneğin, NIS veya LDAP yerine) söz konusu kullanıcı için gerçekte kullanılan veya olmayabilir.
Gilles 'SO- kötü olmayı bırak'

2

Burada alıntılanan bir 'C', 'Python' PAM çözümü var, ben de perl bir tane koymak izin :-)

Kaynak: http://search.cpan.org/~nikip/Authen-PAM-0.16/PAM/FAQ.pod#1._Can_I_authenticate_a_user_non_interactively ?

#!/usr/bin/perl

  use Authen::PAM;
  use POSIX qw(ttyname);

  $service = "login";
  $username = "foo";
  $password = "bar";
  $tty_name = ttyname(fileno(STDIN));

  sub my_conv_func {
    my @res;
    while ( @_ ) {
        my $code = shift;
        my $msg = shift;
        my $ans = "";

        $ans = $username if ($code == PAM_PROMPT_ECHO_ON() );
        $ans = $password if ($code == PAM_PROMPT_ECHO_OFF() );

        push @res, (PAM_SUCCESS(),$ans);
    }
    push @res, PAM_SUCCESS();
    return @res;
  }

  ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) ||
         die "Error code $pamh during PAM init!";

  $res = $pamh->pam_set_item(PAM_TTY(), $tty_name);
  $res = $pamh->pam_authenticate;
  print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS();

Evet, ama soru Python'da yazılmış bir CGI betiğiyle ilgili.
Gilles 'SO- kötü olmayı bırak'

1

Kök erişiminiz varsa ve md5 parolalarını kullanıyorsanız ve parolaları karşılaştırmanız gerekiyorsa, perl Crypt :: PasswdMD5 modülünü kullanabilirsiniz. / Etc / shadow'dan MD5 Hash'i alın, $ 1 $ 'ı soyun ve sonra kalan $' a bölün. Alan 1 = Tuz, Alan 2 = şifreli metin. Sonra metin girişini CGI'nize ekleyin, şifrelenmiş metinle karşılaştırın ve Bob amcanız.

#!/usr/bin/env perl

use Crypt::PasswdMD5;

my $user                = $ARGV[0];
my $plain               = $ARGV[1];
my $check               = qx{ grep $user /etc/shadow | cut -d: -f2 };
chomp($check);
my($salt,$md5txt)       = $check =~ m/\$1\$([^\$].+)\$(.*)$/;
my $pass                = unix_md5_crypt($plain, $salt);

if ( "$check" eq "$pass" ) {
        print "OK","\n";
} else {
        print "ERR","\n";
}

2
sade ve basit :-). / Etc / passwd, md5 karma işlemini kullandığı sürece çalışır. Kimlik doğrulama (nsswitch) sistem için farklıdır, daha sonra pam modülleri kullanmak en iyisidir.
Nikhil Mulley

2
Kötü bir fikir! Programınızın kök olarak veya en azından shadowbir CGI için şiddetle tavsiye edilmeyen grup olarak çalıştığını varsayıyorsunuz : başka bir ayrıcalık yükseltme katmanına ihtiyacınız olacak. Ve belirli bir şifre karma algoritması (bcrypt değil MD5 ve diğer önerilen algoritma) ve şifre saklama konumu ( /etc/shadowörneğin, NIS veya LDAP yerine) söz konusu kullanıcı için gerçekte kullanılan veya olmayabilir.
Gilles 'SO- kötü olmayı bırak'

0

Biraz arama yaptıktan sonra senaryodan kullanılabilecek bu C programını yazdım

#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <crypt.h>
#include <unistd.h>
#include <libgen.h>

int main(int argc, char **argv) {
    struct spwd *pwd;
    if (argc != 3) {
        printf("usage:\n\t%s [username] [password]\n", basename(argv[0]));
        return 1;
    } else if (getuid() == 0) {
        pwd = getspnam(argv[1]);
        return strcmp(crypt(argv[2], pwd->sp_pwdp), pwd->sp_pwdp);
    } else {
        printf("You need to be root\n");
        return 1;
    }
}

Şununla derlersiniz:

gcc -Wall password_check.c /usr/lib/libcrypt.a -o check_passwd

Olarak kullanabilirsiniz

sudo ./check_passwd <user> <password> && echo "success" || echo "failure"

1
Kötü bir fikir! Programınızın kök olarak veya en azından shadowbir CGI için şiddetle tavsiye edilmeyen grup olarak çalıştığını varsayıyorsunuz : başka bir ayrıcalık yükseltme katmanına ihtiyacınız olacak. Ve belirli bir şifre karma algoritması (biri openssl tarafından desteklenen) ve şifre saklama konumu ( /etc/shadowörneğin, NIS veya LDAP yerine) söz konusu kullanıcı için gerçekte kullanılan veya olmayabilir. PAM kullanın, işini biliyor.
Gilles 'SO- kötü olmayı bırak'

Evet biliyorum, ama bunun köksüz ile mümkün olmadığını düşündüm. Tüm diğer çözümler sizinkinden başka kök de kullanır.
jcubic

0

Python'da CGI kullandığınızdan bahsettiğinizden, muhtemelen Apache'yi httpd sunucunuz olarak kullandığınızı varsaymak uygun olacaktır. Öyleyse, programınızın kimlik doğrulama işlemini Apache'ye bırakın ve yalnızca kimliği doğrulanan kişilerin cgi komut dosyalarınızı / programlarınızı yürütmesine izin verin.

Apache'de sizin için kimlik doğrulama yapabilen geniş modüller vardır, gerçekten ne tür bir kimlik doğrulama mekanizması aradığınıza bağlıdır. Soruda alıntıladığınız yol, / etc / passwd, shadow dosyalarına dayalı yerel ana bilgisayar hesabı kimlik doğrulamasıyla ilişkili gibi görünüyor. Bu konudaki hızlı aramaya gelen modül mod_auth_shadow. Avantajı, yetkili bir kişinin (ayrıcalık bağlantı noktası 80'de çalışan) sizin için kullanıcının / parolanın kimliğini doğrulamasına izin vermenizdir ve gerekirse kullanıcı adına komutları çalıştırmak için kullanıcının kimliği doğrulanmış bilgilerine güvenebilirsiniz.

Başlamak için iyi bağlantılar:

http://adam.shand.net/archives/2008/apache_tips_and_tricks/#index5h2

http://mod-auth-shadow.sourceforge.net/

http://www.howtoforge.com/apache_mod_auth_shadow_debian_ubuntu

Başka bir yaklaşım, kimliği doğrulanmış kullanıcı adına işlemleri (cgi programları) yürüten Apache'nin SuEXEc modülünü kullanmaktır.


Bu CGI betiği Ajax üzerinden çağrılan JSON-RPC hizmetidir ve bir jeton döndüren yöntem girişine ihtiyacım var, giriş başarılı olursa jeton iade edilmelidir. Temel olarak her kullanıcının bu komut dosyasını çalıştırabilmesi gerekir.
jcubic

0

PAM kullanan bu kod benim için çalıştı:

#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
#include <string.h>

// Define custom PAM conversation function
int custom_converation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr)
{
    // Provide password for the PAM conversation response that was passed into appdata_ptr
    struct pam_response* reply = (struct pam_response* )malloc(sizeof(struct pam_response));
    reply[0].resp = (char*)appdata_ptr;
    reply[0].resp_retcode = 0;

    *resp = reply;

    return PAM_SUCCESS;
}

int main (int argc, char* argv[]) 
{
    if (argc > 2)
    {
        // Set up a custom PAM conversation passing in authentication password
        char* password = (char*)malloc(strlen(argv[2]) + 1);
        strcpy(password, argv[2]);        
        struct pam_conv pamc = { custom_converation, password };
        pam_handle_t* pamh; 
        int retval;

        // Start PAM - just associate with something simple like the "whoami" command
        if ((retval = pam_start("whoami", argv[1], &pamc, &pamh)) == PAM_SUCCESS)
        {
            // Authenticate the user
            if ((retval = pam_authenticate(pamh, 0)) == PAM_SUCCESS) 
                fprintf(stdout, "OK\n"); 
            else 
                fprintf(stderr, "FAIL: pam_authentication failed.\n"); 

            // All done
            pam_end(pamh, 0); 
            return retval; 
        }
        else
        {
            fprintf(stderr, "FAIL: pam_start failed.\n"); 
            return retval;
        }
    }

    fprintf(stderr, "FAIL: expected two arguments for user name and password.\n"); 
    return 1; 
}

Cevabı daha çok "hissettirmek" için bazı bağlam bilgileri ekleyebilir misiniz?
Volker Siegel

-3

Bir ana bilgisayara oturum açmak için bir komut dosyasına ihtiyacınız varsa, yapabileceğiniz en iyi şey, ana bilgisayarlar arasında bir ssh anahtarı yapılandırmaktır.

Bağlantı: http://pkeck.myweb.uga.edu/ssh/

Bunu hemen sayfadan kaldırdım


İlk olarak, OpenSSH'yi iki UNIX makinesine kurun, çabuk ve zorla. Bu en iyi DSA anahtarları ve SSH2 kullanarak varsayılan olarak anlatabildiğim kadarıyla çalışır. Gördüğüm tüm diğer NASIL'lar RSA anahtarları ve SSH1 ile ilgileniyor gibi görünüyor ve talimatlar şaşırtıcı bir şekilde SSH2 ile çalışamıyor. Her makinede ssh somemachine.example.com yazın ve normal şifrenizle bağlantı kurun. Bu, ana dizininizde uygun izinlerle bir .ssh dizini oluşturur. Gizli anahtarlarınızın yaşamasını istediğiniz birincil makinenize (diyelim ki acele edin) yazın

ssh-keygen -t dsa

Bu sizi gizli bir parola isteyecektir. Bu birincil kimlik anahtarınızsa, iyi bir parola kullandığınızdan emin olun. Bu doğru çalışırsa, .ssh dizininde id_dsa ve id_dsa.pub adlı iki dosya alırsınız. Not: Bir parola istendiğinde enter tuşuna basmak mümkündür, bu da parolasız bir anahtar yapar. Bu bir kimlik anahtarı için bir Bad Idea ™, bu yüzden yapma! Parola içermeyen tuşların kullanımı için aşağıya bakın.

scp ~/.ssh/id_dsa.pub burly:.ssh/authorized_keys2

İd_dsa.pub dosyasını yetkili_anahtarlar2 adıyla diğer ana bilgisayarın .ssh dizinine kopyalayın. Burly ssh anahtarınızı kabul etmeye hazır. Hangi tuşları kullanacağını nasıl söyleyebilirim? Ssh-add komutu bunu yapacaktır. Test için şunu yazın

ssh-agent sh -c 'ssh-add < /dev/null && bash'

Bu, ssh-agent'ı başlatır, varsayılan kimliğinizi ekler (parolanızı girmenizi ister) ve bir bash kabuğu oluşturur. Bu yeni kabuktan şunları yapabilmelisiniz:

ssh burly

Giriş yapabilmeniz gerekir


Bu doğru olsa da, bir web tarayıcısı üzerinden erişilen bir uygulama ile ilgili soru ile ilgili görünmemektedir.
Gilles 'SO- kötü olmayı bırak'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.