<![CDATA[Latest posts for the topic "Linux Execute-only binary vulnerability ?"]]> /hvaonline/posts/list/24.html JForum - http://www.jforum.net Linux Execute-only binary vulnerability ? Code:
int main(int argc, char* argv[]) {
  int a = 1;
  int b = 1;
  char x = 'A';
  char y = 'B';
  return 0;
}
Compile : gcc -o test test.c Sau đó mình tạo một user mới và copy file "test" này vào home folder của user này, chmod +s và remove read perm chgrp thành user. Sau khi làm xong thì nó trông như thế này : Code:
-rws--x--x 1 windak user    6255 2009-10-25 02:50 test
Login thử vào bằng user : "user" và "cat test" -> permission denied, thử gdb : ...(gdb) disass main ...No symbol table is loaded thử execute ./test -> ok Như mọi người biết, 1 khi một chương trình được execute thì nó sẽ được load vào memory, như vậy trên lí thuyết nếu ta execute cái binary này và read từ memory ra, ta sẽ có thể dumb được source của nó ==> READ được nó ?!!?? Mình nghi ngờ với khả năng này, do cũng chưa bao h liếc qua cái source kernel... Thế là test thử : Vẫn là quyền của "user" mình tạo file này : Code:
#include <stdio.h>                                      
#include <stdlib.h>                                     
#include <signal.h>                                     
#include <syscall.h>                                    
#include <sys/ptrace.h>                                 
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <unistd.h>
#include <errno.h>
int main(void) 
{                                                                                                                                                                                                          
        long long counter = 0;  /*  machine instruction counter */
        int wait_val;           /*  child's return value        */
        int pid;                /*  child's process id          */

        puts("Please wait");
        struct user_regs_struct regs;
        long ins;                    

        switch (pid = fork()) {
        case -1:               
                perror("fork");
                break;         
        case 0: /*  child process starts        */
                ptrace(PTRACE_TRACEME, 0, 0, 0);
                
                execl("/home/user/test", "test", NULL);
                
                break;
                /*  child process ends  */
        default:/*  parent process starts       */
                wait(&wait_val);
                /*
                 *   parent waits for child to stop at next
                 *   instruction (execl())
                 */
                while (wait_val == 1407 ) {
                        counter++;
                        if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
                                perror("ptrace");
                        if (ptrace(PTRACE_GETREGS,pid,0,®s)!=0){
                         // perror("ptrace");
                        }
                        else {
                                ins = ptrace(PTRACE_PEEKTEXT, pid,
                                 regs.eip, NULL);

                                printf("Instruction executed: %lx\n", ins);
                        }
                        wait(&wait_val);
                        /*   wait for next instruction to complete  */
                }
                /*
                 * continue to stop, wait and release until
                 * the child is finished; wait_val != 1407
                 * Low=0177L and High=05 (SIGTRAP)
                 */
        }
        printf("Number of machine instructions : %lld\n", counter);
        return 0;
}
code này mình chép từ đây : http://tldp.org/LDP/LG/issue81/sandeep.html có chỉnh sửa một chút compile : gcc -o ptrace ptrace.c Đoạn code trên của mình thật ra chỉ làm mỗi công việc là debug cái file test sau khi nó được nhét vào memory và in ra nó đang execute đoạn mã nào. Sau đấy mình run thử user@windak-pc$ ./ptrace > see windak@windak-pc$./ptrace > how Đồng thời trên 1 terminal khác dưới quyền "windak" mình run : Code:
gdb test
(gdb) disass main
Dump of assembler code for function main:
0x0804831c <main+0>:    push   %ebp
0x0804831d <main+1>:    mov    %esp,%ebp
....
0x08048338 <main+28>:   movl   $0x1,-0x4(%ebp)
0x0804833f <main+35>:   movl   $0x1,-0x8(%ebp)
0x08048346 <main+42>:   movb   $0x41,-0x9(%ebp)
0x0804834a <main+46>:   movb   $0x42,-0xa(%ebp)
0x0804834e <main+50>:   mov    $0x0,%eax
0x08048353 <main+55>:   leave
0x08048354 <main+56>:   ret
(gdb) x/20 0x0804831c
0x804831c <main>:       0x83e58955      0xe48318ec      0x0000b8f0      0xc0830000
0x804832c <main+16>:    0x0fc0830f      0xc104e8c1      0xc42904e0      0x01fc45c7
0x804833c <main+32>:    0xc7000000      0x0001f845      0x45c60000      0x45c641f7
0x804834c <main+48>:    0x00b842f6      0xc9000000      0x909090c3      0x90909090
0x804835c:      0x90909090      0x5de58955      0x26748dc3      0x27bc8d00
Và thật ngạc nhiên... mình cũng tìm được đoạn code sau trong cả see và how : Code:
Instruction executed: 83e58955
Instruction executed: ec83e589
Instruction executed: 8318ec83
Instruction executed: b8f0e483
Instruction executed: b8
Instruction executed: 830fc083
Instruction executed: c10fc083
Instruction executed: c104e8c1
Instruction executed: 2904e0c1
Instruction executed: 45c7c429
Instruction executed: 1fc45c7
Instruction executed: 1f845c7
Instruction executed: 41f745c6
Instruction executed: 42f645c6
Instruction executed: b8
Instruction executed: 9090c3c9
Instruction executed: 909090c3
Như vậy có thât sự đã "READ" được nó ?!? .. Liệu đây có phải là một bug của Linux kernel hay mình đang mơ ngủ =,,= nhầm lẫn chỗ nào đó.... Đây là thông số máy của mình Code:
$ uname -a
Linux windak-pc 2.6.28-11-generic #42-Ubuntu SMP Fri Apr 17 01:57:59 UTC 2009 i686 GNU/Linux
$ gcc -v
Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++,f77,pascal --prefix=/usr --libexecdir=/usr/lib --with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --program-suffix=-3.4 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --with-tune=pentium4 i486-linux-gnu
Thread model: posix
gcc version 3.4.6 (Ubuntu 3.4.6-1ubuntu2)
Giờ đi ngủ, hi vọng mai tỉnh táo sẽ xem xét lại lần nữa. Mọi người xem cùng nhé. wd. ]]>
/hvaonline/posts/list/31853.html#196651 /hvaonline/posts/list/31853.html#196651 GMT
Linux Execute-only binary vulnerability ? /hvaonline/posts/list/31853.html#196750 /hvaonline/posts/list/31853.html#196750 GMT Linux Execute-only binary vulnerability ? /hvaonline/posts/list/31853.html#196761 /hvaonline/posts/list/31853.html#196761 GMT Linux Execute-only binary vulnerability ?

