Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Phénomène curieux, /etc/passwd réduit à 0

7 réponses
Avatar
François Boisson
Bonjour,


Une ph=E9nom=E8ne curieux aux cons=E9quences peu dr=F4les sur le serveur du
lyc=E9e ce matin. Le 19 janvier vers 17h50-17h53, le fichier passwd a =E9t=
=E9
r=E9duit =E0 n=E9ant (longueur 0). R=E9sultats, plus aucun processus autori=
s=E9s =E0
se lancer, les d=E9mons tournaient toujours mais =E9videmment pas de
ssh/telnet/ftp possible. M=EAme un =ABCtrl-Alt-Del=BB me r=E9pondait un
succulent:

"You don't exist, go away..." (textuel).

Donc reboot sauvage sur CD, fsck de la racine, constatation (et unique
satisfaction) que le diagnostic =E9tait bon, reprise d'un passwd d'un
backup du 14 Janvier (ai je dit que les backups sont vraiment
indispensables) et hop c'est reparti. Reste =E0 comprendre pourquoi:

La machine h=E9brege des comptes courriers, un serveur Web avec forum, un
serveur Samba controleur de domaine, un serveur NFS et un serveur NIS.
Il n'y a pas de shadow, les outils susceptibles de toucher passwd sont
outre passwd sur le serveur (sur lequel personne ne va et n'est all=E9
sauf moi):

nis via yppasswd jamais utilis=E9,
un script cgi perl =E9ditant un nouveau fichier passwd1 et se terminant
par
unlink ($RACINE.$PASS.".old");
rename $RACINE.$PASS , $RACINE.$PASS.".old";
rename $RACINE.$PASS_TMP , $RACINE.$PASS;
chown 0,0,$RACINE.$PASS;
# chmod 0600,$RACINE.$PASS;
chmod 0644,$RACINE.$PASS;

o=F9 $RACINE =3D "/etc", $PASS=3D"passwd" et $PASS_TMP=3D"passwd1".

Ce programme laisse un log d=E8s le d=E9but du processus (succ=E8s ou non).=
Or
rien dans les logs et aucune trace du fichier passwd1 sur /etc.

Vers ces heures l=E0, j'ai constat=E9:

-> la pr=E9sence de nombreuses requ=EAtes sur le forum (ligne du type):

172.207.33.240 - - [19/Jan/2005:17:52:03 +0100] "GET
/phpBB2/viewforum.php?f=3D9&amp;sid=3Dhttp://www.google.fr/search%3f<balise
xss>%22%27 HTTP/1.1" 200 50599

