Security fixes for the input-validation gaps in the public download and metadata services, plus missing in-code admin gates: - mpe_accesscheck: validate base_table (LIBDS) and access_level before they reach the authorisation query, and escape embedded quotes in the SQL literals (defence in depth for direct macro callers) - getrawdata: validate table (LIBDS / format-catalog form), filter (integer) and type before they are used; read all inputs with symget in a data step so macro content cannot execute at a resolution boundary - getdiffs: validate libds, table and stp_diffs_csv before the access check and the staging-file stream path - getcols, getcolvals, validatefilter: read the IWANT inputs with symget in a data step and validate (LIBDS / SAS name) before use - admin dirlist, refreshlibs, refreshcatalog, exportconfig: require membership of the DC administrators group (the admin folder prefix is not an access control) - admin dirlist: read parent with symget and reject macro characters Tests (all proven RED on the vulnerable services first, then GREEN on the fix): getrawdata.test.1, getdiffs.test, getcols.test, getcolvals.test.4, validatefilter.test.1, dirlist.test, refreshcatalog.test.1
62 lines
1.5 KiB
SAS
62 lines
1.5 KiB
SAS
/**
|
|
@file
|
|
@brief Fetches directories to facilitate configuration
|
|
@details The service can also be invoked using the following URL param:
|
|
|
|
@li &parent= (parent path)
|
|
|
|
Requires membership of the DC administrators group.
|
|
|
|
<h4> SAS Macros </h4>
|
|
@li mf_getuser.sas
|
|
@li mp_abort.sas
|
|
@li mp_dirlist.sas
|
|
@li mpe_getgroups.sas
|
|
|
|
@version 9.2
|
|
@author 4GL Apps Ltd
|
|
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
|
|
and may not be re-distributed or re-sold without the express permission of
|
|
4GL Apps Ltd.
|
|
|
|
**/
|
|
|
|
%global parent;
|
|
%mpeinit()
|
|
|
|
/* check user is in admin group */
|
|
%let cnt=0;
|
|
%mpe_getgroups(user=%mf_getuser(),outds=work.usergroups)
|
|
proc sql noprint;
|
|
select count(*) into:cnt
|
|
from usergroups
|
|
where groupname="&mpeadmins";
|
|
%mp_abort(iftrue= (&cnt=0)
|
|
,mac=&_program
|
|
,msg=%str(This service is only available to &mpeadmins members)
|
|
)
|
|
|
|
/* if no parent is specified, default to root - read with symget
|
|
* (never re-resolved) so macro content in the param cannot execute */
|
|
%let is_bad=0;
|
|
data _null_;
|
|
length _parent $512;
|
|
_parent=coalescec(symget('parent'),'/');
|
|
if index(_parent,'%')>0 or index(_parent,'&')>0 then do;
|
|
putlog 'ERR' 'OR: Invalid parent:' _parent;
|
|
call symputx('is_bad',1,'l');
|
|
end;
|
|
else call symputx('parent',_parent,'g');
|
|
run;
|
|
|
|
%mp_abort(iftrue=(&is_bad=1)
|
|
,mac=&_program..sas
|
|
,msg=%str(Invalid parent)
|
|
)
|
|
|
|
%mp_dirlist(path=&parent,outds=dirlist, maxdepth=2)
|
|
|
|
%webout(OPEN)
|
|
%webout(OBJ,dirlist)
|
|
%webout(CLOSE)
|