Loading...
Searching...
No Matches
getdiffs.test.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief testing getdiffs service - input validation (security)
4 @details The libds, table and stp_diffs_csv request params must be
5 well-formed before they reach the access check and the staging file
6 path. An invalid value aborts the service, which shows up as a
7 canceled child job (an aborted service registers no webout).
8
9 A real load is staged first (stagedata) and a diffs csv written into
10 the staging directory, so every payload below resolves to that REAL
11 file when executed - on a vulnerable service the job completes, and
12 only the validating service cancels it. The assertions cannot pass
13 against a service that does not validate.
14
15 <h4> SAS Macros </h4>
16 @li mp_assert.sas
17 @li mx_execute.sas
18 @li mf_getuniquefileref.sas
19
20**/
21
22%let _program=&appLoc/services/auditors/getdiffs;
23
24/**
25 * Stage a real load so a real staging directory exists
26 */
27data work.sascontroltable;
28 action='LOAD';
29 message="getdiffs test prep";
30 libds="&dclib..MPE_X_TEST";
31 output;
32 stop;
33run;
34
35proc sql noprint;
36select max(primary_key_field) into: maxpk
37 from &dclib..mpe_x_test;
38quit;
39
40data work.jsdata;
41 set &dclib..mpe_x_test(rename=(
42 some_date=dt2 SOME_DATETIME=dttm2 some_time=tm2)
43 );
44 some_date=put(dt2,date9.);
45 SOME_DATETIME=put(dttm2,datetime19.);
46 some_time=put(tm2,time.);
47 drop dt2 dttm2 tm2;
48 if _n_=1 then do;
49 _____DELETE__THIS__RECORD_____='No';
50 some_char='getdiffs security test';
51 some_num=&maxpk+1;
52 end;
53 else stop;
54run;
55
56%mx_execute(&appLoc/services/editors/stagedata,
57 viyacontext=&defaultcontext,
58 inputdatasets=work.jsdata work.sascontroltable,
59 outlib=webstage,
60 mdebug=&sasjs_mdebug
61)
62
63%let stagetest=0;
64data _null_;
65 set webstage.sasparams;
66 putlog (_all_)(=);
67 if status='SUCCESS' then call symputx('stagetest',1);
68 call symputx('loadref',dsid);
69run;
70
71%mp_assert(
72 iftrue=(&stagetest=1 and &syscc=0),
73 desc=stagedata succeeded in getdiffs prep,
74 outds=work.test_results
75)
76
77/**
78 * Write the diffs csv into the real staging directory
79 */
80%let diffscsv=tempDiffs_secrev.csv;
81data _null_;
82 file "&dc_staging_area/&loadref./&diffscsv";
83 put 'SOME_CHAR,_____STATUS_____';
84 put 'getdiffs security test,UPDATED';
85run;
86
87/**
88 * Test 1 - the mpe_accesscheck SQL injection payload in libds must
89 * abort the service (validation fires before the authz query, so
90 * the authz bypass cannot happen). The payload is sent through the
91 * sasjs table channel (BrowserParams) like the frontend does - the
92 * raw-quote form is masked in plain URL params on this platform.
93 */
94%let fb1=%mf_getuniquefileref();
95data _null_;
96 file &fb1 termstr=crlf;
97 length _row $400.;
98 put 'TABLE:$41. STP_DIFFS_CSV:$100. libds:$41.';
99 _row=cats(symget('loadref'),',',symget('diffscsv'),',',
100 'SOMELIB.SOMEDS',"'22'x"," or ","'22'x",'1',"'22'x",' ne ',"'22'x",'2');
101 put _row;
102run;
103
104%mx_execute(&_program,
105 viyacontext=&defaultcontext,
106 inputfiles=&fb1:BrowserParams,
107 outref=web1,
108 viyaresult=WEBOUT_TXT
109)
110
111%let abort1=0;
112data _null_;
113 set work.results;
114 if state='canceled' then call symputx('abort1',1);
115run;
116
117%mp_assert(
118 iftrue=(&abort1=1),
119 desc=SQL injection payload in libds aborts the service,
120 outds=work.test_results
121)
122
123/**
124 * Test 2 - path traversal in table must abort the service (the
125 * payload resolves to the real staged file through a .. detour)
126 */
127data _null_;
128 length _dir $512;
129 _dir=scan(symget('dc_staging_area'),-1,'/');
130 call symputx('travtable',cats('../',_dir,'/','&loadref'));
131run;
132
133%let fb2=%mf_getuniquefileref();
134data _null_;
135 file &fb2 termstr=crlf;
136 put 'TABLE:$41. STP_DIFFS_CSV:$100. libds:$41.';
137 put "&travtable.,&diffscsv.,&dclib..MPE_X_TEST";
138run;
139
140%mx_execute(&_program,
141 viyacontext=&defaultcontext,
142 inputfiles=&fb2:BrowserParams,
143 outref=web2,
144 viyaresult=WEBOUT_TXT
145)
146
147%let abort2=0;
148data _null_;
149 set work.results;
150 if state='canceled' then call symputx('abort2',1);
151run;
152
153%mp_assert(
154 iftrue=(&abort2=1),
155 desc=Path traversal in table aborts the service,
156 outds=work.test_results
157)
158
159/**
160 * Test 3 - path traversal in stp_diffs_csv must abort the service
161 */
162%let fb3=%mf_getuniquefileref();
163data _null_;
164 file &fb3 termstr=crlf;
165 put 'TABLE:$41. STP_DIFFS_CSV:$100. libds:$41.';
166 put "&loadref.,../&loadref./&diffscsv.,&dclib..MPE_X_TEST";
167run;
168
169%mx_execute(&_program,
170 viyacontext=&defaultcontext,
171 inputfiles=&fb3:BrowserParams,
172 outref=web3,
173 viyaresult=WEBOUT_TXT
174)
175
176%let abort3=0;
177data _null_;
178 set work.results;
179 if state='canceled' then call symputx('abort3',1);
180run;
181
182%mp_assert(
183 iftrue=(&abort3=1),
184 desc=Path traversal in stp_diffs_csv aborts the service,
185 outds=work.test_results
186)
187
188/**
189 * dump results to the log for offline inspection
190 */
191data _null_;
192 set work.test_results;
193 putlog 'TEST_RESULT_LINE: ' test_result ' - ' test_description;
194run;