Détection des piratages web via des sondes linux
Frédéric VANNIÈRE - Homere
f.vanniere@planet-work.com
Sysadmin #7 - 19-20 octobre 2017
Présentation
- sysadmin depuis 2001
- hébergement mutualisé
- serveurs infogérés
Previously on ...
- blocage des attaques web (bruteforce)
- rsyslog, hekad, nginx/openresty
- php-malware-scanner
Contexte
- 10 000 sites
- 30% Wordpress
- nombreuses attaques, sites piratés
- détection lors d'une action malveillante
Besoin d'un système de détection
Mutualisé
Apache / PHP
Apache / PHP
Apache / PHP
Openresty
NFS (NetApp)
Apache / PHP
Openresty
Dédié
ext4 / ZFS
Piratage web
- upload de scripts PHP
- injection de backdoors
- action malveillante :
- envoi de spam
- propagation, attaques de sites
- connexion C&C / IRC
- flood UDP
- site de pishing
détection
Solutions envisagées
- NetApp fpolicy
- inotify
-
while true ; do netstat -natpe | grep -q 6667 && alert ; sleep 1 ; done
BCC / BPF
- Linux ≥ 4.1
- sonde noyau linux (module)
- jeu d'instructions limité / sandbox
- interface espace utilisateur noyau
- performant
int trace_read_entry(struct pt_regs *ctx, struct file *file,
char __user *buf, size_t count)
{
u32 tgid = bpf_get_current_pid_tgid() >> 32;
if (TGID_FILTER)
return 0;
u32 pid = bpf_get_current_pid_tgid();
// skip I/O lacking a filename
struct dentry *de = file->f_path.dentry;
int mode = file->f_inode->i_mode;
if (de->d_name.len == 0 || TYPE_FILTER)
return 0;
// store counts and sizes by pid & file
struct info_t info = {.pid = pid};
bpf_get_current_comm(&info.comm, sizeof(info.comm));
info.name_len = de->d_name.len;
bpf_probe_read(&info.name, sizeof(info.name), (void *)de->d_name.name);
if (S_ISREG(mode)) {
info.type = 'R';
} else if (S_ISSOCK(mode)) {
info.type = 'S';
} else {
info.type = 'O';
}
struct val_t *valp, zero = {};
valp = counts.lookup_or_init(&info, &zero);
if (is_read) {
valp->reads++;
valp->rbytes += count;
} else {
valp->writes++;
valp->wbytes += count;
}
return 0;
}
llvm
Linux
BPF
perf
Python BCC
__sys_execve()
__sys_open()
__tcp_v4_connect()
__vfs_read()
Exemple : opensnoop
root@celia:/usr/share/bcc/tools# ./opensnoop -n apache2
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/fields/class-wp-rest-comment-meta-fields.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/fields/class-wp-rest-post-meta-fields.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/fields/class-wp-rest-term-meta-fields.php
3749 apache2 16 0 /home/epingle/www/wp-includes/rest-api/fields/class-wp-rest-user-meta-fields.php
3749 apache2 16 0 /home/epingle/www/wp-includes/vars.php
3750 apache2 13 0 /usr/share/zoneinfo/America/Argentina
3750 apache2 13 0 /usr/share/zoneinfo/America/Indiana
3749 apache2 16 0 /home/epingle/www/wp-content/plugins/akismet/akismet.php
3749 apache2 16 0 /home/epingle/www/wp-content/plugins/akismet/class.akismet.php
3749 apache2 16 0 /home/epingle/www/wp-content/plugins/akismet/class.akismet-widget.php
3749 apache2 16 0 /home/epingle/www/wp-content/plugins/akismet/wrapper.php
3749 apache2 16 0 /home/epingle/www/wp-content/plugins/counterize/counterize.php
3749 apache2 16 0 /dev/urandom
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/counterize/counterize_browsniff.php
3750 apache2 13 0 /usr/share/zoneinfo/America/Kentucky
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/counterize/counterize_iptocountry.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/counterize/ip_files/countries.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/counterize/counterize_feed.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/jw-player-plugin-for-wordpress/jwplayermodule.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/jw-player-plugin-for-wordpress/jwp6/jwp6-plugin.php
3750 apache2 13 0 /usr/share/zoneinfo/America/North_Dakota
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/jw-player-plugin-for-wordpress/jwp6/jwp6-class-plugin.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/jw-player-plugin-for-wordpress/jwp6/jwp6-class-player.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/jw-player-plugin-for-wordpress/jwp6/jwp6-class-shortcode.php
3750 apache2 13 0 /usr/share/zoneinfo/Antarctica
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/jw-player-plugin-for-wordpress/jwp6/jwp6-class-legacy.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/options-framework/options-framework.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/php-code-widget/execphp.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/wp_related_posts.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/init.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/config.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/lib/stemmer.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/lib/mobile_detect.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/admin_notices.php
3750 apache2 13 0 /usr/share/zoneinfo/Arctic
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/widget.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/thumbnailer.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/settings.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/uploader.php
3749 apache2 17 0 /home/epingle/www/wp-content/plugins/related-posts/recommendations.php
Exemple : tcpconnect
root@celia:/usr/share/bcc/tools# ./tcpconnect -P 80
PID COMM IP SADDR DADDR DPORT
5187 apache2 4 192.168.3.27 109.1.151.41 80
5187 apache2 4 192.168.3.27 109.1.151.41 80
5246 apache2 4 192.168.3.27 212.27.63.116 80
5249 apache2 4 192.168.3.27 54.239.39.136 80
5249 apache2 4 192.168.3.27 54.239.39.136 80
5249 apache2 4 192.168.3.27 54.239.39.136 80
5249 apache2 4 192.168.3.27 54.239.39.136 80
5255 apache2 4 192.168.3.27 109.1.151.41 80
5255 apache2 4 192.168.3.27 109.1.151.41 80
5358 apache2 4 192.168.3.27 212.27.63.116 80
5479 apache2 4 192.168.3.27 79.99.164.4 80
5479 apache2 4 192.168.3.27 178.237.36.10 80
5633 apache2 4 192.168.3.27 91.240.109.21 80
5640 apache2 4 192.168.3.27 212.27.63.116 80
5671 apache2 4 192.168.3.27 195.154.241.86 80
5677 apache2 4 192.168.3.27 79.99.164.4 80
5720 apache2 4 192.168.3.27 35.187.79.8 80
5720 apache2 4 192.168.3.27 35.187.79.8 80
5720 apache2 4 192.168.3.27 35.187.79.8 80
5720 apache2 4 192.168.3.27 35.187.79.8 80
Webserver Gets a Probe
- module noyau BCC/BPF
- Python 3
- sonde + collecteur
- compatible container
Événements
-
Écriture de fichier : __sys_open
- Connexion TCP : __tcp_v[46]_connect
- Écoute de port : __inet_listen
- Éxécution de programme : __sys_execve
Hindsight
wgap-probe
events
BPF
pms
NFS / filesystem
API PW
__sys_execve()
__inet_listen()
__tcp_v4_connect()
__sys_open()
int trace_sys_open_entry(struct pt_regs *ctx, const char __user *filename, int flags, umode_t mode)
{
struct val_t val = {};
u32 tgid = bpf_get_current_pid_tgid() >> 32;
u32 uid = (unsigned)(bpf_get_current_uid_gid() & 0xffffffff);
val.mode = 'R';
if (flags & (O_WRONLY | O_RDWR)) {
val.mode = 'W';
}
if (MODE_FILTER)
return 0;
if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
val.id = id;
val.ts_us = bpf_ktime_get_ns() / 1000;
val.data1 = filename;
val.uid = uid;
}
}
int trace_sys_open_return(struct pt_regs *ctx)
{
u64 id = bpf_get_current_pid_tgid();
struct val_t *valp;
struct data_t data = {};
u64 tsp = bpf_ktime_get_ns() / 1000;
valp = infotmp.lookup(&id);
bpf_probe_read(&data.comm, sizeof(data.comm), valp->comm);
bpf_probe_read(&data.data1, sizeof(data.data1), (void *)valp->data1);
data.id = valp->id;
data.pid = id >> 32;
data.uid = (u32) bpf_get_current_uid_gid();
data.mode = valp->mode;
data.ts_us = tsp / 1000;
data.ret = PT_REGS_RC(ctx);
events.perf_submit(ctx, &data, sizeof(data));
}
:Uuid: DD81D7FD-B6E3-4732-A980-AF464C1B5834
:Timestamp: 2017-10-18T07:03:08.415656192Z
:Type: wgap_callback
:Logger: upload_php
:Severity: 6
:Payload:
:EnvVersion: 0.8
:Pid: 2730
:Hostname: celia
:Fields:
| name: pid type: 2 representation: value: 6667
| name: user type: 0 representation: value: homere
| name: filename type: 0 representation: value: /home/homere/www/xx.php
| name: tenant type: 0 representation: value: mutupw
| name: timestamp type: 0 representation: value: 2017-10-18T09:03:08.415656+00:00
| name: appname type: 0 representation: value: touch
| name: message type: 0 representation: value: homere@mutupw touch[6667] file_write: /home/homere/www/xx.php
| name: event type: 0 representation: value: file_write
| name: uid type: 2 representation: value: 2000
Chez les autres ?
- Upload shell PHP (FilesMan)
- écoute sur port 6667 (C&C)
- exécution de getent passwd, ifconfig et uname
- paquets UDP vers port 123
- se connecter à 50 Wordpress différents en HTTP
- se connecter à 50 Wordpress différents en HTTPs
Aucune réaction (mail, blocage ...)
Plus loin avec BCC / BPF
- nombreux outils
- sondes espace utilisateur (MySQL)
- Réseau : XDP
Cas pratique de BCC
- surcharge NFS en lecture sur le mutualisé
- saturation du réseau local, du stockage
- aléatoire et peu fréquent (2 fois par an)
- source inconnue
Merci !
Détections des attaques web en temps réel
By Frédéric VANNIÈRE
Détections des attaques web en temps réel
IDS web basé sur les outils noyau linux BCC /BPF et Hindsight
- 2,183