Vulnerability / Bug involving Doombringer's Doombringer

While browsing Roblox’s notable accessories I’ve stumbled upon a weird issue involving Doombringer’s Doombringer.
Doombringer’s Doombringer contains 2 scripts, the bucketscript and the targetscript (shown in the image below):
img

When Doombringer’s Doombringer is added into the game (i.e. wore by someone, or used in a game where you can equip catalog accessories) the 2 scripts get executed. This isn’t a bug on its own, but an issue arises because of how the bucketscript works.

When the bucketscript is loaded into the game it first checks if SatDeployed exists in workspace and if it doesn’t, it creates it (snippet of the script below):

-----MrDoomBringer
print("Satellite sniper script") --Look for the sat in the workspace
sat = game.Workspace:FindFirstChild("SatDeployed")
if (sat == nil) then
    print("The satellite has not been found, creating..") --If the sat is not in the workspace, then this creates it.
    sat = Instance.new("Part")
    sat.Size = Vector3.new(5, 16.8, 5)
    sat.Position = Vector3.new(100, 3e+003, 0)
    sat.Name = "SatDeployed"
    sat.Parent = game.Workspace
    print("Part has been made") --This part creates the BodyGyro object
    bodygyronew = Instance.new("BodyGyro")
    bodygyronew.maxTorque = Vector3.new(0, 4e+005, 4e+005)
    bodygyronew.D = 500
    bodygyronew.P = 3e+003
    bodygyronew.Parent = sat
    print("BodyGyro has been made") --This part creates the BodyPosition to keep the sat stable
    bodyposnew = Instance.new("BodyPosition")
    bodyposnew.D = 3e+003
    bodyposnew.maxForce = Vector3.new(4e+006, 4e+006, 4e+006)
    bodyposnew.position = Vector3.new(100, 3e+003, 0)
    bodyposnew.Parent = sat
    print("BodyPosition has been made") --I'd try to put in the satellite mesh, but the MeshId is a "Content" property that doesn't like to be set. --From now on the script proceedes to use the "sat" object created here. It's a global value, so it'll remain --All the other variables for the creation of the supporting children don't matter.
end

The main issue here being that only MrDoomBringer should be allowed to utilize the sat / SatDeployed part in any capacity. Due to this oversight and that because the sat part is not being anchored, this allows exploiters to teleport to it and gain network ownership over it. This allows the exploiter to effectively control the sat. With the power to control the sat the exploiter may kill / fling other people, block entrances, move people, fly even when the game has a server sided anti cheat (since the sat is a part on the server most anti cheats will think it’s okay and normal). It doesn’t matter if the game has collision on or off for player characters either since the part has collision on by default. To add, the part isn’t small and is about 3 times taller than the default Roblox character (as shown here).

I have privately tested this and it does in fact work, but I will not be releasing the script publicly, at least for now.

Expected behavior

The expected behavior would mean the sat / SatDeployed part would only get created and used by MrDoomBringer himself as intended in the script.

A private message is associated with this bug report

5 Likes

Important to note it is only owned by 4 people who can wear it in any game that doesn’t use custom characters; Merely, Shedletsky, a Reverse_Polarity alt named SlingshotJunkie and MrDoombringer themselves.

1 Like

It’s important to note that this is an “Admin item” similar to the Teapot Turret, Bunny Ears of Caprice, and other admin-only items, it is not intended to be equipped by non-admins. This is not a problem with the item, but a problem of some games allowing any user to equip any accessory or item. This problem can be fixed by simpling disabling these specific items for normal players.

In cases of exploiters equipping this item locally (which is what I think you are getting at here), this isn’t the only issue regarding exploits of this nature and instead of bandaid patching a single problem like this we need a more comprehensive solution.

1 Like

I understand this is an Admin only item and that it has little to no owners, but the main issue is that many games, even big ones such as catalog avatar creator, a front page game allow you to equip this item and kill people with exploits by flinging them with the SatDeployed part. Also, I am not getting at exploiters’ ability to equip it locally since that wouldn’t cause any harm to the game.

1 Like

This is a problem created by allowing any user to equip any accessory then. Bug reports are for the Roblox platform and systems as a whole, not specific games. This is a pretty easy issue to fix for these experiences.

2 Likes

This is clearly a bug. If you read the bucketscript and the targetscript you’d understand that only MrDoomBringer should be allowed to use the SatDeployed part. The SatDeployed part is only created to be utilized in specific ways by MrDoomBringer himself.

1 Like

It would have been more helpful if you included the check function in the code sample you provided in order to show that this function was only intended for MRDOOMBRINGER and not all users wearing the accessory.

