05PHP个人博客
Jackie

文件操作&上传&下载&删除&读取&写入等

  • 文件上传类:任意文件上传
  1. 代码自主编写
  2. 编辑器引用
  • 文件下载类:任意文件下载
  1. 直连URL访问
  2. 传参头部修改
  • 文件删除类:任意文件删除
  1. 文件删除
  2. 文件夹删除
  • 文件内容操作类:任意文件读取&写入
  1. 文件读取
  2. 文件写入
  • 文件包含——任意文件包含
  1. 本地文件包含
  2. 远程文件包含
  • Web漏洞核心
  1. 可控变量
  2. 特定函数

站在开发角度看问题→漏洞

输入输出类&留言板&访问IP&UA头来源

  • PHP-全局变量$_SERVER
  • MySQL-插入语法INSERT
  • 输入输出-XSS&反射&存储
  • 安全问题-XSS跨站&CSRF等

通过userAgent判断设备信息 userAgent常用大全

const ua = window.navigator.userAgent || window.navigator.vendor || window.opera

// 是否为智能设备
export const IS_SMART_DEVICE = (/iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/).test(ua)

// 是否为 IOS 浏览器
export const IS_IOS_BROWSER = (/iPhone|iPod|iPad/).test(ua)

// 是否为 Android 浏览器
export const IS_ANDROID_BROWSER = (/Android/).test(ua)

// PC浏览器, 非智能设备
export const IS_NOT_SMART_DEVICE = !IS_SMART_DEVICE

// 微信内
export const IS_WECHAT_APP = (/MicroMessenger/).test(ua)

// APP 内置浏览器 这个是我们跟客服端定义的一个字段 因为有些页面要作为webview嵌套 客户端那边可以在userAgent后面添加参数 可扩展性比较高 也可以加上当前APP版本号
export const IS_APP_WEBVIEW = (/Enjoyrv/).test(ua)

// iPhone 内置浏览器
export const IS_IOS_APP = IS_APP_WEBVIEW && (/iPhone|iPod|iPad/).test(ua)

// Android 内置浏览器
export const IS_ANDROID_APP = IS_APP_WEBVIEW && (/Android/).test(ua) && (/Enjoyrv/).test(ua)

// 智能设备, 但非APP内置浏览器
export const IS_SMART_DEVICE_BROWSER_ONLY = IS_SMART_DEVICE && !IS_APP_WEBVIEW

// 访问设备来源
export const getDeviceType = function () {
if (IS_IOS_APP) {
return 'APP_IOS'
}
if (IS_ANDROID_APP) {
return 'APP_ANDROID'
}
if (IS_WECHAT_APP && IS_ANDROID_BROWSER) {
return 'WECHAT_APP_ANDROID'
}
if (IS_WECHAT_APP && IS_IOS_BROWSER) {
return 'WECHAT_APP_IOS'
}
if (IS_NOT_SMART_DEVICE) {
return 'PC_BROWSER'
}
if (IS_IOS_BROWSER) {
return 'IOS_BROWSER'
}
if (IS_ANDROID_BROWSER) {
return 'ANDROID_BROWSER'
}
if (IS_SMART_DEVICE) {
return 'UNKNOWN_SMART_DEVICE'
}
return ''
}

登录验证&Cookie&Session&验证码安全

  • Cookie:存储到客户端浏览器内

Cookie修改、伪造、盗取

  • Session:存储到服务端服务器内

会话劫持(Session劫持)

验证码

  1. 验证码可爆破

对于验证码位数4-6且没有次数限制和时间限制,或者时间过程我们均可进行验证码的爆破

image

爆破后根据长度回显来判断哪一个验证码是正确的

  1. 验证码回显

验证码存在于请求包或响应包里

image

  1. 验证码复用

使用的验证码没有进行销毁处理,能够一直使用

image

burp右键发送到repeater模块,两次点击go观察返回包若回显信息一样则证明可复用

从安全角度讲,每次登录验证码都要变

每次登录验证码都变化的情况可以使用验证码识别插件

可以写在一些安全的修复方法上,这也是能够得到一定的认可的

  1. 验证码可控

验证长度或内容可以被我们进行修改

image

phone=18888888888&code=6
phone=18888888888&code=zyzm

例如上图抓包前面是电话号码,后面code=6,将6改为4,我们可以收到4位数验证码

