大家好,我是TheWeiJun;最近疫情很严重,大家都要做好防护。转眼间,距离上次发文又快一个月了。今天给大家带来一个Go语言版本的某容器管理平台模拟登录的案例,目的是解放双手,实现自动部署和重启操作,欢迎各位读者多多阅读与交流!
特别声明:本公众号文章只作为学术研究,不用于其它不法用途;如有侵权请联系作者删除。
目录
一、前言介绍
二、模拟登录
三、参数分析
四、代码实现
五、思路总结
趣味模块
老六是一名spider工程师,最近老六遇到了一个棘手的问题,老六每次写完代码上传git后,希望某容器管理平台能够自动同步git代码并且实现代码自动同步重启。老六一番研究后发现某容器平台除了代码宕机重启和定时重启,没有自动重启这么一说!老六很苦恼,后来老六想了想自己的职业,于是决定给他实现自动快速重启功能,彻底解放自己的双手,继续自己的复制粘贴高端操作!接下来,让我们一起去看看老六如何实现的自动登录和快速重启操作吧。
一、前言介绍
1. 什么是模拟登录?
解释:网页上以及app中输入账号密码的过程称为登录,不经过登录有些页面是无法直接跳转的。而模拟登录就是模拟手动输入账号密码的过程,获得登录成功后的cookie,以此cookie直接访问需要登录才能进入的页面,从而获取数据。
2. 模拟登录能做什么?
解释:模拟登录成功后,我们可以模拟人的行为下发一些操作指令,程序会根据我们下发的指令达到真实的人为效果,彻底解放我们的双手。
3. 什么是Cookie?
解释:cookies一种保存在电脑上的一种文件,当我们使用电脑进行浏览网页的时候,服务器就会生成一个证书,并且返回给我们的电脑,这个证书就是cookie,一般情况下,cookie是服务器写入客户端的文件,我们也可以叫浏览器缓存。
二、模拟登录
1、首先打开我们本次需要模拟登录的网站,浏览器中打开网页,截图如下所示:
2、点击账号密码,触发模拟登录操作,打开浏览器开发者工具查看相关请求包,截图如下所示:
环节说明:由于我们想要获取登录的协议接口,故我们随便输入内容,可查看到模拟登录所需要的data参数主要为上图六个。接下来,我们只需要模拟这几个参数并结合headers参数分析即可实现模拟登录!
3、一般网站开发人员为了安全,都会有csrf攻击防护,我们查看请求headers,截图如下所示:
总结:接下来我们只需要模拟data、headers参数即可实现模拟登录访问网站,达到我们最终的目的。
三、参数分析
1、参数初判断,需要我们模拟的参数主要有以下:
Data参数分析如下:
-
username:登录所需要的账号。
-
password:登录所需要的密码。
-
description:固定值,经过多次验证。
-
responseType:固定值,同上。
-
ttl:网站cookie过期时间,同redis过期时间类似。
-
labels:固定值,同上。
Headers参数分析如下:
-
x-api-csrf:登录所需要csrf参数。
-
Cookie:登录成功后需要保留的参数。
2、为了获取csrf参数,我们再次刷新页面,分析每一个可疑请求包,截图如下所示:
3、从前到后分析每一个请求包,我们发现csrf参数并不是通过response或者Set-Cookie的参数返回,这种情况很少见,于是我们模拟请求,查看响应体,果然有意外收获,截图如下所示:
总结:查看js代码后,我发现了问题关键,这个是由于通过浏览器访问时,js代码会将set-cookie给remove掉,这样对我们在分析该网站时,就会定位不到该参数如何下发的,从而放弃操作。那么接下来,我们用Golang去实现模拟登录,并下发操作重启代码服务吧。
四、代码实现
1、使用http包忽略证书认证,并提取登录所需的csrf参数,代码如下所示:
package main
import (
"crypto/tls"
"fmt"
"log"
"net/http"
)
func main() {
tr := &http.Transport{
// 处理x509: certificate signed by unknown authority
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
req, err := http.NewRequest("GET", "https://xxxx/v3/settings/ui-pl", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cookie", "R_USERNAME=")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "https://xxxx/login")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
req.Header.Set("x-api-action-links", "actionLinks")
req.Header.Set("x-api-no-challenge", "true")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
CsrfStr := resp.Header.Get("Set-Cookie")
fmt.Printf("%s\n", CsrfStr)
}
Goland中代码打印截图如下:
2、接下来我们使用上面获取的参数来完成模拟登录操作,完整代码如下:
package main
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"strings"
)
var tr = &http.Transport{
// 处理x509: certificate signed by unknown authority
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
var client = &http.Client{Transport: tr}
func GetCsrf() string {
req, err := http.NewRequest("GET", "https://xxxx/v3/settings/ui-pl", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cookie", "R_USERNAME=xxx")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "https://xxxx/login")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
req.Header.Set("x-api-action-links", "actionLinks")
req.Header.Set("x-api-no-challenge", "true")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
SetCookie := resp.Header.Get("Set-Cookie")
splitStr := strings.Split(SetCookie, ";")[0]
CsrfStr := strings.Replace(splitStr, "CSRF=", "", 1)
return CsrfStr
}
func Login(CsrfStr string) {
var data = strings.NewReader(`{"username":"xxxx","password":"xxxxx","description":"UI Session","responseType":"cookie","ttl":57600000,"labels":{"ui-session":"true"}}`)
req, err := http.NewRequest("POST", "https://xxxx/v3-public/localProviders/local?action=login", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Origin", "https://xxxx")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "https://xxxxx/login")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Cookie", "R_USERNAME=; CSRF="+CsrfStr)
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
req.Header.Set("x-api-action-links", "actionLinks")
req.Header.Set("x-api-csrf", CsrfStr)
req.Header.Set("x-api-no-challenge", "true")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
SetCookie := resp.Header.Get("Set-Cookie")
fmt.Println(SetCookie)
}
func main() {
CsrfStr := GetCsrf()
Login(CsrfStr)
}
Goland中打印登录后的token截图如下:
浏览器中登录后的token截图如下:
3、模拟登录流程实现后,我们开始下发重启代码操作,最后完整代码如下:
package main
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"strings"
)
var tr = &http.Transport{
// 处理x509: certificate signed by unknown authority
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
var client = &http.Client{Transport: tr}
func GetCsrf() string {
req, err := http.NewRequest("GET", "https://xxxx/v3/settings/ui-pl", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cookie", "R_USERNAME=xxx")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "https://xxxx/login")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
req.Header.Set("x-api-action-links", "actionLinks")
req.Header.Set("x-api-no-challenge", "true")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
SetCookie := resp.Header.Get("Set-Cookie")
splitStr := strings.Split(SetCookie, ";")[0]
CsrfStr := strings.Replace(splitStr, "CSRF=", "", 1)
return CsrfStr
}
func Login(CsrfStr string) {
var data = strings.NewReader(`{"username":"xxxx","password":"xxxxx","description":"UI Session","responseType":"cookie","ttl":57600000,"labels":{"ui-session":"true"}}`)
req, err := http.NewRequest("POST", "https://xxxx/v3-public/localProviders/local?action=login", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Origin", "https://xxxx")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "https://xxxxx/login")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Cookie", "R_USERNAME=weijun; CSRF="+CsrfStr)
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
req.Header.Set("x-api-action-links", "actionLinks")
req.Header.Set("x-api-csrf", CsrfStr)
req.Header.Set("x-api-no-challenge", "true")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
SetCookie := resp.Header.Get("Set-Cookie")
fmt.Println(SetCookie)
}
func Redeploy(token, CsrfStr string) {
req, err := http.NewRequest("POST", "https://xxxxx/v3/project/c-djhlx:p-vnncq/workloads/deployment:default:task5?action=redeploy", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Length", "0")
req.Header.Set("Cookie", "R_USERNAME=xxxx; CSRF="+CsrfStr+"; "+token)
req.Header.Set("Origin", "https://xxxx")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "xxxx")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
req.Header.Set("x-api-action-links", "actionLinks")
req.Header.Set("x-api-csrf", CsrfStr)
req.Header.Set("x-api-no-challenge", "true")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
Options := resp.Header.Get("X-Content-Type-Options")
if Options != "" {
fmt.Println("Redeploy successful!")
}
}
func main() {
CsrfStr := GetCsrf()
token := Login(CsrfStr)
Redeploy(token, CsrfStr)
}
代码运行后,Goland运行截图如下所示:
代码执行完毕后,浏览器中服务状态截图如下:
总结:对比上面两张截图,我们发现我们的代码已经能够重启指定的woker服务了,这样就实现了我们想要的自动化重启功能,整个流程到此就完全结束了!
五、思路总结
通过本次案例分析,我们不仅可以通过Python实现模拟登录,也可以用Go去实现模拟登录。本篇分享到这里就结束了,欢迎大家关注下一期,我们不见不散☀️☀️😊。最后希望大家多多转发、点赞、在看支持一波
关注我们获得更多精彩内容
逆向与爬虫的故事
不止于爬虫开发,还有Js逆向、App逆向!
往期推荐
革新之路:重新设计Scrapy调度器,让爬虫速度翻倍
猿人学逆向比赛第四题-gRPC题解 | Go版本
DX滑块验证码别乱捅!一不小心就反爬了。
某安网别逆向,一不小心就......
微信自动聊天机器狗,配置chatGPT,比Siri还智能!
被魔改md5加密坑了?某网站魔改md5加密逆向还原 (多种语言还原)
作者简介
我是TheWeiJun,有着执着的追求,信奉终身成长,不定义自己,热爱技术但不拘泥于技术,爱好分享,喜欢读书和乐于结交朋友,欢迎扫我微信与我交朋友💕
分享日常学习中关于爬虫及逆向分析的一些思路,文中若有错误的地方,欢迎大家多多交流指正💕
文章来源:逆向与爬虫的故事
原文链接:某容器管理平台模拟登录(Go语言版本)
微信搜公众号:逆向与爬虫的故事;给我一个关注!