I’ll work on making some more modern scripts for this

3 Likes

Sorry for the misunderstanding, I’ll edit my original post.

2 Likes

The following changes to the scripts would fix this:

bucketscript:

-----MrDoomBringer


--Look for the sat in the workspace
local sat = game.Workspace:FindFirstChild("SatDeployed")


local character = script:FindFirstAncestorWhichIsA("Model") -- if you insert the hat as a model you will need to use the parent of this instead
if character and character:FindFirstChild("Humanoid") ~= nil then
	playerObj = game.Players:FindFirstChild(character.Name)
	if check(playerObj.UserId) then
		print("Satellite sniper script")
		if (sat == nil) then
			print("The satellite has not been found, creating..")
			--If the sat is not in the workspace, then this creates it.
			local sat = Instance.new("Part")
			sat.Size = Vector3.new(5, 16.8, 5)
			sat.Position = Vector3.new(100, 3e+003, 0)
			sat.Name = "SatDeployed"
			sat.Parent = game.Workspace
			print("Part has been made")
			--This part creates the BodyGyro object
			local bodygyronew = Instance.new("BodyGyro")
			bodygyronew.maxTorque = Vector3.new(0, 4e+005, 4e+005)
			bodygyronew.D = 500
			bodygyronew.P = 3e+003
			bodygyronew.Parent = sat
			print("BodyGyro has been made")
			--This part creates the BodyPosition to keep the sat stable
			local bodyposnew = Instance.new("BodyPosition")
			bodyposnew.D = 3e+003
			bodyposnew.maxForce = Vector3.new(4e+006, 4e+006, 4e+006)
			bodyposnew.position = Vector3.new(100, 3e+003, 0)
			bodyposnew.Parent = sat
			print("BodyPosition has been made")
			--I'd try to put in the satellite mesh, but the MeshId is a "Content" property that doesn't like to be set.
			--From now on the script proceedes to use the "sat" object created here. It's a global value, so it'll remain
			--All the other variables for the creation of the supporting children don't matter.
		end
		game.Players.PlayerAdded:connect(onPlayerEntered)
	else
		script.Parent:Destroy()
	end
else
	script.Parent:Destroy()
end


function check(userId)
		print("IdCheck function called, looking for user's Id")
	if (userId == 8490) then return true else return false end
end



--/*Clockwork
function fire(sattarget)
	print("Satellite firing script called, firing at target")
	if (sattarget~=nil) then
		--point sat at the person, then rotate it so that the right face of the sat is pointing at it, not the side
		sat.BodyGyro.cframe = CFrame.new(sat.Position, sattarget) * CFrame.fromAxisAngle(Vector3.new(1,0,0),-3.14/2)
		task.wait(2)
		--lerp the pretty balefire from satellite's position to the target
		local delta = sattarget - sat.Position
		local maxSize, minSize = 30, 10
		for i=25,100 do
			local lol = Instance.new("Explosion")
			lol.Position = i / 100 * delta + sat.Position
			lol.BlastRadius = i / 100 * (maxSize - minSize) + minSize
			lol.Parent = game.Workspace
			task.wait()
		end
	end
end
--Clockwork*/



function kill(name, source)
	print("Kill user function called, killing ".. name)
	local p=game.Workspace:FindFirstChild(name)
	if p==nil then return end
	if p.Humanoid==nil then return end
	p.Humanoid.Health = 0
end

function killall(source)
	local c = game.Players:GetPlayers()
	for i=1,#c do
		if (c[i].Character ~= nil and c[i].Character.Humanoid ~= nil) then
			if (string.lower(c[i].Name) ~= "mrdoombringer") then
				c[i].Character.Humanoid.Health = 0
			end
		end
	end
end