WinDak wrote:
:) Hi StarGhost, Mình cũng không nghĩ cái này là bug của Linux mà là do design, chỉ càm thấy nó hơi nonsense và unrational một tí vì vẫn leak được sau khi mà loại bỏ cái read permission đi. Từ đó vẫn còn thắc mắc trong đầu lý do nào phần code/data segment của nó trong memory lại không được bảo vệ ? Liệu có phải là do khó khăn trong design hay là sự bất cẩn ?  
Mình nghĩ do thằng ptrace thôi]]>
/hvaonline/posts/list/31853.html#196828 /hvaonline/posts/list/31853.html#196828 GMT
Linux Execute-only binary vulnerability ? /hvaonline/posts/list/31853.html#196853 /hvaonline/posts/list/31853.html#196853 GMT Linux Execute-only binary vulnerability ? Mình nghĩ do thằng ptrace thôi   @gamma : rất có thể là khả năng này, ptrace là kernel function như vậy nghĩa là người develop nó không check quyền của user đang execute ? nếu có thời gian tớ sẽ ngó qua thử cái này. Một cái nữa mình đã thử là thử fopen(/etc/shadow) khi đang ptrace thì bị block ngay tại trận, như vậy ptrace không care đến cái SUID mà mình đã set. Kết luận đến đây: Nếu có những thông tin private, cách tốt nhất là tạo file riêng và set permission cho nó, không nên để trong file binary. wd.]]> /hvaonline/posts/list/31853.html#196887 /hvaonline/posts/list/31853.html#196887 GMT Linux Execute-only binary vulnerability ?

