mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-12 18:51:53 +00:00
[MIRROR] [s] Security vulnerability patch [MDB IGNORE] (#9256)
* [s] Security vulnerability patch (#62568) About The Pull Request In my personal, subjective opinion; trialmins should not, in fact, be able to read and delete server/box configuration files on a whim. cl server: Patches multiple(?) arbitrary file related vulnerabilities /cl * [s] Security vulnerability patch Co-authored-by: TheFakeElon <59686430+TheFakeElon@users.noreply.github.com>
This commit is contained in:
@@ -17,3 +17,6 @@
|
|||||||
|
|
||||||
///Adds a html style to a text string. Hacky, but that's how inputted text appear on paper sheets after going through the UI.
|
///Adds a html style to a text string. Hacky, but that's how inputted text appear on paper sheets after going through the UI.
|
||||||
#define PAPER_MARK_TEXT(text, color, font) "<span style=\"color:[color];font-family:'[font]';\">[text]</span>\n \n"
|
#define PAPER_MARK_TEXT(text, color, font) "<span style=\"color:[color];font-family:'[font]';\">[text]</span>\n \n"
|
||||||
|
|
||||||
|
/// Folder directory for strings
|
||||||
|
#define STRING_DIRECTORY "strings"
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ GLOBAL_LIST(string_cache)
|
|||||||
GLOBAL_VAR(string_filename_current_key)
|
GLOBAL_VAR(string_filename_current_key)
|
||||||
|
|
||||||
|
|
||||||
/proc/strings_replacement(filename, key, directory = "strings")
|
/proc/strings_replacement(filename, key)
|
||||||
load_strings_file(filename, directory)
|
filename = SANITIZE_FILENAME(filename)
|
||||||
|
load_strings_file(filename)
|
||||||
|
|
||||||
if((filename in GLOB.string_cache) && (key in GLOB.string_cache[filename]))
|
if((filename in GLOB.string_cache) && (key in GLOB.string_cache[filename]))
|
||||||
var/response = pick(GLOB.string_cache[filename][key])
|
var/response = pick(GLOB.string_cache[filename][key])
|
||||||
@@ -16,19 +17,21 @@ GLOBAL_VAR(string_filename_current_key)
|
|||||||
response = r.Replace(response, /proc/strings_subkey_lookup)
|
response = r.Replace(response, /proc/strings_subkey_lookup)
|
||||||
return response
|
return response
|
||||||
else
|
else
|
||||||
CRASH("strings list not found: [directory]/[filename], index=[key]")
|
CRASH("strings list not found: [STRING_DIRECTORY]/[filename], index=[key]")
|
||||||
|
|
||||||
/proc/strings(filename as text, key as text, directory = "strings")
|
/proc/strings(filename as text, key as text)
|
||||||
load_strings_file(filename, directory)
|
filename = SANITIZE_FILENAME(filename)
|
||||||
|
load_strings_file(filename)
|
||||||
if((filename in GLOB.string_cache) && (key in GLOB.string_cache[filename]))
|
if((filename in GLOB.string_cache) && (key in GLOB.string_cache[filename]))
|
||||||
return GLOB.string_cache[filename][key]
|
return GLOB.string_cache[filename][key]
|
||||||
else
|
else
|
||||||
CRASH("strings list not found: [directory]/[filename], index=[key]")
|
CRASH("strings list not found: [STRING_DIRECTORY]/[filename], index=[key]")
|
||||||
|
|
||||||
/proc/strings_subkey_lookup(match, group1)
|
/proc/strings_subkey_lookup(match, group1)
|
||||||
return pick_list(GLOB.string_filename_current_key, group1)
|
return pick_list(GLOB.string_filename_current_key, group1)
|
||||||
|
|
||||||
/proc/load_strings_file(filename, directory = "strings")
|
/proc/load_strings_file(filename)
|
||||||
|
filename = SANITIZE_FILENAME(filename) // in case we're called directly
|
||||||
GLOB.string_filename_current_key = filename
|
GLOB.string_filename_current_key = filename
|
||||||
if(filename in GLOB.string_cache)
|
if(filename in GLOB.string_cache)
|
||||||
return //no work to do
|
return //no work to do
|
||||||
@@ -36,7 +39,7 @@ GLOBAL_VAR(string_filename_current_key)
|
|||||||
if(!GLOB.string_cache)
|
if(!GLOB.string_cache)
|
||||||
GLOB.string_cache = new
|
GLOB.string_cache = new
|
||||||
|
|
||||||
if(fexists("[directory]/[filename]"))
|
if(fexists("[STRING_DIRECTORY]/[filename]"))
|
||||||
GLOB.string_cache[filename] = json_load("[directory]/[filename]")
|
GLOB.string_cache[filename] = json_load("[STRING_DIRECTORY]/[filename]")
|
||||||
else
|
else
|
||||||
CRASH("file not found: [directory]/[filename]")
|
CRASH("file not found: [STRING_DIRECTORY]/[filename]")
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* For FTP requests. (i.e. downloading runtime logs.)
|
* For FTP requests. (i.e. downloading runtime logs.)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ GLOBAL_DATUM_INIT(has_discord_embeddable_links, /regex, regex("(https?://\[^\\s|
|
|||||||
//All < and > characters
|
//All < and > characters
|
||||||
GLOBAL_DATUM_INIT(angular_brackets, /regex, regex(@"[<>]", "g"))
|
GLOBAL_DATUM_INIT(angular_brackets, /regex, regex(@"[<>]", "g"))
|
||||||
|
|
||||||
//All characters forbidden by filenames: ", \, \n, \t, /, ?, %, *, :, |, <, >
|
//All characters forbidden by filenames: ", \, \n, \t, /, ?, %, *, :, |, <, >, ..
|
||||||
GLOBAL_DATUM_INIT(filename_forbidden_chars, /regex, regex(@{""|[\\\n\t/?%*:|<>]"}, "g"))
|
GLOBAL_DATUM_INIT(filename_forbidden_chars, /regex, regex(@{""|[\\\n\t/?%*:|<>]|\.\."}, "g"))
|
||||||
// had to use the OR operator for quotes instead of putting them in the character class because it breaks the syntax highlighting otherwise.
|
// had to use the OR operator for quotes instead of putting them in the character class because it breaks the syntax highlighting otherwise.
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ Example config:
|
|||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
if ("map")
|
if ("map")
|
||||||
currentmap = load_map_config("_maps/[data].json")
|
currentmap = load_map_config(data)
|
||||||
if(currentmap.defaulted)
|
if(currentmap.defaulted)
|
||||||
log_config("Failed to load map config for [data]!")
|
log_config("Failed to load map config for [data]!")
|
||||||
currentmap = null
|
currentmap = null
|
||||||
|
|||||||
@@ -454,9 +454,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
|||||||
|
|
||||||
/datum/controller/subsystem/mapping/proc/preloadRuinTemplates()
|
/datum/controller/subsystem/mapping/proc/preloadRuinTemplates()
|
||||||
// Still supporting bans by filename
|
// Still supporting bans by filename
|
||||||
var/list/banned = generateMapList("[global.config.directory]/lavaruinblacklist.txt")
|
var/list/banned = generateMapList("lavaruinblacklist.txt")
|
||||||
banned += generateMapList("[global.config.directory]/spaceruinblacklist.txt")
|
banned += generateMapList("spaceruinblacklist.txt")
|
||||||
banned += generateMapList("[global.config.directory]/iceruinblacklist.txt")
|
banned += generateMapList("iceruinblacklist.txt")
|
||||||
|
|
||||||
for(var/item in sort_list(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
|
for(var/item in sort_list(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
|
||||||
var/datum/map_template/ruin/ruin_type = item
|
var/datum/map_template/ruin/ruin_type = item
|
||||||
@@ -491,7 +491,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
|||||||
//SKYRAT EDIT END//
|
//SKYRAT EDIT END//
|
||||||
|
|
||||||
/datum/controller/subsystem/mapping/proc/preloadShuttleTemplates()
|
/datum/controller/subsystem/mapping/proc/preloadShuttleTemplates()
|
||||||
var/list/unbuyable = generateMapList("[global.config.directory]/unbuyableshuttles.txt")
|
var/list/unbuyable = generateMapList("unbuyableshuttles.txt")
|
||||||
|
|
||||||
for(var/item in subtypesof(/datum/map_template/shuttle))
|
for(var/item in subtypesof(/datum/map_template/shuttle))
|
||||||
var/datum/map_template/shuttle/shuttle_type = item
|
var/datum/map_template/shuttle/shuttle_type = item
|
||||||
|
|||||||
@@ -34,14 +34,15 @@
|
|||||||
/// Dictionary of job sub-typepath to template changes dictionary
|
/// Dictionary of job sub-typepath to template changes dictionary
|
||||||
var/job_changes = list()
|
var/job_changes = list()
|
||||||
|
|
||||||
/proc/load_map_config(filename = "data/next_map.json", default_to_box, delete_after, error_if_missing = TRUE)
|
/proc/load_map_config(filename = "next_map.json", default_to_box, delete_after, error_if_missing = TRUE)
|
||||||
|
filename = "_maps/[filename].json"
|
||||||
var/datum/map_config/config = new
|
var/datum/map_config/config = new
|
||||||
if (default_to_box)
|
if (default_to_box)
|
||||||
return config
|
return config
|
||||||
if (!config.LoadConfig(filename, error_if_missing))
|
if (!config.LoadConfig(filename, error_if_missing))
|
||||||
qdel(config)
|
qdel(config)
|
||||||
config = new /datum/map_config // Fall back to Box
|
config = new /datum/map_config // Fall back to Box
|
||||||
if (delete_after)
|
else if (delete_after)
|
||||||
fdel(filename)
|
fdel(filename)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|||||||
@@ -328,10 +328,9 @@
|
|||||||
itemname = pressed_pda.name
|
itemname = pressed_pda.name
|
||||||
info = pressed_pda.notehtml
|
info = pressed_pda.notehtml
|
||||||
|
|
||||||
var/sanitized_name = sanitize(itemname)
|
itemname = sanitize(itemname)
|
||||||
|
|
||||||
to_chat(paper_user, span_notice("You hold \the [itemname] up to the camera..."))
|
to_chat(paper_user, span_notice("You hold \the [itemname] up to the camera..."))
|
||||||
paper_user.log_talk(sanitized_name, LOG_GAME, log_globally=TRUE, tag="Pressed to camera")
|
paper_user.log_talk(itemname, LOG_GAME, log_globally=TRUE, tag="Pressed to camera")
|
||||||
paper_user.changeNext_move(CLICK_CD_MELEE)
|
paper_user.changeNext_move(CLICK_CD_MELEE)
|
||||||
|
|
||||||
for(var/mob/potential_viewer in GLOB.player_list)
|
for(var/mob/potential_viewer in GLOB.player_list)
|
||||||
@@ -343,11 +342,11 @@
|
|||||||
to_chat(AI, "[span_name(paper_user)] holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ...")
|
to_chat(AI, "[span_name(paper_user)] holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ...")
|
||||||
else
|
else
|
||||||
to_chat(AI, "<b><a href='?src=[REF(AI)];track=[html_encode(paper_user.name)]'>[paper_user]</a></b> holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ...")
|
to_chat(AI, "<b><a href='?src=[REF(AI)];track=[html_encode(paper_user.name)]'>[paper_user]</a></b> holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ...")
|
||||||
AI.log_talk(sanitized_name, LOG_VICTIM, tag="Pressed to camera from [key_name(paper_user)]", log_globally=FALSE)
|
AI.log_talk(itemname, LOG_VICTIM, tag="Pressed to camera from [key_name(paper_user)]", log_globally=FALSE)
|
||||||
AI.last_paper_seen = "<HTML><HEAD><TITLE>[itemname]</TITLE></HEAD><BODY><TT>[info]</TT></BODY></HTML>"
|
AI.last_paper_seen = "<HTML><HEAD><TITLE>[itemname]</TITLE></HEAD><BODY><TT>[info]</TT></BODY></HTML>"
|
||||||
else if (potential_viewer.client.eye == src)
|
else if (potential_viewer.client.eye == src)
|
||||||
to_chat(potential_viewer, "[span_name("[paper_user]")] holds \a [itemname] up to one of the cameras ...")
|
to_chat(potential_viewer, "[span_name("[paper_user]")] holds \a [itemname] up to one of the cameras ...")
|
||||||
potential_viewer.log_talk(sanitized_name, LOG_VICTIM, tag="Pressed to camera from [key_name(paper_user)]", log_globally=FALSE)
|
potential_viewer.log_talk(itemname, LOG_VICTIM, tag="Pressed to camera from [key_name(paper_user)]", log_globally=FALSE)
|
||||||
potential_viewer << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", itemname, info), text("window=[]", itemname))
|
potential_viewer << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", itemname, info), text("window=[]", itemname))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generateConfigMapList(directory =
|
|||||||
|
|
||||||
/proc/generateMapList(filename)
|
/proc/generateMapList(filename)
|
||||||
. = list()
|
. = list()
|
||||||
|
filename = "[global.config.directory]/[SANITIZE_FILENAME(filename)]"
|
||||||
var/list/Lines = world.file2list(filename)
|
var/list/Lines = world.file2list(filename)
|
||||||
|
|
||||||
if(!Lines.len)
|
if(!Lines.len)
|
||||||
|
|||||||
@@ -54,6 +54,8 @@
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
/datum/tgs_api/v3210/proc/file2list(filename)
|
/datum/tgs_api/v3210/proc/file2list(filename)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
CRASH("Attempted to read file via admin call")
|
||||||
return splittext(trim_left(trim_right(file2text(filename))), "\n")
|
return splittext(trim_left(trim_right(file2text(filename))), "\n")
|
||||||
|
|
||||||
/datum/tgs_api/v3210/OnWorldNew(minimum_required_security_level)
|
/datum/tgs_api/v3210/OnWorldNew(minimum_required_security_level)
|
||||||
|
|||||||
@@ -321,3 +321,6 @@
|
|||||||
// Resend the assets
|
// Resend the assets
|
||||||
for(var/asset in sent_assets)
|
for(var/asset in sent_assets)
|
||||||
send_asset(asset)
|
send_asset(asset)
|
||||||
|
|
||||||
|
/datum/tgui_window/vv_edit_var(var_name, var_value)
|
||||||
|
return var_name != NAMEOF(src, id) && ..()
|
||||||
|
|||||||
Reference in New Issue
Block a user