1- import { BaseJavaCstVisitorWithDefaults } from 'java-parser'
2- import { ManifestPlugin } from '../ManifestPlugin'
3- import { Severity , getRelativePath , searchKeywordInFile } from '../util'
4- import { getJavaFiles } from '../../utils/fileutils'
5- const { parse} = require ( 'java-parser' )
6- import * as fs from 'node:fs'
1+ import { BaseJavaCstVisitorWithDefaults } from 'java-parser'
2+ import { ManifestPlugin } from '../ManifestPlugin'
3+ import { Severity , getRelativePath , searchKeywordInFile } from '../util'
4+ import path from 'node:path' ;
5+ import { execFileSync } from 'node:child_process' ;
6+ const { execFile } = require ( 'child_process' ) ;
7+
78
89export default class ExportedComponentRule extends ManifestPlugin {
910 BAD_EXPORTED_TAGS = [
@@ -52,8 +53,6 @@ export default class ExportedComponentRule extends ManifestPlugin {
5253 'getShortExtra' ,
5354 'getStringArrayExtra' ,
5455 'getStringArrayListExtra' ,
55- 'getString' ,
56- 'getInt' ,
5756 ] ;
5857
5958 PROTECTED_BROADCASTS = [
@@ -250,26 +249,33 @@ if the Intent carries data that is tainted (2nd order injection)`;
250249 }
251250 }
252251
253- // // write a code to traverse directory recursively and get all java files
254- // const directoryPath =
255- // 'C:\\Users\\Shiva\\AndroidStudioProjects\\DEVAAVulnerableApp'
256- // let javaFiles = []
257- // javaFiles = getJavaFiles(directoryPath)
258- // // console.log(javaFiles)
259-
260- // for (const javaFile of javaFiles) {
261- // // read file using fs
262- // // const file = fs.readFileSync(javaFile, "utf8");
263- // // // console.log(file);
264- // // const cst = parse(file);
265- // // // console.log(cst);
266- // // const methodcollector = new MethodCollector();
267- // // // The CST result from the previous code snippet
268- // // methodcollector.visit(cst);
269- // // methodcollector.customResult.forEach((arrowOffset) => {
270- // // console.log(arrowOffset);
271- // // });
252+ // // check if enableAST flag is set
253+ // if (ManifestPlugin.isASTEnabled) {
254+ // const resourceDir = path.resolve(path.join(__dirname, "..", "..", "resource"))
255+
256+ // const javaPath = 'java';
257+ // const jarPath = path.join(resourceDir, 'android-project-parser-1.0-SNAPSHOT-shaded.jar');
258+ // const className = 'MainActivity';
259+
260+ // const args = [
261+ // '-jar',
262+ // jarPath,
263+ // 'find-methods-declaration-invocations-arguments',
264+ // ManifestPlugin.androidProjectDirectory,
265+ // className
266+ // ];
267+
268+ // execFile(javaPath, args, (error: Error | null, stdout: string, stderr: string) => {
269+ // if (error) {
270+ // console.error(`exec error: ${error}`);
271+ // } else {
272+ // const methodResults = JSON.parse(stdout)
273+ // console.log(methodResults[0].methodInvocations[6].methodName)
274+ // }
275+ // });
276+
272277 // }
278+
273279 }
274280
275281 checkManifestIssue ( exported_tag : string , tag : any ) : void {
@@ -279,11 +285,48 @@ if the Intent carries data that is tainted (2nd order injection)`;
279285 const name = tag . $ [ 'android:name' ]
280286 const tag_info = TAG_INFO [ exported_tag ]
281287 const isProvider = exported_tag === 'provider'
288+ let methodResults = [ ]
289+ let argumentVal : string [ ] = [ ]
282290
283291 if ( isExported === 'false' ) {
284292 return
285293 }
286294
295+ if ( ManifestPlugin . isASTEnabled ) {
296+ const resourceDir = path . resolve ( path . join ( __dirname , ".." , ".." , "resource" ) )
297+
298+ const javaPath = 'java' ;
299+ const jarPath = path . join ( resourceDir , 'android-project-parser-1.0-SNAPSHOT-shaded.jar' ) ;
300+ let lastDotIndex = name . lastIndexOf ( '.' ) ;
301+ const className = name . substring ( lastDotIndex + 1 ) ;
302+
303+ const args = [
304+ '-jar' ,
305+ jarPath ,
306+ 'find-methods-declaration-invocations-arguments' ,
307+ ManifestPlugin . androidProjectDirectory ,
308+ className
309+ ] ;
310+
311+ const result = execFileSync ( javaPath , args ) ;
312+
313+ if ( result ) {
314+ methodResults = JSON . parse ( result . toString ( ) ) ;
315+ if ( ! methodResults . errorMessage && methodResults . length > 0 ) {
316+ let declaredMethods = methodResults ;
317+ declaredMethods . forEach ( ( declaredMethod : { methodInvocations : any [ ] ; } ) => {
318+ if ( declaredMethod . methodInvocations . length > 0 ) {
319+ declaredMethod . methodInvocations . forEach ( ( methodInvocation : { methodName : string , arguments : [ ] } ) => {
320+ if ( this . EXTRAS_METHOD_NAMES . includes ( methodInvocation . methodName ) ) {
321+ argumentVal = argumentVal . concat ( methodInvocation . arguments )
322+ }
323+ } ) ;
324+ }
325+ } ) ;
326+ }
327+ }
328+ }
329+
287330 if ( ( isExported && isExported !== 'false' ) || isProvider ) {
288331 if (
289332 ( isProvider && ManifestPlugin . minSdk > 16 ) ||
@@ -299,7 +342,7 @@ if the Intent carries data that is tainted (2nd order injection)`;
299342 )
300343
301344 let description = this . EXPORTED_AND_PERMISSION_TAG
302- description = description . replace ( '{tag}' , exported_tag )
345+ description = description . replaceAll ( '{tag}' , exported_tag )
303346 description = description . replace ( '{tag_name}' , name )
304347
305348 this . issues . push ( {
@@ -311,6 +354,11 @@ if the Intent carries data that is tainted (2nd order injection)`;
311354 ManifestPlugin . androidProjectDirectory ,
312355 ManifestPlugin . manifestPath ,
313356 ) ,
357+ exploit : {
358+ "exported_enum" : name ,
359+ "tag_name" : exported_tag ,
360+ "arguments" : argumentVal ,
361+ } ,
314362 line : result ?. line ,
315363 start_column : result ?. start_column ,
316364 end_column : result ?. end_column ,
@@ -322,7 +370,7 @@ if the Intent carries data that is tainted (2nd order injection)`;
322370 )
323371
324372 let description = this . EXPORTED
325- description = description . replace ( '{tag}' , exported_tag )
373+ description = description . replaceAll ( '{tag}' , exported_tag )
326374 description = description . replace ( '{tag_name}' , name )
327375
328376 this . issues . push ( {
@@ -334,6 +382,12 @@ if the Intent carries data that is tainted (2nd order injection)`;
334382 ManifestPlugin . androidProjectDirectory ,
335383 ManifestPlugin . manifestPath ,
336384 ) ,
385+ exploit : {
386+ "exported_enum" : name ,
387+ "tag_name" : exported_tag ,
388+ "package_name" : ManifestPlugin . packageName ,
389+ "arguments" : argumentVal
390+ } ,
337391 line : result ?. line ,
338392 start_column : result ?. start_column ,
339393 end_column : result ?. end_column ,
@@ -355,7 +409,7 @@ if the Intent carries data that is tainted (2nd order injection)`;
355409 if ( this . PROTECTED_BROADCASTS . includes ( actionName ) ) {
356410
357411 let description = this . EXPORTED_IN_PROTECTED
358- description = description . replace ( '{tag}' , exported_tag )
412+ description = description . replaceAll ( '{tag}' , exported_tag )
359413 description = description . replace ( '{tag_name}' , name )
360414
361415 this . issues . push ( {
@@ -367,14 +421,20 @@ if the Intent carries data that is tainted (2nd order injection)`;
367421 ManifestPlugin . androidProjectDirectory ,
368422 ManifestPlugin . manifestPath ,
369423 ) ,
424+ exploit : {
425+ "exported_enum" : name ,
426+ "tag_name" : exported_tag ,
427+ "package_name" : ManifestPlugin . packageName ,
428+ "arguments" : argumentVal
429+ } ,
370430 line : result ?. line ,
371431 start_column : result ?. start_column ,
372432 end_column : result ?. end_column ,
373433 } )
374434 } else if ( permission && ManifestPlugin . minSdk < 20 ) {
375435
376436 let description = this . EXPORTED_AND_PERMISSION_TAG
377- description = description . replace ( '{tag}' , exported_tag )
437+ description = description . replaceAll ( '{tag}' , exported_tag )
378438 description = description . replace ( '{tag_name}' , name )
379439
380440 this . issues . push ( {
@@ -386,14 +446,20 @@ if the Intent carries data that is tainted (2nd order injection)`;
386446 ManifestPlugin . androidProjectDirectory ,
387447 ManifestPlugin . manifestPath ,
388448 ) ,
449+ exploit : {
450+ "exported_enum" : name ,
451+ "tag_name" : exported_tag ,
452+ "package_name" : ManifestPlugin . packageName ,
453+ "arguments" : argumentVal
454+ } ,
389455 line : result ?. line ,
390456 start_column : result ?. start_column ,
391457 end_column : result ?. end_column ,
392458 } )
393459 } else {
394460
395461 let description = this . EXPORTED
396- description = description . replace ( '{tag}' , exported_tag )
462+ description = description . replaceAll ( '{tag}' , exported_tag )
397463 description = description . replace ( '{tag_name}' , name )
398464
399465 this . issues . push ( {
@@ -404,6 +470,12 @@ if the Intent carries data that is tainted (2nd order injection)`;
404470 ManifestPlugin . androidProjectDirectory ,
405471 ManifestPlugin . manifestPath ,
406472 ) ,
473+ exploit : {
474+ "exported_enum" : name ,
475+ "tag_name" : exported_tag ,
476+ "package_name" : ManifestPlugin . packageName ,
477+ "arguments" : argumentVal
478+ } ,
407479 name : 'Exported Components Check' ,
408480 line : result ?. line ,
409481 start_column : result ?. start_column ,
@@ -454,36 +526,4 @@ const TAG_INFO: any = {
454526 activity : Activity ,
455527 'activity-alias' : Activity ,
456528 service : Service ,
457- }
458-
459- class MethodCollector extends BaseJavaCstVisitorWithDefaults {
460- customResult : any [ ] ;
461- constructor ( ) {
462- super ( )
463- this . customResult = [ ]
464- this . validateVisitor ( )
465- }
466-
467- // methodDeclarator - method declaration
468- // method
469-
470- // This method override gives you actual method declaration like onCreate, onClick, onCreateOptionsMenu
471- methodDeclarator ( ctx : any ) {
472- // console.log(ctx.Identifier[0].image);
473- this . customResult . push ( ctx . Identifier [ 0 ] . image )
474- }
475-
476- // this method resembles method invocation call
477- // methodInvocationSuffix(ctx: any) {
478- // console.log(ctx)
479- // }
480-
481- // this method gets you the method invoker argument list
482- // argumentList(ctx: any) {
483- // console.log(ctx.expression);
484- // }
485-
486- // importDeclaration(ctx: any) {
487- // console.log(ctx.packageOrTypeName[0].children.Identifier);
488- // }
489- }
529+ }
0 commit comments