WinDak wrote:
Một cái nữa mình đã thử là thử fopen(/etc/shadow) khi đang ptrace thì bị block ngay tại trận, như vậy ptrace không care đến cái SUID mà mình đã set. 
Không hiểu câu này của bạn. Bạn cơ bản không thể ptrace() được process có suid hoặc sgid, trừ phi process của bạn có euid là root. Một ví dụ điển hình là khi dùng gdb để debug suid/sgid programs. Nếu bạn muốn dấu algorithm này kia thì mình có một cách này. Đầu tiên bạn viết program của bạn như bình thường. Sau đó set permission cho nó, ví dụ 700, trong đó owner là bạn. Sau đó bạn viết một suid program khác gọi cái program này (dùng execve()).]]>
/hvaonline/posts/list/31853.html#196899 /hvaonline/posts/list/31853.html#196899 GMT
Linux Execute-only binary vulnerability ?

StarGhost wrote:

WinDak wrote:
Một cái nữa mình đã thử là thử fopen(/etc/shadow) khi đang ptrace thì bị block ngay tại trận, như vậy ptrace không care đến cái SUID mà mình đã set. 
Không hiểu câu này của bạn. Bạn cơ bản không thể ptrace() được process có suid hoặc sgid, trừ phi process của bạn có euid là root. Một ví dụ điển hình là khi dùng gdb để debug suid/sgid programs.  
Không phải không thể, như bạn xem kỹ bài ở trên mình vẫn có thể ptrace được SUID program, trong khi ptrace của tớ euid là "user". Vấn đề là khi đó thì euid mình vẫn chỉ là euid của ptrace chứ không được copy từ SUID của process child.

StarGhost wrote:
Nếu bạn muốn dấu algorithm này kia thì mình có một cách này. Đầu tiên bạn viết program của bạn như bình thường. Sau đó set permission cho nó, ví dụ 700, trong đó owner là bạn. Sau đó bạn viết một suid program khác gọi cái program này (dùng execve()). 
Theo lý thuyết đây chắc là 1 cách :D. Mình sẽ thử nghiệm Thanks. wd. ]]>
/hvaonline/posts/list/31853.html#196900 /hvaonline/posts/list/31853.html#196900 GMT
Linux Execute-only binary vulnerability ?

WinDak wrote:
Không phải không thể, như bạn xem kỹ bài ở trên mình vẫn có thể ptrace được SUID program, trong khi ptrace của tớ euid là "user". Vấn đề là khi đó thì euid mình vẫn chỉ là euid của ptrace chứ không được copy từ SUID của process child. 
Như vậy thì có gì mâu thuẫn? Nếu bạn gọi ptrace() trước, thì process sẽ không có suid/sgid. Nếu process đã có suid/sgid rồi, thì bạn không thể ptrace() được nữa. Đây là nguyên tắc security cho ptrace().]]>
/hvaonline/posts/list/31853.html#196911 /hvaonline/posts/list/31853.html#196911 GMT
Linux Execute-only binary vulnerability ?

StarGhost wrote:

