Skip to content

Commit

Permalink
update exploit.md and exploit.c
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinrich1337 committed Oct 19, 2024
1 parent 227f0e4 commit 399dc65
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 7 deletions.
14 changes: 7 additions & 7 deletions pocs/linux/kernelctf/CVE-2023-4147_lts_cos/docs/exploit.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ We can trigger the vulnerability in LTS as follows:
- Create three chains, `Base`, `Vulnerable`, and `Victim`. Set `NFT_CHAIN_BINDING` flag for `Vulnerable`. If a chain with the `NFT_CHAIN_BINDING` flag set is bound to an immediate expr, when this expr is destroyed, the bound chain and its rules will also be destroyed.
- Create a rule in `Base` with an immediate expr referencing the `Vulnerable`.
- Create a rule in `Vulnerable` with an immediate expr referencing `Victim`.
- Trigger the vulnerability by replacing the rule in `Vulnerable`. This results in the `Victim` having a reference count of 0 `(nft_chain->use)`.
- Delete the rule in `Base` to deactivate the `Vulnerable` again. This results in the `Victim` having a reference count of -1.
- Trigger the vulnerability by replacing the rule in `Vulnerable`. This results in the `Victim` having a reference count `(nft_chain->use)` of 0.
- Delete the rule in `Base` to deactivate the `Vulnerable` again. This results in the `Victim` having a reference count `(nft_chain->use)` of -1.
We can trigger the vulnerability in COS as follows:
Expand Down Expand Up @@ -80,9 +80,9 @@ The KASLR address is leaked through `chain->name`, which is stored in the verdic
- Create three chains, `Base`, `Vulnerable`, and `Victim`. Set `NFT_CHAIN_BINDING` flag for `Vulnerable`. If a chain with the `NFT_CHAIN_BINDING` flag set is bound to an immediate expr, when this expr is destroyed, the bound chain and its rules will also be destroyed.
- Create a rule in `Base` with an immediate expr referencing the `Vulnerable`.
- Create a rule in `Vulnerable` with an immediate expr referencing `Victim`.
- Trigger the vulnerability by replacing the rule in `Vulnerable`. This results in the `Victim` having a reference count of 0 `(nft_chain->use)`.
- Delete the rule in `Base` to deactivate the `Vulnerable` again. This results in the `Victim` having a reference count of -1.
- Create an immediate expr in `Base` that references to the Victim, making the `Victim`'s reference count 0, and destroy the `Victim`.
- Trigger the vulnerability by replacing the rule in `Vulnerable`. This results in the `Victim` having a reference count `(nft_chain->use)` of 0.
- Delete the rule in `Base` to deactivate the `Vulnerable` again. This results in the `Victim` having a reference count `(nft_chain->use)` of -1.
- Create an immediate expr in `Base` that references to the Victim, making the `Victim`'s reference count `(nft_chain->use)` 0, and destroy the `Victim`.
- Spray counter exprs (struct nft_expr) to place it at `Victim`'s chain->name. At this time, the counter exprs are allocated in the `kmalloc-cg-16`.
- We dump the immediate expr of `Base` using `GETRULE` command, we can get the ops address of counter expr through the freed `chain->name` to get the kernel base address [5].

Expand Down Expand Up @@ -294,7 +294,7 @@ Starting with commit [4bedf9ee] (https://git.kernel.org/pub/scm/linux/kernel/git
The KASLR address and heap address are leaked through `nft_rule` allocated in `kmalloc-cg-192`. The leak process is as follows:

- Create four chains, `Base`, `Vulnerable`, `Chain_Victim`, and `Target`. Set `NFT_CHAIN_BINDING` flag for `Vulnerable`. If a chain with the `NFT_CHAIN_BINDING` flag set is bound to an immediate expr, when this expr is destroyed, the bound chain and its rules will also be destroyed.
- Create chains `Chain_Victim2_n`. In this exploit, 0x30 chains are sprayed.
- Create chains `Chain_Victim2_n` for the victim rules created in the next step. In this exploit, 0x30 chains are sprayed.
- Create an anonymous rhash set `Set_Victim`.
- Create a set element in set `Set_Victim`. The element is allocated in `kmalloc-cg-256`.

Expand Down Expand Up @@ -328,7 +328,7 @@ static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
}
```

- Spray rhash sets `Set_Spray_n`. When destroying an `nf_tables_set_elem_destroy` element, `nft_set_ext` is used [10], and `nft_set_ext` is retrieved by referencing `set->ops->elemsize` [12]. Thus, a rhash set with `elemsize` of 8 is overwritten by an rbtree set with `elemsize` of 24, causing the `nft_set_elem_expr_destroy` to reference the wrong `nft_set_ext`. We manipulate the offset to destroy the `immedieate expr` in `Rule_Victim_n`, that is allocated after the element, in [11]. This frees `Rule_Victim2_n` of `Chain_Victim2_n` in the `nft_immediate_destroy`. However, `Chain_Victim2_n` and `Rule_Victim2_n` are remain accessible.
- Spray rhash sets `Set_Spray_n`. When destroying an `nf_tables_set_elem_destroy` element, `nft_set_ext` is used [10], and `nft_set_ext` is retrieved by referencing `set->ops->elemsize` [12]. Thus, a rhash set with `elemsize` of 8 is overwritten by an rbtree set with `elemsize` of 24, causing the `nft_set_elem_expr_destroy` to reference the wrong `nft_set_ext`. We manipulate the offset to destroy the `immedieate expr` in `Rule_Victim_n`, that is allocated after the element, in [11]. This frees `Rule_Victim2_n` of `Chain_Victim2_n` in the `nft_immediate_destroy`. However, `Chain_Victim2_n` and `Rule_Victim2_n` remain accessible.
- Spray fake rules using `nft_table->udata` into freed `Rule_Victim2_n` (`kmalloc-cg-192`). Set `nft_rule->udata` of the fake rule to 1 and `nft_rule->udata->len` to 0xff.
- Get the fake rule will read 0xff bytes start from `nft_rule->udata`. As a result, we can obtain kbase (`nft_last_ops`) and heap address (`nft_rule.list.next` and `nft_rule.list.prev`) of `Rule_Targret_n`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ void save_state(void) {
return;
}

// We can put everthing in the Table1. Just need to change the rule_handle.
char * table1_name = "table1";
char * table2_name = "table2";
char * table3_name = "table3";
Expand Down Expand Up @@ -573,6 +574,7 @@ void trig(){
nftnl_rule_nlmsg_build_payload(nlh, rule_bind_chain_1_2_del);
mnl_nlmsg_batch_next(batch);

// create a delay to spray sets_rbtree[]
nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_DELSET, family, 0, seq++);
nftnl_set_nlmsg_build_payload(nlh, set_delay);
mnl_nlmsg_batch_next(batch);
Expand Down

0 comments on commit 399dc65

Please sign in to comment.