Skip to content

Add Gogs rebase RCE exploit module#21515

Open
jburgess-r7 wants to merge 3 commits into
rapid7:masterfrom
jburgess-r7:add-gogs-rebase-rce
Open

Add Gogs rebase RCE exploit module#21515
jburgess-r7 wants to merge 3 commits into
rapid7:masterfrom
jburgess-r7:add-gogs-rebase-rce

Conversation

@jburgess-r7
Copy link
Copy Markdown
Contributor

Adds an exploit module for an argument injection vulnerability in the pull request merge flow of Gogs (<= 0.14.2 and 0.15.0+dev).

The Merge() function in internal/database/pull.go passes the PR base branch name to git rebase without a -- separator. A branch named --exec=<CMD> is parsed by Git as the --exec flag rather than a positional argument, causing sh -c <CMD> to run after each replayed commit during the rebase.

Any authenticated user who can create a repository (the default configuration) can exploit this — no interaction from other users is required.

  • GHSA: GHSA-qf6p-p7ww-cwr9
  • Blog: Technical Analysis
  • Affected: Gogs <= 0.14.2 and 0.15.0+dev
  • Targets: Unix Command, Linux Dropper, Windows Command, Windows Dropper
  • Exploit methods: own_repo (creates temp repo, default) and existing_repo (targets a repo the attacker has write access to)

Verification

  • Start msfconsole
  • use exploit/multi/http/gogs_rebase_rce
  • set RHOSTS <target>
  • set USERNAME <gogs_user>
  • set PASSWORD <gogs_password>
  • set LHOST <your_ip>
  • check — should detect Gogs version
  • run — should get a shell as the Gogs process user
  • Verify cleanup deletes the temporary repository
  • set EXPLOIT_METHOD existing_repo
  • set REPO_OWNER <owner> / set REPO_NAME <repo>
  • run — should get a shell; cleanup deletes branches and closes the PR
  • set TARGET 2 (Windows Command) — repeat against a Windows Gogs instance
  • Verify msftidy, rubocop, and msftidy_docs pass with no offenses

Copy link
Copy Markdown
Contributor

@cdelafuente-r7 cdelafuente-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jburgess-r7 for this great PR, here is today's first review. I'll go over the code again and test it ASAP.

Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Comment thread modules/exploits/multi/http/gogs_rebase_rce.rb Outdated
Changes requested by @cdelafuente-r7:
- Remove require 'open3' (autoloaded in framework)
- Remove include Msf::Exploit::CmdStager and Linux Dropper target;
  use fetch payloads instead (FETCH_COMMAND: WGET for Unix, CURL for
  Windows)
- Remove hardcoded PAYLOAD default; let framework auto-select fetch
  payload
- Add ['linux', 'unix'] Platform to Unix Command target
- Add conditions: to REPO_OWNER and REPO_NAME options
- Remove hardcoded send_request_cgi timeouts (kept 5s on merge
  trigger to avoid blocking on payload execution)
- Replace regex CSRF extraction with Nokogiri XPath via
  res.get_html_document
- Use target['Type'] for dispatch instead of sentinel instance
  variable
- Add layered report_service with :parents (tcp -> http -> gogs)

Additional improvements:
- Remove Windows Dropper target (same fetch rationale as Linux Dropper)
- Simplify Arch to ARCH_CMD (dropper arches no longer needed)
- Remove execute_command method (was for CmdStager)
- Update module description to remove stale CmdStager/dropper
  references
- Update documentation: remove Linux Dropper scenario, fix Windows
  target index
## Vulnerable Application

This module exploits an argument injection vulnerability in the pull request merge flow
of [Gogs](https://github.com/gogs/gogs) (<= 0.14.2 and 0.15.0+dev).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
of [Gogs](https://github.com/gogs/gogs) (<= 0.14.2 and 0.15.0+dev).
of [Gogs](https://github.com/gogs/gogs) (<= 0.14.2 and <= 0.15.0+dev).

Comment on lines +134 to +151
# Maps CSS/JS commit hashes to Gogs release versions for fingerprinting.
# The hash appears in the ?v= parameter of static asset URLs on unauthenticated pages.
COMMIT_TO_VERSION = {
'5dcb6c64bdf61e38dbdbb941c1d69789c560d0fb' => '0.14.2',
'f5c8030c1fd936f3e0e9f774e3c7c39fd102f56f' => '0.14.1',
'36c26c4ccc3ca0339db53eb1fa41e4e86b55163d' => '0.14.0',
'd958a47a0e9d8747e399c687fdb3ec64a3b1a736' => '0.13.4',
'5084b4a9b77a506f5e287e82e945e1c6882b827a' => '0.13.3',
'593c7b6db601c68d16b2fb9a7e1194cb816f5efb' => '0.13.2',
'0c40e600a275d490481cfeea53705810fbe94d9b' => '0.13.1',
'8c21874c00b6100d46b662f65baeb40647442f42' => '0.13.0',
'c9fba3cb30af0789fcf89098dfcb8f2286ee7d3b' => '0.12.11',
'1ce5171ae170750298c150874e718740dd7ef69f' => '0.12.10',
'012a1ba19ed2f8f5185be4254f655ba6c4b34db2' => '0.12.9',
'7f8799c01f264eb7770766621fb68debee414b68' => '0.12.8',
'd06ba7e527fcc462aecdb660ce001e87d94f024c' => '0.12.7',
'26395294bdef382b577fd60234e5bb14f4090cc8' => '0.12.6'
}.freeze
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this should go into a dedicated file, like lib/msf/core/exploit/remote/http/gitlab/version.rb does it for gitlab, otherwise it'll invariably result in duplication at some point. Same for the helpers methods that should likely be into a dedicated file

)
return CheckCode::Unknown('Target did not respond.') unless res

unless res.body.to_s.match(%r{<meta +name="author" +content="Gogs" */>})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unless res.body.to_s.match(%r{<meta +name="author" +content="Gogs" */>})
unless res.body.to_s.match(%r{<meta +name="author" +content="Gogs"})

No need to keep matching

return CheckCode::Safe('Target does not appear to be running Gogs.')
end

report_service(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make sense to report the service with its version if the version can be detected

Comment on lines +24 to +27
**Important**: A successful rebase merge may leave the server-side repository in a
corrupted git state (mid-rebase). For `own_repo` this is inconsequential because the
repository is deleted during cleanup. For `existing_repo`, this can break the target
repository for legitimate users and prevents re-exploitation against the same repo.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be fixed by prepending git rebase --abort to the payload?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

5 participants