> For the complete documentation index, see [llms.txt](https://simon-6.gitbook.io/simoncyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simon-6.gitbook.io/simoncyber/portswigger-web-academy/sql-injection/lab-11.md).

# Lab 11

The techniques for triggering a time delay are specific to the type of database being used. For example, on Microsoft SQL Server, you can use the following to test a condition and trigger a delay depending on whether the expression is true:

`'; IF (1=2) WAITFOR DELAY '0:0:10'-- '; IF (1=1) WAITFOR DELAY '0:0:10'--`

<figure><img src="/files/uLtRHhTQrvTL9RKISQyk" alt=""><figcaption></figcaption></figure>

Since this shows no error or output, we'll need to assume the database. Since most databases are PostgreSQL, we'll be using the "`SELECT pg_sleep(10)"` method.&#x20;

The core idea: instead of trying to read data back from the response, you make the database itself stall for a measurable amount of time when a condition is true. `WAITFOR DELAY '0:0:10'` is SQL Server's sleep function. So `IF (1=2) WAITFOR DELAY '0:0:10'` never delays (false condition), while `IF (1=1) WAITFOR DELAY '0:0:10'` always delays 10 seconds (true condition). You're using response latency as a side channel to exfiltrate boolean answers.

<figure><img src="/files/7Fu5G7sksLc8jGGwheAb" alt=""><figcaption></figcaption></figure>

The payload to induce a 10 second wait is:\
`TrackingId=x'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END--`

The reason why we URL-encoded this one as to suppose other is the delimiter.&#x20;

{% hint style="info" %}
Cookie header → `;` and `,` are delimiters, encode them. Query string → `&` and `=` matter. URL path → `/` matters. Any header → watch for `\r\n` (CRLF injection). Rule: encode whatever character the *current parsing layer* uses to know where your value ends — that's the only one that'll actually break your payload if left raw.
{% endhint %}

Hence, we'll need to encode the ";" part. Keep in mind, even if you replace the "+" with spaces, it still works.

<figure><img src="/files/PtLpI4OgGtDhIqsVCzcY" alt=""><figcaption></figcaption></figure>

However, if you don't replace the ";" with an url encoded character, it doesn't work.&#x20;

<figure><img src="/files/U6101HRQgx6ULZZbS6rW" alt=""><figcaption></figcaption></figure>

So using the cheat sheet:\
![](/files/6fi9gZN5WMiQx2jzedcB)

{% hint style="info" %}
You would need to use the "END" because of the CASE. `END` is just SQL grammar — every `CASE WHEN ... THEN ... ELSE ... END` block requires a matching `END` to close it. It's not optional syntax, it's literally how you terminate a CASE expression. Leave it off and you get a syntax error, full stop.
{% endhint %}

<figure><img src="/files/0YwVwrflNIR8p4VfrPwX" alt=""><figcaption></figcaption></figure>

Hence, we can replace the 1=1 with confirmation that a username with administrator exists.&#x20;

<figure><img src="/files/F6tcUR2gatpkg91UFkR5" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/w2IPNORLfVPPXua0sht4" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/DZfmVmZX4f4iqqWO3ORQ" alt=""><figcaption></figcaption></figure>

I then added the lists, a-z, A-Z, and 0-9.&#x20;

<figure><img src="/files/6jKkckF3sJP7aoO0yXYV" alt=""><figcaption></figcaption></figure>

After a quick moment, all of the lengths remained the same (as expected since this is Blind), but one has an odd amount of responses. It turns out the letter "e" was the first one! I'm not going to do the entire thing but you get it.&#x20;
