- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Does the SAS interpreter remove single quotes for values passed in parameters over the web?
For example, using the sample intrnet application below and the following webrequest: https://sampleapplicationserver/cgi-bin/broker?_SERVICE=default&_PROGRAM=SAMPLIB.WEBSAMP.PRINT_TO_HT...
The 'SASHELP.RETAIL' dataset is still rendered correctly despite the addition of single quotes (SA'SHELP.RE'TAIL). I have also tried URL encoding these to %27 and it still has no affect.
%global bg bgtype dataset style tmpstyle; %macro print_to_html; %if not %sysfunc(exist(&dataset)) %then %do; data _null_; file _webout; put '<HTML>'; put '<HEAD>'; put '<TITLE>Missing Data Set</TITLE>'; put '</HEAD>'; bgtype = symget('bgtype'); if trim(upcase(bgtype))="COLOR" then put "<BODY BGCOLOR=&bg>"; else if trim(upcase(bgtype))="IMAGE" then put '<BODY BACKGROUND="' "&bg" '">'; else put '<BODY>'; put '<H1>Missing Data Set</H1>'; put "Data set &dataset not found."; put '</BODY>'; put '</HTML>'; run; %goto done; %end; %if &style ne %then %let tmpstyle=style=styles.&style; %else %if %UPCASE(&bgtype) eq COLOR %then %do; ods path work.templat(update) sasuser.templat(read) sashelp.tmplmst(read); proc template; define style tmpstyle; parent=styles.default; style body from body / background=&bg; style systemtitle from systemtitle / background=&bg; style systemfooter from systemfooter / background=&bg; style systitleandfootercontainer from systitleandfootercontainer / background=&bg; end; run; %let tmpstyle=style=tmpstyle; %end; %else %if %UPCASE(&bgtype) eq IMAGE %then %do; ods path work.templat(update) sasuser.templat(read) sashelp.tmplmst(read); proc template; define style tmpstyle; parent=styles.default; style body from body / backgroundimage="&bg"; end; run; %let tmpstyle=style=tmpstyle; %end; %else %let tmpstyle=; ods html &tmpstyle body=_webout rs=none; title "Data Set &dataset in HTML Format"; proc print data=&dataset; run; ods html close; %done: %mend print_to_html; * HTML encode vulnerable values to prevent XSS injection; data _null_; call symputx('BG', htmlencode(symget('bg'))); call symputx('DATASET', htmlencode(symget('dataset'))); run; %print_to_html;
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
The quotation marks are stripped from the input parameter to prevent cross-site scripting code injections:
SAS/IntrNet 9.4: Application Dispatcher > PROC APPSRV Statement > UNSAFE='string'
If you have a good reason to access the value that was passed in, including the quotation marks, you can use the APPSRV_UNSAFE function:
SAS/IntrNet 9.4: Application Dispatcher > Development Tasks > Application Server Functions > APPSRV_UNSAFE Function
https://go.documentation.sas.com/doc/en/dispatch/9.4/n0gc4breypvrrzn1jfsuk607bcp2.htm
But it's called "unsafe" for a reason. You can read a little more about the cautions of using it in the SAS Viya documentation.
SAS 9.4 and SAS Viya 3.5 Programming Documentation > DATA Step Programming > Functions and CALL Routines > Dictionary of Functions and CALL Routines > COMPSRV_OVAL Function
Vince DelGobbo
SAS R&D
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
A few helpful functions can escape special characters in URLs and in HTML. If appearing in a URL, use urlencode. If you need to encode in HTML body, use htmlencode.
Decodes a string that contains HTML numeric character references or HTML character entity references and returns the decoded string. |
|
Encodes characters using HTML character entity references and returns the encoded string. |
|
Returns a string that was decoded using the URL escape syntax. |
|
Returns a string that was encoded using the URL escape syntax. From: urlencode(%str(ga:sessions,ga:pageviews,ga:users)); To: ga%3Asessions,ga%3Apageviews,ga%3Ausers |
|
%str(&) |
Prevent SAS from interpreting “&” in a URL as a macro variable. Avoids "WARNING: Apparent symbolic reference TOPPING not resolved." |
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Chris, thanks for the reply. I guess my question is, without modifying the previously provided code, why are the single quotes not being interpreted? Other URL encoded symbol characters such as the equal sign, question mark, etc are interpreted correctly, however, single quotes and percent signs appear to have no affect on the values.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@test110 wrote:
Chris, thanks for the reply. I guess my question is, without modifying the previously provided code, why are the single quotes not being interpreted? Other URL encoded symbol characters such as the equal sign, question mark, etc are interpreted correctly, however, single quotes and percent signs appear to have no affect on the values.
Please highlight or extract the lines you expect to be using text with single quotes. I cannot tell where you are expecting them to come from or be used.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Please see below for the highlighted (in red) lines-
For the URL portion: &DATASET=SA%27SHELP.RE%27TAIL
For the code portion: line 4 (&dataset)
Also, here is the full URL that is being used (it appears it got cut off earlier in the post):
https://sampleapplicationserver/cgi-bin/broker?_SERVICE=default&_PROGRAM=SAMPLIB.WEBSAMP.PRINT_TO_HTML.SOURCE&_ENTRY=SAMPLIB.WEBSAMP.PRINT_TO_HTML.SOURCE&BGTYPE=COLOR&BG=%23FFFFFF&DATASET=SA%27SHELP.RE%27TAIL&TEMPFILE=Unknown
%global bg bgtype dataset style tmpstyle; %macro print_to_html; %if not %sysfunc(exist(&dataset)) %then %do; data _null_; file _webout; put '<HTML>'; put '<HEAD>'; put '<TITLE>Missing Data Set</TITLE>'; put '</HEAD>'; bgtype = symget('bgtype'); if trim(upcase(bgtype))="COLOR" then put "<BODY BGCOLOR=&bg>"; else if trim(upcase(bgtype))="IMAGE" then put '<BODY BACKGROUND="' "&bg" '">'; else put '<BODY>'; put '<H1>Missing Data Set</H1>'; put "Data set &dataset not found."; put '</BODY>'; put '</HTML>'; run; %goto done; %end; %if &style ne %then %let tmpstyle=style=styles.&style; %else %if %UPCASE(&bgtype) eq COLOR %then %do; ods path work.templat(update) sasuser.templat(read) sashelp.tmplmst(read); proc template; define style tmpstyle; parent=styles.default; style body from body / background=&bg; style systemtitle from systemtitle / background=&bg; style systemfooter from systemfooter / background=&bg; style systitleandfootercontainer from systitleandfootercontainer / background=&bg; end; run; %let tmpstyle=style=tmpstyle; %end; %else %if %UPCASE(&bgtype) eq IMAGE %then %do; ods path work.templat(update) sasuser.templat(read) sashelp.tmplmst(read); proc template; define style tmpstyle; parent=styles.default; style body from body / backgroundimage="&bg"; end; run; %let tmpstyle=style=tmpstyle; %end; %else %let tmpstyle=; ods html &tmpstyle body=_webout rs=none; title "Data Set &dataset in HTML Format"; proc print data=&dataset; run; ods html close; %done: %mend print_to_html; * HTML encode vulnerable values to prevent XSS injection; data _null_; call symputx('BG', htmlencode(symget('bg'))); call symputx('DATASET', htmlencode(symget('dataset'))); run; %print_to_html;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Your code does not show where the value of &dataset is set. So we cannot tell what the actual value of the variable &dataset holds. Since you are using the SAS function Exist it is very likely that the data set parameter does not have any quotes because that will generate an error:
52 %let dataset= sas'help.cla'ss; ---------- 49 NOTE 49-169: The meaning of an identifier after a quoted string might change in a future SAS release. Inserting white space between a quoted string and the succeeding identifier is recommended. 53 %put Sysfunc result is: %sysfunc(exist(&dataset)) ; NOTE: Line generated by the macro variable "DATASET". 1 sas'help.cla'ss ---------- 49 Sysfunc result is: 0 NOTE 49-169: The meaning of an identifier after a quoted string might change in a future SAS release. Inserting white space between a quoted string and the succeeding identifier is recommended.
The 0 result means the data set doesn't exist.
The data set sashelp.class does exist as shown here:
54 %let dataset= sashelp.class; 55 %put Sysfunc result is: %sysfunc(exist(&dataset)) ; Sysfunc result is: 1
The form of data set names that would be acceptable to the Exist function would be 'some non-standard name'n. No quotes in the middle, the entire name would have to be within quotes and have an n following. So your EXIST always fails. and not of that header information gets by the data _null_ step.
Or perhaps you need to run the code with OPTIONS MPRINT and examine what is being generated in your macro.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
The value is being retrieved from the URL request here, with the actual value highlighted in red:
https://sampleapplicationserver/cgi-bin/broker?_SERVICE=default&_PROGRAM=SAMPLIB.WEBSAMP.PRINT_TO_HTML.SOURCE&_ENTRY=SAMPLIB.WEBSAMP.PRINT_TO_HTML.SOURCE&BGTYPE=COLOR&BG=%23FFFFFF&DATASET=SA%27SHELP.RE%27TAIL&TEMPFILE=Unknown
Just to reiterate, the %27 (single quotes) are not making it to the actual 'dataset' value, that it my question. Why are the single quotes not being interpreted? Other symbols, like: @$() seem to be interpreted alright, but the single quotes and percent signs, when passed in URL parameters do not get interpreted.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
So the app broker seems to be "cleaning" them out? @Vince_SAS may be able to shed some light.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
The quotation marks are stripped from the input parameter to prevent cross-site scripting code injections:
SAS/IntrNet 9.4: Application Dispatcher > PROC APPSRV Statement > UNSAFE='string'
If you have a good reason to access the value that was passed in, including the quotation marks, you can use the APPSRV_UNSAFE function:
SAS/IntrNet 9.4: Application Dispatcher > Development Tasks > Application Server Functions > APPSRV_UNSAFE Function
https://go.documentation.sas.com/doc/en/dispatch/9.4/n0gc4breypvrrzn1jfsuk607bcp2.htm
But it's called "unsafe" for a reason. You can read a little more about the cautions of using it in the SAS Viya documentation.
SAS 9.4 and SAS Viya 3.5 Programming Documentation > DATA Step Programming > Functions and CALL Routines > Dictionary of Functions and CALL Routines > COMPSRV_OVAL Function
Vince DelGobbo
SAS R&D