et =E9galement des pages bigbrother indiquant l'=E9tat du r=E9seau et des
machines (cf http://charlemagne.dyndns.org/bb/bb.html) mais ces requ=EAtes
continuent largement apr=E8s que le probl=E8me soit effectivement arriv=E9.

-> Une l=E9g=E8re augmentation de la charge du serveur (en gros elle est
mont=E9e =E0 3)

mis =E0 part =E7a, aucune interruption du service.

-> Le seul =E9v=E8nement marquant semble =EAtre d=E9crit dans le syslog par

Jan 19 17:50:10 yoda ipop3d[31906]: Login user=3Dboisson
host=3Dalf94-3-82-66-248-156.fbx.proxad.net [82.66.248.156] nmsgs=3D7/7

Jan 19 17:50:28 yoda ipop3d[31906]: Logout user=3Dboisson
host=3Dalf94-3-82-66-248-156.fbx.proxad.net [82.66.248.156] nmsgs=3D7
ndele=3D0

(* =E7a c'est fetchmail (chez moi donc par Internet) qui r=E9cup=E8re mon
courrier, passwd existe donc encore *)

Jan 19 17:53:27 yoda mountd[294]: NFS mount of /home attempted from
192.168.1.20 Jan 19 17:53:27 yoda mountd[294]: /home has been mounted by
192.168.1.20=20

(* une machine est bout=E9e sur linux et monte plusieurs r=E9pertoires par
NFS, il se trouve que cette machine a eu son =E9cran chang=E9 et le nouvel
=E9cran ne supporte pas la configuration XFree86, la machine va donc =EAtre
sauvagement =E9teinte 3 minutes plus tard... *)

Jan 19 17:53:29 yoda inetd[8776]: getpwnam: mail: No such user

(* passwd n'existe plus *)

Jan 19 17:53:29 yoda mountd[294]: NFS mount of /home attempted from
192.168.1.25=20

(* le gars essaye d'une autre machine, puis d'une troisi=E8me plus tard *)

Jan 19 17:53:46 yoda inetd[8834]: getpwnam: root: No such user

(* root n'existe plus, passwd est r=E9duit =E0 n=E9ant *)

Les logs de samba montrent que plus personne n'utilisait de machines
sous windows =E0 partir de 16h40.


Bref, je n'ai aucune id=E9e sur la raison de la disparition du fichier
passwd. chkrootkit et mes programmes de surveillance n'indiquent rien
(pas de fichiers modifi=E9s, pas de processus cach=E9s). Personne d'autre
que moi ne s'est loggu=E9 sur le serveur ce jour l=E0, bref je suis
perplexe. Si quelqu'un a une id=E9e de ce qui pourrait s'=EAtre pass=E9, je
suis preneur.


Fran=E7ois Boisson

7 réponses

Avatar
Frederic Grollier
François Boisson a écrit :

[snip]

Même un «Ctrl-Alt-Del» me répondait un
succulent:

"You don't exist, go away..." (textuel).




vraiment ? c'est génial, faut que j'essaie ... :)



Fred (désolé).


--
Pensez à lire la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench

Pensez à rajouter le mot ``spam'' dans vos champs "From" et "Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
David Dumortier
Bonsoir,

François Boisson a écrit :
Bonjour,


Une phénomène curieux aux conséquences peu drôles sur le serveur du
lycée ce matin. Le 19 janvier vers 17h50-17h53, le fichier passwd a été
réduit à néant (longueur 0). Résultats, plus aucun processus autorisés à
se lancer, les démons tournaient toujours mais évidemment pas de
ssh/telnet/ftp possible. Même un «Ctrl-Alt-Del» me répondait un
succulent:



Je crois avoir déjà vu ça. De mémoire, deux explications :
- Partition pleine (tu as dû vérifier)
- /proc/sys/fs/file-max atteint, mais à ma connaissance il laisse des
traces dans syslog, ou au moins dans kern.log|messages|...

"You don't exist, go away..." (textuel).



Un inittab modifié ?
[...]

Bref, je n'ai aucune idée sur la raison de la disparition du fichier
passwd. chkrootkit et mes programmes de surveillance n'indiquent rien
(pas de fichiers modifiés, pas de processus cachés). Personne d'autre
que moi ne s'est loggué sur le serveur ce jour là, bref je suis
perplexe. Si quelqu'un a une idée de ce qui pourrait s'être passé, je
suis preneur.



Je ne vois pas grand chose d'autre, mais la réponse à ta question peut
être effectivement intéressante.

François Boisson



Au fait, les sauvegardes c'est vital.

David Dumortier.



--
Pensez à lire la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench

Pensez à rajouter le mot ``spam'' dans vos champs "From" et "Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
JusTiCe8
Bonsoir,

François Boisson a écrit :

Bonjour,


[...]
unlink ($RACINE.$PASS.".old");
rename $RACINE.$PASS , $RACINE.$PASS.".old";
rename $RACINE.$PASS_TMP , $RACINE.$PASS;
chown 0,0,$RACINE.$PASS;
# chmod 0600,$RACINE.$PASS;
chmod 0644,$RACINE.$PASS;

où $RACINE = "/etc", $PASS="passwd" et $PASS_TMP="passwd1".
[...]




une idée comme ça :

si (justement) passwdl est vide (pour une raison lambda), le rename va
agir comme ilf aut et donc, /etc/passwd sera... vide lui aussi. Ce qui
expliquerai la "disparition" de passwd1.

Pour la pauvre machine ( ;) ) sauvagement éteinte, l'usage des magic
syskey aurait été plus appréciée par celle ci (si activées dans la conf
noyau). Ou une extinction à distance.

François Boisson




A+,

J8.


--
Pensez à lire la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench

Pensez à rajouter le mot ``spam'' dans vos champs "From" et "Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
François Boisson
Le Thu, 20 Jan 2005 19:40:16 +0100
JusTiCe8 a écrit:

Bonsoir,

François Boisson a écrit :

>Bonjour,
>
>
>[...]
>unlink ($RACINE.$PASS.".old");
>rename $RACINE.$PASS , $RACINE.$PASS.".old";
>rename $RACINE.$PASS_TMP , $RACINE.$PASS;
>chown 0,0,$RACINE.$PASS;
># chmod 0600,$RACINE.$PASS;
>chmod 0644,$RACINE.$PASS;
>
>où $RACINE = "/etc", $PASS="passwd" et $PASS_TMP="passwd1".
>[...]
>
>
une idée comme ça :

si (justement) passwdl est vide (pour une raison lambda), le rename va
agir comme ilf aut et donc, /etc/passwd sera... vide lui aussi. Ce qui
expliquerai la "disparition" de passwd1.



Dans ce cas, le script aurait été utilisé et je l'aurais retrouvé d ans
les logs d'apache, je rerecherche...

Bingo...!

172.207.33.240 - - [19/Jan/2005:17:50:49 +0100] "GET
/cgi-bin/script_pwd.cgi?userÞfault&old_pwdÞfault&new_pwd=http://w ww
.google.fr/search%3f<balisexss>%22%27&new_pwd_verÞfault HTTP/1.1" 200
242

ça concorde, par contre je viens de reproduire tel que les différents
appels(il y en a eu 5) au script perl et n'ai eu aucune erreur. Donc
effectivement, l'erreur vient de là mais je ne vois pas comment elle a
pu arriver. (Le script est en fin de message pour les perlophiles)


Pour la pauvre machine ( ;) ) sauvagement éteinte, l'usage des magic
syskey aurait été plus appréciée par celle ci (si activées dans la
conf noyau). Ou une extinction à distance.