或此处就是它的验证码,可以将这里进行修改,修改为别的接着发送,我们就能收到什么样的验证码

  1. 修改返回包

验证只在本地验证,通过修改返回包进行绕过

image

false改为success、true,400改为200,0改为1或-1

  1. 双写导致验证码转发

加个逗号后面接上需要转发的手机号,因为开发可能使用数组就导致同时把验证码发给两个手机号

mobi=18888888888,17777777777
mobi=18888888888&mobi=17777777777
  1. 随意验证码

填写任意满足位数需求的验证码都能完成登录

原因:有验证码功能模块,但验证模块与业务功能没有什么关联性,即无论输入什么或者不输入验证码都判断验证码安全

  1. 万能验证码

由于开发的失误,上线测试时设置了万能验证码方便登录调试,但上线后却没有进行删除导致万能验证码的存在

image

验证码可以使用0000/8888/000000/888888等一系列便于记忆的相同数字进行尝试

  1. 验证码为空

将验证码字段修改为空或者null,即可进行绕过

mobil=18888888888&code=
mobil=18888888888&code=null
mobil=18888888888&code=true
mobil=18888888888&code=1
  1. 绑定关系存在缺陷

只验证了验证码,没有做账号绑定

image

mobil=18888888888  收到验证码
mobil=19999999999 收到验证码123456
mobil=18888888888&code=123456
  1. 特殊字符绕过

手机号码前后加空格,86,086,0086,+86,0,00,/r,/n以及特殊符号等

或者在手机号码最后多添加一位数字,因为12位经过短信网关取前11位,导致短信轰炸

mobi=8618888888888
mobi= 18888888888
mobi=0018888888888
mobi=/r18888888888
  1. 特殊的绕过点

有些验证码是通过cookie中的PHPSESSID来判断的

修改PHPSESSID,成功绕过了验证码限制

image

此处说验证码必须存在,但是修改PHPSESSID后

image

可绕过验证码的判定,从而实现账号密码的枚举

  1. ip的伪造绕过

程序只对访问者的错误次数与ip进行绑定,通过XXF伪造ip从而进行绕过限制

X-Forwarded-For:127.0.0.1
X-Remote-IP:127.0.0.1
X-Client-IP:127.0.0.1
X-Real-IP:127.0.0.1
Client-IP:127.0.0.1
X-Originating-IP:127.0.0.1
X-Remote-Addr;127.0.0.1
  1. 删除Cookie绕过

虽然有验证码,但是只要抓包后把Cookie去掉即可,之后就再也没有验证码提示

image

  1. 并发验证码

通过并发验证码请求数据包,导致可以短时间内收到大量短信,从而实现短信轰炸

  1. 验证码DOS

原理:图形验证码的生成大多都基于复杂的图像生成算法,本来就很消耗CPU、GPU性能,此时攻击者再把尺寸增大,就会成倍消耗性能,如果大到一定程度再结合高并发,服务器很有可能瞬间崩溃,也就造成了DOS攻击,修改数据包验证码的长宽,如果响应字节变大则存在该漏洞

接口:https://www.xxx.com/xxx?width=162&height=162

如果没有参数可以自己添加尝试

height=1111
h=1111
size=1111
margin=1111

不仅仅是验证码可以出现,该漏洞二维码也是可以的

image

image

  1. 时间戳绕过

很多发送验证码的时候都会出现类似time参数,对于这类参数大多都是使用时间戳来验证,只需将时间提前即可绕过,比如抓到的包时间是08:09,直接改为08:20,它会比时间戳多出一两个数字

时间戳在线转换地址

image

  1. 验证码前端验证

验证码的检测是由前端进行的,可以通过禁用js的方式从而实现绕过

验证码由客户端js生成并且仅仅在客户端用js验证,通过抓包看是否有验证码字段,或者是关闭js看能否通过验证

  1. 验证码后端验证

端验证码是由后端生成的验证码。当用户打开登录页面后,浏览器会向服务器发送请求并携带生成的令牌token,服务器随机生成验证码并将验证码和token对应关系存储在Redis缓存中,之后会在前端动态的生成一张验证码图片。当用户输入验证码并点击登录的时候,服务器会在Redis缓存中找到该浏览器的token对应的验证码,验证验证码是否正确,如果正确,接下来开始比较用户名和密码

image

可看到回显数据包中也有一个336

