55import com .alibaba .fastjson .JSONException ;
66import com .alibaba .fastjson .JSONObject ;
77import io .dongtai .iast .common .constants .ApiPath ;
8+ import io .dongtai .iast .core .handler .hookpoint .models .taint .range .TaintCommand ;
9+ import io .dongtai .iast .core .handler .hookpoint .models .taint .range .TaintCommandRunner ;
10+ import io .dongtai .iast .core .handler .hookpoint .models .taint .tag .TaintTag ;
811import io .dongtai .iast .core .handler .hookpoint .vulscan .VulnType ;
912import io .dongtai .iast .core .utils .HttpClientUtils ;
1013import io .dongtai .iast .core .utils .StringUtils ;
@@ -24,7 +27,10 @@ public class PolicyBuilder {
2427 private static final String KEY_SIGNATURE = "signature" ;
2528 private static final String KEY_INHERIT = "inherit" ;
2629 private static final String KEY_VUL_TYPE = "vul_type" ;
30+ private static final String KEY_TAGS = "tags" ;
31+ private static final String KEY_UNTAGS = "untags" ;
2732 private static final String KEY_COMMAND = "command" ;
33+ private static final String KEY_STACK_BLACKLIST = "stack_blacklist" ;
2834 private static final String KEY_IGNORE_INTERNAL = "ignore_internal" ;
2935 private static final String KEY_IGNORE_BLACKLIST = "ignore_blacklist" ;
3036
@@ -69,7 +75,7 @@ public static Policy build(JSONArray policyConfig) throws PolicyException {
6975 buildPropagator (policy , nodeType , node );
7076 buildSink (policy , nodeType , node );
7177 } catch (PolicyException e ) {
72- DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ), e . getMessage () );
78+ DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ), e );
7379 }
7480 }
7581 return policy ;
@@ -99,12 +105,12 @@ public static void buildPropagator(Policy policy, PolicyNodeType type, JSONObjec
99105 Set <TaintPosition > sources = parseSource (node , type );
100106 Set <TaintPosition > targets = parseTarget (node , type );
101107 MethodMatcher methodMatcher = buildMethodMatcher (node );
102- // @TODO: command
103- PropagatorNode propagatorNode = new PropagatorNode (sources , targets , null , new String []{}, methodMatcher );
108+ PropagatorNode propagatorNode = new PropagatorNode (sources , targets , methodMatcher );
104109 setInheritable (node , propagatorNode );
105110 List <String []> tags = parseTags (node , propagatorNode );
106111 propagatorNode .setTags (tags .get (0 ));
107112 propagatorNode .setUntags (tags .get (1 ));
113+ parseCommand (node , propagatorNode );
108114 parseFlags (node , propagatorNode );
109115 policy .addPropagator (propagatorNode );
110116 }
@@ -124,7 +130,7 @@ public static void buildSink(Policy policy, PolicyNodeType type, JSONObject node
124130 }
125131 setInheritable (node , sinkNode );
126132 sinkNode .setVulType (vulType );
127- sinkNode . setStackDenyList ( parseStackDenyList (sinkNode ) );
133+ parseStackDenyList (node , sinkNode );
128134 parseFlags (node , sinkNode );
129135 policy .addSink (sinkNode );
130136 }
@@ -212,43 +218,156 @@ private static MethodMatcher buildMethodMatcher(JSONObject node) throws PolicyEx
212218
213219 /**
214220 * stack deny list for sink node
215- * TODO: parse stack deny list from policy
216221 */
217- private static String [] parseStackDenyList (SinkNode node ) {
218- if (!(node .getMethodMatcher () instanceof SignatureMethodMatcher )) {
219- return new String [0 ];
220- }
221-
222- String signature = ((SignatureMethodMatcher ) node .getMethodMatcher ()).getSignature ().toString ();
223- if ("java.lang.Class.forName(java.lang.String)" .equals (signature )) {
224- return new String []{"java.net.URL.getURLStreamHandler" };
225- } else if ("java.lang.Class.forName(java.lang.String,boolean,java.lang.ClassLoader)" .equals (signature )) {
226- return new String []{"org.jruby.javasupport.JavaSupport.loadJavaClass" };
222+ private static void parseStackDenyList (JSONObject node , SinkNode sinkNode ) {
223+ try {
224+ if (node .has (KEY_STACK_BLACKLIST )) {
225+ JSONArray arr = node .getJSONArray (KEY_STACK_BLACKLIST );
226+ sinkNode .setStackDenyList (arr .toList ().toArray (new String [0 ]));
227+ }
228+ } catch (JSONException ignore ) {
229+ DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ),
230+ new PolicyException (PolicyException .ERR_POLICY_NODE_STACK_BLACKLIST_INVALID + ": " + node .toString ()));
231+ } catch (ArrayStoreException ignore ) {
232+ DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ),
233+ new PolicyException (PolicyException .ERR_POLICY_NODE_STACK_BLACKLIST_INVALID + ": " + node .toString ()));
227234 }
228-
229- return new String [0 ];
230235 }
231236
232237 private static List <String []> parseTags (JSONObject node , PolicyNode policyNode ) {
233238 List <String []> empty = Arrays .asList (new String [0 ], new String [0 ]);
234239 if (!(policyNode .getMethodMatcher () instanceof SignatureMethodMatcher )) {
235240 return empty ;
236241 }
237- String signature = ((SignatureMethodMatcher ) policyNode .getMethodMatcher ()).getSignature ().toString ();
238242
239- // TODO: parse tags/untags from policy
240- List <String []> taintTags = PolicyTag .TAGS .get (signature );
241- if (taintTags == null || taintTags .size () != 2 ) {
242- return empty ;
243+ boolean hasInvalid = false ;
244+ List <String > tags = new ArrayList <String >();
245+ List <String > untags = new ArrayList <String >();
246+ try {
247+ if (node .has (KEY_TAGS )) {
248+ JSONArray ts = node .getJSONArray (KEY_TAGS );
249+ for (Object o : ts ) {
250+ String t = (String ) o ;
251+ if (TaintTag .UNTRUSTED .equals (t )) {
252+ continue ;
253+ }
254+ if (TaintTag .get (t ) != null ) {
255+ tags .add (TaintTag .get (t ).getKey ());
256+ } else {
257+ hasInvalid = true ;
258+ }
259+ }
260+ }
261+ } catch (JSONException ignore ) {
262+ hasInvalid = true ;
263+ } catch (ClassCastException ignore ) {
264+ hasInvalid = true ;
265+ }
266+
267+ try {
268+ if (node .has (KEY_TAGS )) {
269+ JSONArray uts = node .getJSONArray (KEY_UNTAGS );
270+ for (Object o : uts ) {
271+ String ut = (String ) o ;
272+ if (TaintTag .UNTRUSTED .equals (ut )) {
273+ continue ;
274+ }
275+ TaintTag tt = TaintTag .get (ut );
276+ if (tt != null ) {
277+ if (tags .contains (tt .getKey ())) {
278+ hasInvalid = true ;
279+ }
280+ untags .add (tt .getKey ());
281+ } else {
282+ hasInvalid = true ;
283+ }
284+ }
285+ }
286+ } catch (JSONException ignore ) {
287+ hasInvalid = true ;
288+ } catch (ClassCastException ignore ) {
289+ hasInvalid = true ;
243290 }
244291
245- return taintTags ;
292+ if (hasInvalid ) {
293+ DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ),
294+ new PolicyException (PolicyException .ERR_POLICY_NODE_TAGS_UNTAGS_INVALID + ": " + node .toString ()));
295+ }
296+
297+ return Arrays .asList (tags .toArray (new String [0 ]), untags .toArray (new String [0 ]));
298+ }
299+
300+ private static void parseCommand (JSONObject node , PropagatorNode propagatorNode ) {
301+ try {
302+ if (node .has (KEY_COMMAND )) {
303+ String cmdConfig = node .getString (KEY_COMMAND );
304+ if (cmdConfig == null ) {
305+ return ;
306+ }
307+ cmdConfig = cmdConfig .trim ();
308+ if (cmdConfig .isEmpty ()) {
309+ return ;
310+ }
311+
312+ boolean isInvalid = false ;
313+ int parametersStartIndex = cmdConfig .indexOf ("(" );
314+ int parametersEndIndex = cmdConfig .indexOf (")" );
315+
316+ if (parametersStartIndex <= 0 || parametersEndIndex <= 1
317+ || parametersStartIndex > parametersEndIndex
318+ || parametersEndIndex != cmdConfig .length () - 1 ) {
319+ isInvalid = true ;
320+ } else {
321+ String cmd = cmdConfig .substring (0 , parametersStartIndex ).trim ();
322+ String argumentsStr = cmdConfig .substring (parametersStartIndex + 1 , parametersEndIndex ).trim ();
323+ String [] arguments = new String []{};
324+ if (!argumentsStr .isEmpty ()) {
325+ argumentsStr = argumentsStr .toUpperCase ();
326+ arguments = argumentsStr .replace (" " , "" ).split ("," );
327+ for (String argument : arguments ) {
328+ String dig = argument ;
329+ if (dig .startsWith ("P" )) {
330+ dig = dig .substring (1 );
331+ }
332+ if (!dig .matches ("\\ d+" )) {
333+ isInvalid = true ;
334+ break ;
335+ }
336+ }
337+ }
338+
339+ TaintCommand command = TaintCommand .get (cmd );
340+ if (command == null ) {
341+ isInvalid = true ;
342+ } else {
343+ if (!(propagatorNode .getMethodMatcher () instanceof SignatureMethodMatcher )) {
344+ return ;
345+ }
346+ String signature = ((SignatureMethodMatcher ) propagatorNode .getMethodMatcher ()).getSignature ().toString ();
347+ TaintCommandRunner commandRunner = TaintCommandRunner .create (signature , command , arguments );
348+ propagatorNode .setCommandRunner (commandRunner );
349+ }
350+ }
351+
352+ if (isInvalid ) {
353+ DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ),
354+ new PolicyException (PolicyException .ERR_POLICY_NODE_RANGE_COMMAND_INVALID + ": " + node .toString ()));
355+ }
356+ }
357+ } catch (JSONException ignore ) {
358+ DongTaiLog .warn (ErrorCode .get ("POLICY_CONFIG_INVALID" ),
359+ new PolicyException (PolicyException .ERR_POLICY_NODE_RANGE_COMMAND_INVALID + ": " + node .toString ()));
360+ }
246361 }
247362
248363 private static void parseFlags (JSONObject node , PolicyNode policyNode ) {
249364 try {
250365 boolean ignoreInternal = node .getBoolean (KEY_IGNORE_INTERNAL );
251366 policyNode .setIgnoreInternal (ignoreInternal );
367+ } catch (JSONException ignore ) {
368+ }
369+
370+ try {
252371 boolean ignoreBlackList = node .getBoolean (KEY_IGNORE_BLACKLIST );
253372 policyNode .setIgnoreBlacklist (ignoreBlackList );
254373 } catch (JSONException ignore ) {
0 commit comments