Pour l'extinction à distance, sans passwd, pas de connexion possible,
sinon j'aurai directement réglé le pbm. Quant aux magic syskey, je n'y
pense jamais au moment de la configuration du noyau mais c'est une bonne
idée.


François Boisson

---- script Perl pour les amateurs -----
use Time::Local;

print "Content-type: text/htmlnn";

# Get the input
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

@pairs = split(/&/, $buffer);

foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

$FORM{$name} = $value;
}
$RACINE="/etc/";
# $PASS = "shadow";
# $PASS_TMP = "shadow1";
$PASS="passwd";
$PASS_TMP = "passwd1";
$user = $FORM{'user'};
$new_pwd = crypt($FORM{'new_pwd'}, "FB");
$old_pwd = $FORM{'old_pwd'};

print "<HTML>";
print "<HEAD>";
print "<TITLE>Conclusion </TITLE>";
print "</HEAD>";
print "<BODY>";
print "<FONT SIZE=4>";
print "<HR>";

print "<LI>Utilisateur = $user<BR></LI>n";
print "<HR>";
# attend une éventuelle fin
while (-e "/tmp/__script_pwd") {
}
#Path securité
$ex_path = $ENV{"PATH"};
$ENV{"PATH"} = "/bin:/usr/bin";

#let'sgo 1) drapeau
system("touch /tmp/__script_pwd");

