Files
dc/sas/sasjs/services/public/getrawdata.test.1.sas
T
dc a20a5a627c
Lighthouse Checks / lighthouse (pull_request) Failing after 3m1s
Build / Build-and-ng-test (pull_request) Successful in 4m53s
Build / Build-and-test-development (pull_request) Failing after 6m4s
refactor(tests): mpe_assert_abort reads the sasjsAbort object from the response
dc_assert_abort inferred the outcome from the status row.  The assertion should
prove the service rejected its input, so it now reads the child's response and
requires a sasjsAbort object, and compares that object's MSG value with the
message the service is expected to return:

  %mpe_assert_abort(desc=An invalid libds aborts the service,
    outref=web1, msg=Invalid libds)

Renamed with the mpe_ prefix to match the other macro-level helpers.  getdata
Test 4 asserted completion with the abort macro, which was the wrong tool; it
now checks the status row for state=completed directly.
2026-10-27 09:26:34 +00:00

142 lines
3.3 KiB
SAS

/**
@file
@brief testing getrawdata service - input validation (security)
@details table must be a well-formed LIBREF.DATASET (the trailing
format-catalog suffix is permitted), filter must be an integer and
type one of the supported download types. An invalid value aborts
the service before any request content can execute. The abort is
asserted from the child job state: the payloads either resolve to a
real table when executed as macro code, or write a file outside the
WORK directory (verified by live probe) - so on the vulnerable
service the job completes, and only the validating service cancels
it. The assertion cannot pass against a service that does not
validate.
<h4> SAS Macros </h4>
@li mpe_assert_abort.sas
@li mp_assert.sas
@li dc_execute.sas
**/
%let _program=&appLoc/services/public/getrawdata;
/**
* Test 1 - macro content in table must abort the service
* (the payload resolves to a real table when executed as macro code)
*/
data work.params1;
length name $32 value $1000;
name='type';value='CSV';output;
name='table';value='%sysfunc(coalescec(&mpelib..MPE_X_TEST,))';output;
name='filter';value='0';output;
run;
%dc_execute(&_program,
viyacontext=&defaultcontext,
inputparams=work.params1,
outref=web1,
outstatus=work.ab1,
failfast=0,
viyaresult=WEBOUT_TXT
)
%mpe_assert_abort(
desc=Macro content in table aborts the service,
outref=web1,
msg=Invalid filter
)
/**
* Test 2 - sql injection in filter must abort the service
*/
data work.params2;
length name $32 value $1000;
name='type';value='CSV';output;
name='table';value="&dclib..MPE_X_TEST";output;
name='filter';value='0 or 1=1';output;
run;
%dc_execute(&_program,
viyacontext=&defaultcontext,
inputparams=work.params2,
outref=web2,
outstatus=work.ab2,
failfast=0,
viyaresult=WEBOUT_TXT
)
%mpe_assert_abort(
desc=SQL injection in filter aborts the service,
outref=web2,
msg=Invalid filter
)
/**
* Test 3 - path traversal in table must abort the service
* (verified by live probe: on a vulnerable service this writes
* ../SECPROBE.csv outside the WORK directory and completes)
*/
data work.params3;
length name $32 value $1000;
name='type';value='CSV';output;
name='table';value='../secprobe';output;
name='filter';value='0';output;
run;
%dc_execute(&_program,
viyacontext=&defaultcontext,
inputparams=work.params3,
outref=web3,
outstatus=work.ab3,
failfast=0,
viyaresult=WEBOUT_TXT
)
%mpe_assert_abort(
desc=Path traversal in table aborts the service,
outref=web3,
msg=Invalid filter
)
/**
* Test 4 - the valid request must still work (positive control)
*/
data work.params4;
length name $32 value $1000;
name='type';value='CSV';output;
name='table';value="&dclib..MPE_X_TEST";output;
name='filter';value='0';output;
run;
%dc_execute(&_program,
viyacontext=&defaultcontext,
inputparams=work.params4,
outref=web4,
viyaresult=WEBOUT_TXT
)
%let ok4=0;
data _null_;
infile web4;
input;
if _infile_=:'PRIMARY_KEY_FIELD' then do;
call symputx('ok4',1);
stop;
end;
run;
%mp_assert(
iftrue=(&ok4=1),
desc=Valid table request still returns data,
outds=work.test_results
)
/**
* dump results to the log for offline inspection
*/
data _null_;
set work.test_results;
putlog 'TEST_RESULT_LINE: ' test_result ' - ' test_description;
run;