事很短,处理也简单。权当记录一下,各位安全大大们手下留情。
最近一位客户遇到官网被劫持的情况,想我们帮忙解决一下(本来不关我们的事,毕竟情面在这...还是无偿地协助一下),经过三四轮“谦让”最终这个任务还是落到了我这个不精通安全的人的头上()。
客户说通过百度跳转官网,首页加载到一半时发生另一次跳转,跳到一个“赌球”网站去(欧洲杯最近大热),但直接输入域名就不会发生跳转。
我初步尝试了一下,除了 PC 端有这种情况外,移动端也会触发这种跳转...首先不要被现象迷惑,从首页能够加载到一半的情况可知,这种恶意跳转应该是通过代码触发的。
因为如果是在网络层面又或者 Http Server 转发,根本就不会让官网首页出现,因此排查的方向应聚焦到代码层面。
其次,通过百度访问会触发恶意跳转,但域名访问不会。这不禁让我想到对方有可能是通过 Header 中的 Referer 进行来源判断。于是我尝试使用 bing 搜索引擎对官网进行访问,结果证实了我的想法,在 bing 访问是不会发生跳转的。
好了,既然是通过代码跳转的,那么它总要发生请求吧。究竟是从哪发生的请求呢?
为了防止跳转过快的情况,先在百度页面中复制一个链接,打开一个新的窗口并且打开开发者模式,再将链接复制到浏览器进行访问。如下图:
这时候就能够将首次访问的所有请求获取到,并且在准备发生自动跳转之前你有足够的时间来取消页面请求,就能够得到上图的输出。通过上图的网络输出可知,其他都是正常的官网请求,唯独 data.joysoo.xyz 是一个不知来路的域名。而且请求的 JavaScript 文件也足够可疑,连名字都是经过加密的样子。
嗯...在截获了当前的信息后,让其跳转看看还有什么网络输出,如下图:
噢,这个网站也尝试加载 data.joysoo.xyz 的 DL1iBa6yb(这里与官网的 JavaScript 已经不一样了)。至此,从信息层面能够通过 data.joysoo.xyz 域名可以将两个网站的关联串联起来了,那么接下来就可通过这个域名进行代码搜索。
将客户网站的 PHP 代码放入 VSCode 中进行全局搜索。如下图:
这个域名恰巧只有一个 php 文件匹配成功。从这里也可以看出为什么无论从哪个页面跳转都会进行恶意跳转,因为这个脚本是直接植入到页面的 ICP banner 模块中的,而由于 ICP banner 每个页面都内嵌的,因此无论哪个页面都会发生跳转。
那么这个脚本是从哪里植入的呢?
从上图可知,在 log 文件中也找到两条与这个域名相关的记录,如下图:
呃...这里有一条 update 语句将这个脚本写入到数据库里面,估计是被 SQL注入了吧。
至此,整个解决思路也形成了。由于当前的 PHP 框架会在网页访问时自动生成新的页面,因此只需要重新更新数据库内容即可恢复。但是,这样也只是治标不治本,最最重要的还是加强对云服务器以及应用的防护才是重中之重,不然问题还是会重新出现。
菜鸟入门,各位大佬轻喷,如有谬误之处欢迎讨论建议,也欢迎各位道友与我同行
"不积跬步,无以至千里;不积小流,无以成江海"
续接上篇文章,我们实现了一个简单的登陆界面,但是我们的表单提示,例如用户名等,是用的文字在按钮上方提示的
那我们如何去实现一个提示框用于提示呢?然后再自动聚焦到输入框中呢?
// 是否显示弹窗的标识
@State private var showAlert:Bool=false;
// 在登陆按钮之后放置弹窗
Button("登陆"){
// 切换要显示Alert
showAlert.toggle();
// 省略一部分操作。。。
}.alert(isPresented: $showAlert){ // 这里 isPresented 绑定 showAlert变量
Alert(
title: Text("提示"), // 顶部的标题
message: Text(res), // 弹窗的内容,需要是一个Text,调用了我们之前定义的提示文本
primaryButton: .default(Text("取消")){// 第一个按钮是默认类型样式,显示取消
// 第一个按钮点击后的操作
},
secondaryButton: .destructive(Text("确定")){
}
)
}
以上的代码运行后得到如下结果
在这里插入图片描述
以上的弹出框提示已经解决,那么接下来需要实现的是弹出之后哪一个字段没填,就让它自动聚焦,让用户可以直接填写那个字段 添加如下的代码
// 是否聚焦到用户名字段,注意@符号后面跟的是 FocusState,不然用到focused里面会报错,并且不能设置默认值
@FocusState private var focusUser:Bool;
HStack{
Text("用户名")
Spacer()
TextField("请输入用户名",text:$userName)
.multilineTextAlignment(.center)
// 给用户名字段的 focused 绑定 focusUser 变量
.focused($focusUser)
}.padding(.all)
}
/// ... 省略部分代码
Button("登陆"){
// 切换要显示Alert
showAlert.toggle();
if(userName==""){
// 如果没填 userName 那么切换 focusUser 的值
focusUser.toggle()
}
// 省略一部分操作。。。
}
// 。。。 省略Alert部分
此处的代码实现了,如果在点击登陆按钮后用户名没有填,自动聚焦到用户名字段
在本页面中,共有三个字段,可以定义三个变量的形式来进行判定聚焦
但是如果有很多个字段的话就不合适了,我们可以使用枚举的方式来进行定义
以下贴出本页面完整的代码
import SwiftUI
struct ContentView: View {
// 用户名
@State private var userName:String="";
// 密码
@State private var passWord:String="";
// 验证码
@State private var code:String="";
// 提示语
@State private var res:String="请输入。。。";
// 提示语的颜色,color类型
@State private var color:Color=.red;
// 是否显示弹窗标识
@State private var showAlert:Bool=false;
// 聚焦到哪一个字段?
@FocusState private var focus:FocusField?;
// 定义一个 Hashable 的枚举,因为 focused 的第二个参数需要一个hashable的参数
enum FocusField:Hashable{
case name;
case password;
case code;
case clear;
};
var body: some View {
// 整体纵向布局
VStack {
// 页面标题,加粗,标题字体
Text("登陆界面").fontWeight(.bold).font(.title)
// 分隔占位,有点类似html中flex的flex:1,具体怎么用之后再看
Spacer()
// 一个横向布局,表单项名称-分隔占位-以及表单项
// 给一个 .all 的 padding,不然不好看
HStack{
Text("用户名")
Spacer()
TextField("请输入用户名",text:$userName)
.multilineTextAlignment(.center)
// focused 绑定 focus变量,当该变量为 .name 时
.focused($focus,equals: .name)
}.padding(.all)
HStack{
Text("密码")
Spacer()
// secure field 跟 TextField基本类似,只是隐藏输入的内容
SecureField("请输入密码",text:$passWord)
.multilineTextAlignment(.center)
.focused($focus, equals: .password)
}.padding(.all)
HStack{
Text("验证码")
Spacer()
TextField("请输入验证码",text:$code)
.multilineTextAlignment(.center)
.focused($focus, equals: .code)
}.padding(.all)
Spacer()
// 提示语和button在一起
Text(res).foregroundColor(color)
Button("登陆"){
showAlert.toggle();
color=.red
// button 的点击事件action,做一个简单的判断
// 修改 res 的名称,以及res的颜色
if(userName==""){
res="请输入用户名!";
return ;
}
if(passWord==""){
res="请输入密码!"
return ;
}
if(code==""){
res="请输入验证码";
return ;
}
color=.green;
res="登陆成功"
// 清空表单数据
userName="";
passWord="";
code="";
}.buttonStyle(.bordered)
.alert(isPresented: $showAlert){
Alert(
title: Text("提示"),
message: Text(res),
primaryButton: .default(Text("取消")),
secondaryButton: .destructive(Text("确定")){
if(res=="请输入用户名!"){
// 没有用户名
focus=.name
}
if(res=="请输入密码!"){
focus=.password
}
if(res=="请输入验证码!"){
focus=.code
}
if(res=="登陆成功" || res=="请输入。。。"){
focus=.clear
}
}
)
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
运行得到以下的结果
在这里插入图片描述
HTML 的 tabindex 属性开发过程中一般不会使用到,最近开发中有个需求兼顾富交互,便总结了一下。本篇文章同时收录在我的【前端知识点】中,Github链接请点击阅读原文直达,欢迎 Star
兼容性:Safari不支持!
在我们日常使用网页的过程中,可以通过键盘控制一些元素的聚焦,从而达到便捷访问的目的
element 分为 focusable 和 非focusable ,如果使用了tabindex就可以改变相关的行为
在HTML中有6个元素默认支持聚焦:
以上的元素默认都可以使用 Tab 键,以及 JS focus() 方法聚焦
document.querySelector("a").focus();
使用 tab键 进行聚焦元素时,聚焦的顺序等于元素在代码中的出现先后顺序,当我们进行富交互优化时,就需要用到 tabindex 这个属性来帮助我们进行更好用户体验的优化了
①元素是否能聚焦:通过键盘这类输入设备,或者通过 JS focus() 方法
②元素什么时候能聚焦:在用户通过键盘与页面交互时
通俗来说:就是当用户使用键盘时,tabindex用来定位html元素,即使用tab键时焦点的顺序。
tabindex理论上可以使用在几乎所有元素上
tabindex 有三个值:0,-N(通常是-1),N(正值)
tabindex 决定聚焦顺序
// HTML
<button type="button" tabindex="1">tabindex === 1</button>
<button type="button" tabindex="999">tabindex === 999</button>
<button type="button" tabindex="0">tabindex === 0</button>
// HTML
<button type="button" tabindex="0">tabindex === 0</button>
<button type="button" tabindex="1">tabindex === 1</button>
<button type="button" tabindex="999">tabindex === 999</button>
<button type="button" tabindex="0">tabindex === 0</button>
tabindex 决定是否聚焦
// HTML
<button type="button">未设置tabindex</button>
<button type="button" tabindex="-1">tabindex === -1</button>
<button type="button" tabindex="0">tabindex === 0</button>
<button type="button" tabindex="1">tabindex === 1</button>
tabindex 与JS编程聚焦
// HTML
<button type="button" @click="clickBtn()">点击让DIV聚焦</button>
<div id="FocusDiv" ref="FocusDiv" tabindex="-1">这是一个div</div>
// JS
clickBtn: function() {
document.getElementById('FocusDiv').focus();
}
针对自定义标签进行富交互优化
针对特定节点禁止聚焦操作
复杂列表控制聚焦顺序
*请认真填写需求信息,我们会在24小时内与您取得联系。