WinDak wrote:
Không phải không thể, như bạn xem kỹ bài ở trên mình vẫn có thể ptrace được SUID program, trong khi ptrace của tớ euid là "user". Vấn đề là khi đó thì euid mình vẫn chỉ là euid của ptrace chứ không được copy từ SUID của process child. 
Như vậy thì có gì mâu thuẫn? Nếu bạn gọi ptrace() trước, thì process sẽ không có suid/sgid. Nếu process đã có suid/sgid rồi, thì bạn không thể ptrace() được nữa. Đây là nguyên tắc security cho ptrace(). 
Có ai nói mâu thuẫn gì đâu :D, vì chưa hiểu ý StarGhost là sau khi run thì mới ptrace, cái này mình chưa thử, nếu ptrace trước thì sẽ chạy được, như ở trên đã trình bày. Câu hỏi ở đây là lí do gì ptrace vẫn có khả năng trace vào memory của process ? Nếu protect process memory đi trong trường hợp này thì sẽ hợp lí hơn. Vừa search ra cái này http://www.quantumg.net/sudojump.php mọi người xem cùng chơi. wd. ]]>
/hvaonline/posts/list/31853.html#196913 /hvaonline/posts/list/31853.html#196913 GMT
Linux Execute-only binary vulnerability ? Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
   int a = 1;
   int b = 1;
   char x = 'A';
   char y = 'B';
   int euid, uid;
   euid = geteuid();
   uid = getuid();
   printf("euid: %d\nuid: %d\n",euid,uid);
   sleep(100000);
   exit(EXIT_SUCCESS);
}
output: Code:
root@bsd# ls -l /tmp/test
-rws--x--x  1 puffy  monkey  6704 Oct 28 14:09 /tmp/test*
root@bsd# /tmp/test
euid: 0
uid: 0
^C
root@bsd# su -l monkey
-bash-3.2$ /tmp/test
euid: 1000
uid: 1000
^C
-bash-3.2$ logout
root@bsd# su -l puffy
-bash-3.2$ /tmp/test
euid: 1002
uid: 1002
^C
-bash-3.2$
- Ông xác định mấy thứ sau: cái ptrace của ông khi ông invoke nó với user 'windak' thì nó có euid là gì ? Sau khi ptrace fork thì child process của ông có euid là gì. Child process của ptrace gọi execl() thì process image của nó được thay bởi test, tuy nhiên cái program test này của ông không thực sự change cái euid của nó, nên nó vẫn có euid là id của user 'windak'. Vậy có gì mà parent process k0 access đc memory của nó. - Tương tự ông thử xác định xem khi ông invoke cái program ptrace kia với account là 'user' thì cuối cùng cái euid của program 'test' có được change thành id của windak k0, hay vẫn là id của 'user' ?]]>
/hvaonline/posts/list/31853.html#196919 /hvaonline/posts/list/31853.html#196919 GMT
Linux Execute-only binary vulnerability ? /hvaonline/posts/list/31853.html#196922 /hvaonline/posts/list/31853.html#196922 GMT Linux Execute-only binary vulnerability ? /hvaonline/posts/list/31853.html#196927 /hvaonline/posts/list/31853.html#196927 GMT Linux Execute-only binary vulnerability ?

StarGhost wrote:
@puffy: cái vụ seteuid() của bạn mình không đồng ý nhé. Không biết bsd kernel hoạt động ra sao, chứ trong linux thì chả cần seteuid(), chỉ cần SUID bit được set trong file permission thi khi file đó được chạy, euid sẽ tự động được set luôn thành file owner. 
Confirm đúng như StarGhost nói khi chạy trên máy mình. Cũng cám ơn bác puffy, nhờ vậy biết linux != bsd chỗ này, trước giờ tưởng như nhau hệch hệch :-) Code:
cat test.c
int main(int argc, char* argv[]) {
  int a = 1;
  int b = 1;
  char x = 'A';
  char y = 'B';
  printf ("Euid : %d, ID: %d \n", geteuid(), getuid());
  return 0;
}
....
windak@windak-pc$./test
Euid : 1000, ID: 1000
....
user@windak-pc$./test
Euid : 1000, ID: 1001
Ngoài ra cách xử dụng wrap của StarGhost Code:
int main(){
  execl("/home/user/test","test",0);
  return 0;
}
gcc -o wrap wrap.c ls -al : Code:
-rwx------ 1 windak windak    6582 2009-10-28 20:27 test
-rws--x--x 1 windak user    6368 2009-10-28 20:31 wrap
cũng rất hiệu quả O-) Code:
user@windak-pc$./wrap
Euid : 1000, ID: 1001
user@windak-pc$./ptrace
Please wait...
Number of machine instructions : 115862
...
windak@windak-pc$./ptrace
Please wait...
Euid : 1000, ID: 1000
Number of machine instructions : 237642
Thanks các bác wd.]]>
/hvaonline/posts/list/31853.html#196941 /hvaonline/posts/list/31853.html#196941 GMT