image

比如这是第一次验证码的返回包是336,下次验证码请求时336仍会出现在这里。所以只需要获取上一次验证码的值,然后拼接在这一次的值中可实现账号密码的爆破

  1. 语音轰炸

通过不断重放数据包或并发该数据包,从而实现语音轰炸

image

补充

并发轰炸:同时并发数据包,若存在限制,留意返回时间,采用单线程,调节间断时间,并发发包

存在检测:若网页存在检测无法抓包,可以换手机抓包进行绕过,接着将数据包发送给电脑进行测试

邮箱绕过:比如email=xxx@qq.com,当次数达到限制时,将字母修改为大写:email=XXX@Qq.com,即可绕过

思路拓展:任意盗刷别人银行卡

仅在绑卡时知道卡号,然后把手机号替换成自己的号码去接收验证码,再去绑定别人的卡,小额致富不需要知道银行卡密码,只需要自己设置的密码就行(参考vx支付的时候使用银行卡)

image

抓包替换手机号
1.银行卡=123456&手机号=123****4567
2.银行卡=123456&手机号=12345678910
抓包替换银行卡
1.银行卡=123456&手机号=123****4567
1.银行卡=789987&手机号=123****4567

拓展情境:

image

输入卡号后会显示预留的电话号码,让输入正确的电话号码后同意协议并验证,此时输入任意一个号码,会提示号码前三位和后四位,爆破中间的四位,成功后可让别人的银行卡绑定在自己的账号上面

JS-Ajax&前端逻辑&购物&登录&上传

  • JS前端验证-文件上传
  • JS-Ajax传递-登录-状态
  • JS-Ajax传递-购物-参数

TP框架&路由访问&安全写法&历史漏洞

  • 框架
    • ThinkPHP
    • Laravel
    • yii

ThinkPHP-URL访问形式与对应文件

首页会指向application/index/controller/Index.php

ThinkPHP5.0典型URL访问规则是

http://127.0.0.1/index.php(或者其他应用入口文件)/模块/控制器/操作/[参数名/
Struggle.php(.\application\index\controller)
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;

class Struggle extends Controller{
public function x(){
echo "成功访问Struggle!";
}
}
1.http://127.0.0.1/index.php/index/struggle/x
2.http://127.0.0.1/index.php?s=index/struggle/x
3.http://127.0.0.1/index.php/index/struggle/x.html(具体要看配置)
4.http://127.0.0.1/index.php?m=index&c=index&a=index(3.x的写法)
(MVC开发:m代表model,v代表view,c代表controller,a代表方法名)
---
成功访问Struggle!

Struggle.php(.\application\index\controller)
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;

class Struggle extends Controller{
public function x(){
echo "成功访问Struggle!";
}
public function y(){
//1
$x=$_GET['x'];
echo $x;
//2
$x=input('x');
echo $x;
}
}
1:http://127.0.0.1/index.php/index/struggle/y?x=1
2:http://127.0.0.1/index.php/index/struggle/y/x/1

application中创建yes文件夹,复制application的index中的public到yes

Love.php(.\application\yes\controller)
<?php
namespace app\yes\controller;
use think\Controller;
use think\Db;

class Love extends Controller{
public function x(){
echo "成功访问Struggle!";
}
public function xxx(){
$x=input('x');
echo $x;
}
}
http://127.0.0.1/index.php/yes/love/xxx?x=1
  • ThinkPHP5配置文件
.\application\config.php
.\application\database.php
.\thinkphp\tpl\base.php//看TP版本
  • 实例

AdminLTE后台管理系统

layui后台管理系统

thinkcmf

H-ui.admin后台管理系统

tpshop

FastAdmin

eyoucms

LarryCMS后台管理系统

tpadmin后台管理系统

snake后台管理系统

ThinkSNS

DolphinPHP后台管理系统

ThinkSNS

DolphinPHP后台管理系统

WeMall商城系统

CLTPHP

齐博CMS

DSMALL

YFCMF

HisiPHP后台管理系统

Tplay后台管理系统

lyadmin后台管理系统

haoid后台管理系统

用的框架找漏洞

  1. 看写法
  2. 看历史漏洞
github.com/Mochazz/ThinkPHP-Vuln
TP历史漏洞
坤舆-seebug-thinkphp
 评论
评论插件加载失败
正在加载评论插件