open(FIN,">".$RACINE.$PASS_TMP) || die("M'enfin ! Y a un bug !");
open(DEB,$RACINE.$PASS);
$heure = localtime();
$logger = "Appel script_passwd a $heuren";
open(LOG,">>/var/log/motdepasse.log");
print LOG $logger;
close(LOG);
$logger = "Appel sans succesn";
while(<DEB>) {
if (m/^$user:/) {
$ligne = $_;
($qui , $mot ,$fin) = ($ligne =~ /([^:]+):([^:]+):(.*)/);
# print "<LI>",$qui;
# cas d'un changement de mot de passe
$heure = localtime();
if ($mot ne "!") {
$cle = substr ($mot,0,2);
print "<LI>",crypt($old_pwd,$cle),"<BR></LI>n";
$logger = "Changement pour $qui a $heuren";
}
# sinon utilisateur sans mot de passe
else { print "<LI>Creation d'un mot de passe (circonstances
enregistrees)<BR></LI>n";
print "<LI> origine: machine $ENV{'REMOTE_ADDR'} heure
$heure<BR></LI>n";
$logger = "Creation pour $qui par$ENV{'REMOTE_ADDR'} a $heuren";
}
if ((($mot eq crypt($old_pwd,$cle)) || ($mot eq"!")) &&
($FORM{'new_pwd'} eq $FORM{'new_pwd_ver'})) {
print "<LI>Changement de mot de passe de",$user,"<BR></LI>n";
$logger = "OK: ".$logger;
print FIN $qui,":",$new_pwd,":",$fin,"n";
}
else { print FIN $ligne;}
}
else { print FIN };
}
print "<LI>Si il y a eu changement de mot de passe, cela est ecrit
ci-dessus sinon refaire la manoeuvre<BR></LI>";
close(FIN);
close(DEB);
# affichage environnement
open(LOG,">>/var/log/motdepasse.log");
print LOG $logger;
close(LOG);
#print "<HR>";
#while (($key,$val) = each %ENV) {
# print "<LI>$key =$val<BR></LI>n";}

print "<HR>";
unlink ($RACINE.$PASS.".old");
rename $RACINE.$PASS , $RACINE.$PASS.".old";
rename $RACINE.$PASS_TMP , $RACINE.$PASS;
chown 0,0,$RACINE.$PASS;
# chmod 0600,$RACINE.$PASS;
chmod 0644,$RACINE.$PASS;
#$ex_path = $ENV{"PATH"};
#$ENV{"PATH"} = "/bin:/usr/bin";
#while (($key,$val) = each %ENV) {
# print "<LI>$key =$val<BR></LI>n";}

#print "<HR>";

chdir "/var/yp";
system ("make > /dev/null");
# OK, c'est bon
unlink "/tmp/__script_pwd";
$ENV{"PATH"} = $ex_path;
print "</FONT>";
print "</BODY>";
print "</HTML>";
Avatar
François Boisson
Le Thu, 20 Jan 2005 19:31:53 +0100
David Dumortier a écrit:

Je crois avoir déjà vu ça. De mémoire, deux explications :
- Partition pleine (tu as dû vérifier)
- /proc/sys/fs/file-max atteint, mais à ma connaissance il laisse des
traces dans syslog, ou au moins dans kern.log|messages|...