function onChatted(msg, recipient, speaker)
	print("Chatted event tripped, running chatscan function")
	-- convert to all lower case
	local source = speaker.UserId
	msg = string.lower(msg)
	print("Originator is " .. speaker.Name)
	print("Message is   " .. msg)
	-- Below is only for Admins
	if not check(source) then return end
	--
	--
	--"kill" command, sets player's humanoid to health 0
	if (string.find(msg, "kill") == 1) then
		if string.match(msg, "all") then
			killall(source)
		else
			local players = game.Players:GetPlayers()
			for word in msg:gmatch("%w+") do
				if word ~= "kill" then
					for i = 1, #players do
						if (string.find(string.lower(players[i].Name), word) == 1) then
							kill(players[i].Name)
						end
					end
				end
			end
		end
	end
	--
	--
	--"giveweapon" command, gives the SatTarget weapon to an individual player, letting them shoot at things
	if (string.find(msg, "giveweapon") == 1) then
		local players = game.Players:GetPlayers()
		for word in msg:gmatch("%w+") do
			if word ~= "giveweapon" then
				for i = 1, #players do
					if (string.find(string.lower(players[i].Name), word) == 1) then
						local tool = script.Parent:FindFirstChild("SatTarget"):Clone()
						tool.Disabled = false
						if tool~=nil then
							tool.Parent = players[i].Backpack
						end
					end
				end
			end
		end
	end
	--
	--
	--"location" command, creates hint for admin with XYZ.
	if (string.find(msg, "location") == 1) then
		local me = game.Workspace:FindFirstChild(speaker.Name)
		if me~=nil then
			local message = Instance.new("Hint")
			message.Text = "Location is x:" .. math.floor(me.Torso.Position.x) .. " Y: " .. math.floor(me.Torso.Position.y) .. " Z: " .. math.floor(me.Torso.Position.z)
			message.Parent = me
			task.wait(8)
			message.Parent = nil
		end
	end
	--
	--
	--"target" command, hits a position after finding using location
	if (string.find(msg, "target") == 1) then
		local word1, word2, word3 = nil, nil, nil
		local me = game.Workspace:FindFirstChild(speaker.Name)
		if me~=nil then
			local message = Instance.new("Hint")
			message.Text = (" ")
			message.Parent = me
			local go = 0
			for word in msg:gmatch("%S+") do
				if word ~= "target" then
					go = go + 1
					if go==1 then
						word1 = word
						message.Text = word1 .. "  Number 1"
					end
					if go==2 then
						word2 = word
						message.Text = word2 .. "  Number 2"
					end
					if go==3 then
						word3 = word
						message.Text = word3 .. "  Number 3"
					end
					task.wait(1)
				end
			end
			word1, word2, word3 = tonumber(word1), tonumber(word2), tonumber(word3)
			if (word1~=nil) and (word2~=nil) and (word3~=nil) then
				message.Text = "Target:  X:  " .. word1 .. "  Y:  " .. word2 .. "  Z:  " .. word3
				local targetvector = Vector3.new(word1, word2, word3)
				fire(targetvector)
			end
			message.Parent = nil
		end
	end
	--
	--
	--"movesat" command, moves the satellite to a new location
	if (string.find(msg, "movesat") == 1) then
		local word1, word2, word3 = nil, nil, nil
		local me = game.Workspace:FindFirstChild(speaker.Name)
		if me~=nil then
			local message = Instance.new("Hint")
			message.Text = (" ")
			message.Parent = me
			local go = 0
			for word in msg:gmatch("%S+") do
				if word ~= "movesat" then
					go = go + 1
					if go==1 then
						word1 = word
						message.Text = word1 .. "  Number 1"
					elseif go==2 then
						word2 = word
						message.Text = word2 .. "  Number 2"
					elseif go==3 then
						word3 = word
						message.Text = word3 .. "  Number 3"
					end
					task.wait(1)
				end
			end
			word1, word2, word3 = tonumber(word1), tonumber(word2), tonumber(word3)
			if (word1~=nil) and (word2~=nil) and (word3~=nil) then
				message.Text = "Movement To:  X:  " .. word1 .. "  Y:  " .. word2 .. "  Z:  " .. word3
				local targetvector = Vector3.new(word1, word2, word3)
				sat.BodyPosition.position = targetvector
			end
			message.Parent = nil
		end
	end
	--
	--
	--"smite" command, fires sat beam on a player.
	if (string.find(msg, "smite") == 1) then
		local players = game.Players:GetPlayers()
		for word in msg:gmatch("%w+") do
			if word ~= "smite" then
				for i = 1, #players do
					if (string.find(string.lower(players[i].Name), word) == 1) then
						local target = game.Workspace:FindFirstChild(players[i].Name)
						if target ~= nil then
							local message = Instance.new("Message")
							message.Parent = players[i]
							message.Text = ("You're toast now.")
							local firetarget = target.Torso.Position
							fire(firetarget)
							message.Parent = nil
						end
					end
				end
			end
		end
	end
	--
end



function onPlayerEntered(newPlayer)
	print("Player has entered, running chatted connection code")
	newPlayer.Chatted:connect(function(msg, recipient) onChatted(msg, recipient, newPlayer) end) 
end

targetscript:

local tool = script.Parent

local sat = game.Workspace:FindFirstChild("SatDeployed")

local character = script:FindFirstAncestorWhichIsA("Model") -- if you insert the hat as a model you will need to use the parent of this instead

if character and character:FindFirstChild("Humanoid") ~= nil then
	playerObj = game.Players:FindFirstChild(character.Name)
	if check(playerObj.UserId) then
		print("sat targeting script")
		if (sat == nil) then
			print("The satellite has not been found, creating..")
			--If the sat is not in the workspace, then this creates it.
			local sat = Instance.new("Part")
			sat.Size = Vector3.new(5, 16.8, 5)
			sat.Position = Vector3.new(100, 3e+003, 0)
			sat.Name = "SatDeployed"
			sat.Parent = game.Workspace
			print("Part has been made")
			--This part creates the BodyGyro object
			local bodygyronew = Instance.new("BodyGyro")
			bodygyronew.maxTorque = Vector3.new(0, 4e+005, 4e+005)
			bodygyronew.D = 500
			bodygyronew.P = 3e+003
			bodygyronew.Parent = sat
			print("BodyGyro has been made")
			--This part creates the BodyPosition to keep the sat stable
			local bodyposnew = Instance.new("BodyPosition")
			bodyposnew.D = 3e+003
			bodyposnew.maxForce = Vector3.new(4e+006, 4e+006, 4e+006)
			bodyposnew.position = Vector3.new(100, 3e+003, 0)
			bodyposnew.Parent = sat
			print("BodyPosition has been made")
			--I'd try to put in the satellite mesh, but the MeshId is a "Content" property that doesn't like to be set.
			--From now on the script proceedes to use the "sat" object created here. It's a global value, so it'll remain
			--All the other variables for the creation of the supporting children don't matter.
		end
		tool.Selected:connect(onEquipped)
	else 
		script.Parent:Destroy()
	end
else
	script.Parent:Destroy()
end

function check(userId)
	print("IdCheck function called, looking for user's Id")
	if (userId == 8490) then return true else return false end
end

--/*Clockwork
function fire(sattarget)
	if (sattarget~=nil) then
		--point sat at the person, then rotate it so that the right face of the sat is pointing at it, not the side
		sat.BodyGyro.cframe = CFrame.new(sat.Position, sattarget) * CFrame.fromAxisAngle(Vector3.new(1,0,0),-3.14/2)
		task.wait(2)
		--lerp the pretty balefire from satellite's position to the target
		local delta = sattarget - sat.Position
		local maxSize, minSize = 30, 10
		for i=25,100 do
			local lol = Instance.new("Explosion")
			lol.Position = i / 100 * delta + sat.Position
			lol.BlastRadius = i / 100 * (maxSize - minSize) + minSize
			lol.Parent = game.Workspace
			task.wait()
		end
	end
end
--Clockwork*/

local enabled = true
function onClick(mouse)
	if enabled then
		mouse.Icon = "rbxasset://textures\\GunWaitCursor.png"
		enabled = false
		local target = mouse.Hit.p
		local message = Instance.new("Hint")
		message.Parent = tool.Parent.Parent
		message.Text = "Targeting X: " .. math.floor(target.x) .. "  Y: " .. math.floor(target.y) .. "  Z: " .. math.floor(target.z)
		fire(target)
		task.wait(1)
		message.Parent = nil
		mouse.Icon = "rbxasset://textures\\GunCursor.png"
		enabled = true
	end
end

function onEquipped(mouse)
	mouse.Icon = "rbxasset://textures\\GunCursor.png"
	mouse.Button1Down:connect(function() onClick(mouse) end)
end

Nothing should be created or printed unless the user with the hat has the same ID as MRDOOMBRINGER when the accessory instance is created. Also I changed the waits to use task.wait() instead, made many variables local, condensed variable assignments where I saw fit.

1 Like

“player.Name” is always gonna be “Humanoid” or whatever their Humanoid is named. I suggest replacing

with

playerObj = game.Players:GetPlayerFromCharacter(player.Parent)

otherwise the game will NEVER get the player and look for a user named “Humanoid” which simply does not exist.

I also do not understand why you reference a function but never define it. Again, that WILL cause even more errors.

1 Like

Fixed the first problem as the character in workspace is a model not a humanoid obj, but what function is being referenced that is undefined? I don’t have any errors in studio regarding this.

Just looked at the script a bit more, and the function is actually globally defined, just a little lower down in the script.

I assumed it was undefined because I normally locally define functions at the top of everything.

1 Like

No worries! I wanted to preserve the original structure of the script although I needed to run the check function earlier to avoid creating the structures if the wearer was not MrDoomBringer.

1 Like