Non, j'ai vérifié, rien de cela, si le phénomène déclencheur est trouvé
(script dans message précédent), la raison exacte n'est pas connue
(erreur à l'écriture du fichier peut être?).



> "You don't exist, go away..." (textuel).

Un inittab modifié ?



Non, message logique, shutdown doit vérifier qu'il est lancé par un
ayant droit donc rechercher l'uid dans le passwd, si il ne trouve
pas l'utilisateur, root ou pas il l'envoit paître par ce message.

On retrouve la chaine «You don't exist. Go away.» dans /sbin/shutdown
(essaye avec strings!).


François Boisson
Avatar
Yves Rutschle
Salut,

Je vois deux problèmes potentiels:

# attend une éventuelle fin
while (-e "/tmp/__script_pwd") {
}
#Path securité
$ex_path = $ENV{"PATH"};
$ENV{"PATH"} = "/bin:/usr/bin";

#let'sgo 1) drapeau
system("touch /tmp/__script_pwd");



Ok, tu t'es protégé contre plusieurs exécutions de ton
script; mais que ce passe-t-il si un autre processus écrit
dans le fichier? AMA il faudrait au moins flock-er le
fichier.

print FIN $qui,":",$new_pwd,":",$fin,"n";



Potentiellement, le print peut échouer (cas de disque plein
par exemple).

Et enfin:

1> unlink ($RACINE.$PASS.".old");
2> rename $RACINE.$PASS , $RACINE.$PASS.".old";
3> rename $RACINE.$PASS_TMP , $RACINE.$PASS;
4> chown 0,0,$RACINE.$PASS;

Entre la ligne 2 et la ligne 3, il n'y a plus de fichier
/etc/passwd. Si un autre programme suit le même algorithme
et lit /etc/passwd entre ces deux lignes, il viendra ensuite
réécrire un /etc/passwd vide. Je changerais ça en:

1> unlink ($RACINE.$PASS.".old");
2> copy $RACINE.$PASS , $RACINE.$PASS.".old";
3> rename $RACINE.$PASS_TMP , $RACINE.$PASS;
4> chown 0,0,$RACINE.$PASS;

(rename est garanti atomique, donc ne pose pas de problèmes
de concurrence).

Cela dit, si un autre programme a modifié /etc/passwd entre
le moment où tu l'as ouvert et le moment où tu execute la
ligne 4, tu vas perdres ces modifications...

En fait, considérant l'importance de /etc/passwd, j'aurais
tendance à réécrire le script entièrement en utilisant
putpwent, qui, je suppose, prend toutes les précautions
nécessaires. Ou bien en appellant passwd par le shell.

Y.


--
Pensez à lire la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench

Pensez à rajouter le mot ``spam'' dans vos champs "From" et "Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
François Boisson
Le Fri, 21 Jan 2005 02:00:29 +0000
Yves Rutschle a écrit:

Salut,




Ok, tu t'es protégé contre plusieurs exécutions de ton
script; mais que ce passe-t-il si un autre processus écrit
dans le fichier? AMA il faudrait au moins flock-er le
fichier.



Il ne doit pas y avoir d'autres processus qui écrivent dans ce fichier
en théorie, cela dit j'y avais pensé mais mettre un flock ne fait que
reculer le pbm, puisqu'il faut bien clore le fichier avant les
manoeuvres de rename/copy et il y aura un intervalle entre la fermeture
du fichier et le changement effectif. Or je tiens à ne pas éditer
directement le fichier pour conserver une copie au cas où(ça m'a servi
d'ailleurs:-))


> print FIN $qui,":",$new_pwd,":",$fin,"n";

Potentiellement, le print peut échouer (cas de disque plein
par exemple).



Exact, mais si / est plein, le serveur est mal et dans ce cas, le script
échoue et /etc/passwd reste dans sa version originale. Simplement,
le script est bloqué puisqu'il subsiste le verrou /tmp/__script_pwd.
(cela dit, en l'occurrence, le disque n'était pas plein)


Et enfin:

1> unlink ($RACINE.$PASS.".old");
2> rename $RACINE.$PASS , $RACINE.$PASS.".old";
3> rename $RACINE.$PASS_TMP , $RACINE.$PASS;
4> chown 0,0,$RACINE.$PASS;

Entre la ligne 2 et la ligne 3, il n'y a plus de fichier
/etc/passwd. Si un autre programme suit le même algorithme
et lit /etc/passwd entre ces deux lignes, il viendra ensuite
réécrire un /etc/passwd vide. Je changerais ça en:

1> unlink ($RACINE.$PASS.".old");
2> copy $RACINE.$PASS , $RACINE.$PASS.".old";
3> rename $RACINE.$PASS_TMP , $RACINE.$PASS;
4> chown 0,0,$RACINE.$PASS;



Modifications faites, merci de la suggestion. Pour l'histoire, à
l'époque où j'avais fait le script, je ne savais pas qu'il fallait faire
un

use File::Copy;

pour utiliser la fonction copie de fichier d'où ces unlink/rename.


Cela dit, si un autre programme a modifié /etc/passwd entre
le moment où tu l'as ouvert et le moment où tu execute la
ligne 4, tu vas perdres ces modifications...



En fait, considérant l'importance de /etc/passwd, j'aurais
tendance à réécrire le script entièrement en utilisant
putpwent, qui, je suppose, prend toutes les précautions
nécessaires. Ou bien en appellant passwd par le shell.




Là encore, j'ai appris après la rédaction du script qu'effectivement, il
y avait moyen de passer un mot de passe à passwd en ligne de commande
(option--stdin) et donc de s'en sortir par ce biais. Tu as sans doute
raison mais j'ai une certaine flemme...

Merci des tuyaux


François Boisson