Python中使用socket发送HTTP

发布时间:May 2, 2015 // 分类:工作日志,代码学习,python // No Comments

由于工作的需求,需要用python做一个类似网络爬虫的采集器。虽然Python的urllib模块提供更加方便简洁操作,但是涉及到一些底层的需求,如手动设定User-Agent,Referer等,所以选择了直接用socket进行设计。当然,这样的话,需要对HTTP协议比较熟悉,HTTP协议这里就不做讲解了。整个python的代码如下:

#!/usr/bin env python
import socket
host="0cx.cc"
se=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
se.connect((host,80))
se.send("GET / HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\nHost: %s\r\n\r\n" % host)
print se.recv(1024)

可是我们得到的返回结果是这样的

HTTP/1.1 200 OK
Date: Sat, 02 May 2015 07:54:08 GMT
Server: Apache/2.2.15 (CentOS)
X-Pingback: http://0cx.cc/action/xmlrpc
Vary: Accept-Encoding
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

426c
<!DOCTYPE h

代码运行正常,但是发现一个比较重要的问题,运行结果只返回了HTTP的头部信息,网页的内容则没有被返回。网上查找了很多资料,一无所获,经过一夜的思考,突然想到了一个问题,有可能我请求的资源非常大,一个网络的IP包的大小,它是受很多因素制约的,最典型的便是MTU(最大传输单元),那么会不会我请求的数据被分割了,HTTP的头部信息只是一部分,其它数据还在传输或者缓冲区呢?于是做了这样一个遍历:

#!/usr/bin env python
import socket
host="0cx.cc"
se=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
se.connect((host,80))
se.send("GET / HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\nHost: %s\r\n\r\n" % host)
while True:
  result = se.recv(1024)
  if not len(result ):
    break
  print result

查看返回的结果,果然正常了。看来要想做好网络编程,深入理解TCP/IP协议是非常必要的。利用这个还可以探测某域名是否在某IP段内

一句一句解说 iptables的详细中文手册

发布时间:May 2, 2015 // 分类:工作日志,运维工作,linux,转帖文章 // No Comments

总览 
用iptables -ADC 来指定链的规则,-A添加 -D删除 -C 修改
iptables - [RI] chain rule num rule-specification[option] 
用iptables - RI 通过规则的顺序指定
iptables -D chain rule num[option] 
删除指定规则 
iptables -[LFZ] [chain][option] 
用iptables -LFZ 链名 [选项]
iptables -[NX] chain 
用 -NX 指定链
iptables -P chain target[options] 
指定链的默认目标
iptables -E old-chain-name new-chain-name 
-E 旧的链名 新的链名 
用新的链名取代旧的链名 
说明 
Iptalbes 是用来设置、维护和检查Linux内核的IP包过滤规则的。 
可以定义不同的表,每个表都包含几个内部的链,也能包含用户定义的链。每个链都是一个规则列表,对对应的包进行匹配:每条规则指定应当如何处理与之相匹配的包。这被称作'target'(目标),也可以跳向同一个表内的用户定义的链。
TARGETS 
防火墙的规则指定所检查包的特征,和目标。如果包不匹配,将送往该链中下一条规则检查;如果匹配,那么下一条规则由目标值确定.该目标值可以是用户定义的链名,或是某个专用值,如ACCEPT[通过], DROP[删除], QUEUE[排队], 或者 RETURN[返回]。 
ACCEPT 表示让这个包通过。DROP表示将这个包丢弃。QUEUE表示把这个包传递到用户空间。RETURN表示停止这条链的匹配,到前一个链的规则重新开始。如果到达了一个内建的链(的末端),或者遇到内建链的规则是RETURN,包的命运将由链准则指定的目标决定。
TABLES 
当前有三个表(哪个表是当前表取决于内核配置选项和当前模块)。 
-t table 
这个选项指定命令要操作的匹配包的表。如果内核被配置为自动加载模块,这时若模块没有加载,(系统)将尝试(为该表)加载适合的模块。这些表如下:filter,这是默认的表,包含了内建的链INPUT(处理进入的包)、FORWORD(处理通过的包)和OUTPUT(处理本地生成的包)。nat,这个表被查询时表示遇到了产生新的连接的包,由三个内建的链构成:PREROUTING (修改到来的包)、OUTPUT(修改路由之前本地的包)、POSTROUTING(修改准备出去的包)。mangle 这个表用来对指定的包进行修改。它有两个内建规则:PREROUTING(修改路由之前进入的包)和OUTPUT(修改路由之前本地的包)。 
OPTIONS 
这些可被iptables识别的选项可以区分不同的种类。
COMMANDS 
这些选项指定执行明确的动作:若指令行下没有其他规定,该行只能指定一个选项.对于长格式的命令和选项名,所用字母长度只要保证iptables能从其他选项中区分出该指令就行了。 
-A -append 
在所选择的链末添加一条或更多规则。当源(地址)或者/与目的(地址)转换为多个地址时,这条规则会加到所有可能的地址(组合)后面。
-D -delete 
从所选链中删除一条或更多规则。这条命令可以有两种方法:可以把被删除规则指定为链中的序号(第一条序号为1),或者指定为要匹配的规则。
-R -replace 
从选中的链中取代一条规则。如果源(地址)或者/与目的(地址)被转换为多地址,该命令会失败。规则序号从1开始。
-I -insert 
根据给出的规则序号向所选链中插入一条或更多规则。所以,如果规则序号为1,规则会被插入链的头部。这也是不指定规则序号时的默认方式。
-L -list 
显示所选链的所有规则。如果没有选择链,所有链将被显示。也可以和z选项一起使用,这时链会被自动列出和归零。精确输出受其它所给参数影响。
-F -flush 
清空所选链。这等于把所有规则一个个的删除。
--Z -zero 
把所有链的包及字节的计数器清空。它可以和 -L配合使用,在清空前察看计数器,请参见前文。
-N -new-chain 
根据给出的名称建立一个新的用户定义链。这必须保证没有同名的链存在。
-X -delete-chain 
删除指定的用户自定义链。这个链必须没有被引用,如果被引用,在删除之前你必须删除或者替换与之有关的规则。如果没有给出参数,这条命令将试着删除每个非内建的链。 
-P -policy 
设置链的目标规则。
-E -rename-chain 
根据用户给出的名字对指定链进行重命名,这仅仅是修饰,对整个表的结构没有影响。TARGETS参数给出一个合法的目标。只有非用户自定义链可以使用规则,而且内建链和用户自定义链都不能是规则的目标。
-h Help. 
帮助。给出当前命令语法非常简短的说明。
PARAMETERS 
参数 
以下参数构成规则详述,如用于add、delete、replace、append 和 check命令。
-p -protocal [!]protocol 
规则或者包检查(待检查包)的协议。指定协议可以是tcp、udp、icmp中的一个或者全部,也可以是数值,代表这些协议中的某一个。当然也可以使用在/etc/protocols中定义的协议名。在协议名前加上"!"表示相反的规则。数字0相当于所有all。Protocol all会匹配所有协议,而且这是缺省时的选项。在和check命令结合时,all可以不被使用。 
-s -source [!] address[/mask] 
指定源地址,可以是主机名、网络名和清楚的IP地址。mask说明可以是网络掩码或清楚的数字,在网络掩码的左边指定网络掩码左边"1"的个数,因此,mask值为24等于255.255.255.0。在指定地址前加上"!"说明指定了相反的地址段。标志 --src 是这个选项的简写。
-d --destination [!] address[/mask] 
指定目标地址,要获取详细说明请参见 -s标志的说明。标志 --dst 是这个选项的简写。
-j --jump target 
-j 目标跳转 
指定规则的目标;也就是说,如果包匹配应当做什么。目标可以是用户自定义链(不是这条规则所在的),某个会立即决定包的命运的专用内建目标,或者一个扩展(参见下面的EXTENSIONS)。如果规则的这个选项被忽略,那么匹配的过程不会对包产生影响,不过规则的计数器会增加。
-i -in-interface [!] [name] 
i -进入的(网络)接口 [!][名称] 
这是包经由该接口接收的可选的入口名称,包通过该接口接收(在链INPUT、FORWORD和PREROUTING中进入的包)。当在接口名前使用"!"说明后,指的是相反的名称。如果接口名后面加上"+",则所有以此接口名开头的接口都会被匹配。如果这个选项被忽略,会假设为"+",那么将匹配任意接口。
-o --out-interface [!][name] 
-o --输出接口[名称] 
这是包经由该接口送出的可选的出口名称,包通过该口输出(在链FORWARD、OUTPUT和POSTROUTING中送出的包)。当在接口名前使用"!"说明后,指的是相反的名称。如果接口名后面加上"+",则所有以此接口名开头的接口都会被匹配。如果这个选项被忽略,会假设为"+",那么将匹配所有任意接口。
[!] -f, --fragment 
[!] -f --分片 
这意味着在分片的包中,规则只询问第二及以后的片。自那以后由于无法判断这种把包的源端口或目标端口(或者是ICMP类型的),这类包将不能匹配任何指定对他们进行匹配的规则。如果"!"说明用在了"-f"标志之前,表示相反的意思。
OTHER OPTIONS 
其他选项 
还可以指定下列附加选项:
-v --verbose 
-v --详细 
详细输出。这个选项让list命令显示接口地址、规则选项(如果有)和TOS(Type of Service)掩码。包和字节计数器也将被显示,分别用K、M、G(前缀)表示1000、1,000,000和1,000,000,000倍(不过请参看-x标志改变它),对于添加,插入,删除和替换命令,这会使一个或多个规则的相关详细信息被打印。
-n --numeric 
-n --数字 
数字输出。IP地址和端口会以数字的形式打印。默认情况下,程序试显示主机名、网络名或者服务(只要可用)。
-x -exact 
-x -精确 
扩展数字。显示包和字节计数器的精确值,代替用K,M,G表示的约数。这个选项仅能用于 -L 命令。
--line-numbers 
当列表显示规则时,在每个规则的前面加上行号,与该规则在链中的位置相对应。
MATCH EXTENSIONS 
对应的扩展 
iptables能够使用一些与模块匹配的扩展包。以下就是含于基本包内的扩展包,而且他们大多数都可以通过在前面加上!来表示相反的意思。
tcp 
当 --protocol tcp 被指定,且其他匹配的扩展未被指定时,这些扩展被装载。它提供以下选项:
--source-port [!] [port[:port]] 
源端口或端口范围指定。这可以是服务名或端口号。使用格式端口:端口也可以指定包含的(端口)范围。如果首端口号被忽略,默认是"0",如果末端口号被忽略,默认是"65535",如果第二个端口号大于第一个,那么它们会被交换。这个选项可以使用 --sport的别名。
--destionation-port [!] [port:[port]] 
目标端口或端口范围指定。这个选项可以使用 --dport别名来代替。
--tcp-flags [!] mask comp 
匹配指定的TCP标记。第一个参数是我们要检查的标记,一个用逗号分开的列表,第二个参数是用逗号分开的标记表,是必须被设置的。标记如下:SYN ACK FIN RST URG PSH ALL NONE。因此这条命令:iptables -A FORWARD -p tcp --tcp-flags SYN, ACK, FIN, RST SYN只匹配那些SYN标记被设置而ACK、FIN和RST标记没有设置的包。
[!] --syn 
只匹配那些设置了SYN位而清除了ACK和FIN位的TCP包。这些包用于TCP连接初始化时发出请求;例如,大量的这种包进入一个接口发生堵塞时会阻止进入的TCP连接,而出去的TCP连接不会受到影响。这等于 --tcp-flags SYN, RST, ACK SYN。如果"--syn"前面有"!"标记,表示相反的意思。
--tcp-option [!] number 
匹配设置了TCP选项的。
udp 
当protocol udp 被指定,且其他匹配的扩展未被指定时,这些扩展被装载,它提供以下选项:
--source-port [!] [port:[port]] 
源端口或端口范围指定。详见 TCP扩展的--source-port选项说明。
--destination-port [!] [port:[port]] 
目标端口或端口范围指定。详见 TCP扩展的--destination-port选项说明。
icmp 
当protocol icmp被指定,且其他匹配的扩展未被指定时,该扩展被装载。它提供以下选项: 
--icmp-type [!] typename 
这个选项允许指定ICMP类型,可以是一个数值型的ICMP类型,或者是某个由命令iptables -p icmp -h所显示的ICMP类型名。
mac 
--mac-source [!] address 
匹配物理地址。必须是XX:XX:XX:XX:XX这样的格式。注意它只对来自以太设备并进入PREROUTING、FORWORD和INPUT链的包有效。
limit 
这个模块匹配标志用一个标记桶过滤器一一定速度进行匹配,它和LOG目标结合使用来给出有限的登陆数.当达到这个极限值时,使用这个扩展包的规则将进行匹配.(除非使用了"!"标记)
--limit rate 
最大平均匹配速率:可赋的值有'/second', '/minute', '/hour', or '/day'这样的单位,默认是3/hour。
--limit-burst number 
待匹配包初始个数的最大值:若前面指定的极限还没达到这个数值,则概数字加1.默认值为5
multiport 
这个模块匹配一组源端口或目标端口,最多可以指定15个端口。只能和-p tcp 或者 -p udp 连着使用。
--source-port [port[, port]] 
如果源端口是其中一个给定端口则匹配
--destination-port [port[, port]] 
如果目标端口是其中一个给定端口则匹配
--port [port[, port]] 
若源端口和目的端口相等并与某个给定端口相等,则匹配。 
mark 
这个模块和与netfilter过滤器标记字段匹配(就可以在下面设置为使用MARK标记)。
--mark value [/mask] 
匹配那些无符号标记值的包(如果指定mask,在比较之前会给掩码加上逻辑的标记)。
owner 
此模块试为本地生成包匹配包创建者的不同特征。只能用于OUTPUT链,而且即使这样一些包(如ICMP ping应答)还可能没有所有者,因此永远不会匹配。
--uid-owner userid 
如果给出有效的user id,那么匹配它的进程产生的包。
--gid-owner groupid 
如果给出有效的group id,那么匹配它的进程产生的包。
--sid-owner seessionid 
根据给出的会话组匹配该进程产生的包。
state 
此模块,当与连接跟踪结合使用时,允许访问包的连接跟踪状态。
--state state 
这里state是一个逗号分割的匹配连接状态列表。可能的状态是:INVALID表示包是未知连接,ESTABLISHED表示是双向传送的连接,NEW表示包为新的连接,否则是非双向传送的,而RELATED表示包由新连接开始,但是和一个已存在的连接在一起,如FTP数据传送,或者一个ICMP错误。
unclean 
此模块没有可选项,不过它试着匹配那些奇怪的、不常见的包。处在实验中。
tos 
此模块匹配IP包首部的8位tos(服务类型)字段(也就是说,包含在优先位中)。
--tos tos 
这个参数可以是一个标准名称,(用iptables -m tos -h 察看该列表),或者数值。
TARGET EXTENSIONS 
iptables可以使用扩展目标模块:以下都包含在标准版中。
LOG 
为匹配的包开启内核记录。当在规则中设置了这一选项后,linux内核会通过printk()打印一些关于全部匹配包的信息(诸如IP包头字段等)。 
--log-level level 
记录级别(数字或参看 syslog.conf(5))。 
--log-prefix prefix 
在纪录信息前加上特定的前缀:最多14个字母长,用来和记录中其他信息区别。
--log-tcp-sequence 
记录TCP序列号。如果记录能被用户读取那么这将存在安全隐患。
--log-tcp-options 
记录来自TCP包头部的选项。 
--log-ip-options 
记录来自IP包头部的选项。
MARK 
用来设置包的netfilter标记值。只适用于mangle表。
--set-mark mark
REJECT 
作为对匹配的包的响应,返回一个错误的包:其他情况下和DROP相同。
此目标只适用于INPUT、FORWARD和OUTPUT链,和调用这些链的用户自定义链。这几个选项控制返回的错误包的特性:
--reject-with type 
Type可以是icmp-net-unreachable、icmp-host-unreachable、icmp-port-nreachable、icmp-proto-unreachable、 icmp-net-prohibited 或者 icmp-host-prohibited,该类型会返回相应的ICMP错误信息(默认是port-unreachable)。选项 echo-reply也是允许的;它只能用于指定ICMP ping包的规则中,生成ping的回应。最后,选项tcp-reset可以用于在INPUT链中,或自INPUT链调用的规则,只匹配TCP协议:将回应一个TCP RST包。 
TOS 
用来设置IP包的首部八位tos。只能用于mangle表。
--set-tos tos 
你可以使用一个数值型的TOS 值,或者用iptables -j TOS -h 来查看有效TOS名列表。 
MIRROR 
这是一个试验示范目标,可用于转换IP首部字段中的源地址和目标地址,再传送该包,并只适用于INPUT、FORWARD和OUTPUT链,以及只调用它们的用户自定义链。
SNAT 
这个目标只适用于nat表的POSTROUTING链。它规定修改包的源地址(此连接以后所有的包都会被影响),停止对规则的检查,它包含选项:
--to-source [-][:port-port] 
可以指定一个单一的新的IP地址,一个IP地址范围,也可以附加一个端口范围(只能在指定-p tcp 或者-p udp的规则里)。如果未指定端口范围,源端口中512以下的(端口)会被安置为其他的512以下的端口;512到1024之间的端口会被安置为1024以下的,其他端口会被安置为1024或以上。如果可能,端口不会被修改。
--to-destiontion [-][:port-port] 
可以指定一个单一的新的IP地址,一个IP地址范围,也可以附加一个端口范围(只能在指定-p tcp 或者-p udp的规则里)。如果未指定端口范围,目标端口不会被修改。
MASQUERADE 
只用于nat表的POSTROUTING链。只能用于动态获取IP(拨号)连接:如果你拥有静态IP地址,你要用SNAT。伪装相当于给包发出时所经过接口的IP地址设置一个映像,当接口关闭连接会终止。这是因为当下一次拨号时未必是相同的接口地址(以后所有建立的连接都将关闭)。它有一个选项:
--to-ports [-port>] 
指定使用的源端口范围,覆盖默认的SNAT源地址选择(见上面)。这个选项只适用于指定了-p tcp或者-p udp的规则。
REDIRECT 
只适用于nat表的PREROUTING和OUTPUT链,和只调用它们的用户自定义链。它修改包的目标IP地址来发送包到机器自身(本地生成的包被安置为地址127.0.0.1)。它包含一个选项:
--to-ports [] 
指定使用的目的端口或端口范围:不指定的话,目标端口不会被修改。只能用于指定了-p tcp 或 -p udp的规则。
DIAGNOSTICS 
诊断 
不同的错误信息会打印成标准错误:退出代码0表示正确。类似于不对的或者滥用的命令行参数错误会返回错误代码2,其他错误返回代码为1。
BUGS 
臭虫 
Check is not implemented (yet). 
检查还未完成。
COMPATIBILITY WITH IPCHAINS 
与ipchains的兼容性 
iptables和Rusty Russell的ipchains非常相似。主要区别是INPUT 链只用于进入本地主机的包,而OUTPUT只用于自本地主机生成的包。因此每个包只经过三个链的一个;以前转发的包会经过所有三个链。其他主要区别是 -i 引用进入接口;-o引用输出接口,两者都适用于进入FORWARD链的包。当和可选扩展模块一起使用默认过滤器表时,iptables是一个纯粹的包过滤器。这能大大减少以前对IP伪装和包过滤结合使用的混淆,所以以下选项作了不同的处理: 
-j MASQ 
-M -S 
-M -L 
在iptables中有几个不同的链。
SEE ALSO 
参见 
iptables-HOWTO有详细的iptables用法,对netfilter-hacking-HOWTO也有详细的本质说明。

利用WMI代替psexec——WMIEXEC.vbs

发布时间:May 1, 2015 // 分类:转帖文章,windows // No Comments

0x01 背景

内网渗透中经常用到psexec这个工具,可以很方便的得到一个半交互式的cmd shell。

但是psexec也有一些问题:psexec需要对方开启ADMIN$共享,而且需要安装服务;另外,psexec退出时有可能服务删除失败,这个情况只是偶尔,但是我碰到过。

安装服务会留下明显的日志,而且服务没有删除的风险更大,管理员很容易就会发现。

WMI可以远程执行命令,所以我就想用VBS脚本调用WMI来模拟psexec的功能,于是乎WMIEXEC就诞生了。基本上psexec能用的地方,这个脚本也能够使用。

0x02 WMIEXEC功能

利用WMI代替psexec——WMIEXEC.vbs

WMIEXEC支持两种模式,一种是半交互式shell模式,另一种是执行单条命令模式。

WMIEXEC需要提供账号密码进行远程连接,但是如果没有破解出账号密码,也可以配合WCE的hash注入功能一起使用,先进行hash注入,然后再使用WMIEXEC即可。

半交互式shell模式

提供账号密码,执行如下命令:

cscript.exe //nologo wmiexec.vbs /shell 192.168.1.1 username password

利用WMI代替psexec——WMIEXEC.vbs

这样就获得了一个半交互式的shell,这个shell和psexec的shell没什么区别。之所以称为半交互式,是因为这个shell也不能执行实时交互的命令,和psexec是一样的。

上个执行命令的图:

利用WMI代替psexec——WMIEXEC.vbs

左边是虚拟机里面执行的命令,右边是WMIEXEC里面执行的。

还可以抓取hash:

利用WMI代替psexec——WMIEXEC.vbs

单个命令执行的模式

这个模式适用于只需要执行一个命令,或者说当前的环境不是交互式shell,没法运行WMIEXEC的shell模式时(比如在webshell里面)。

  cscript.exe wmiexec.vbs /cmd 192.168.1.1 username password "command"

利用WMI代替psexec——WMIEXEC.vbs

上面是提供账号密码的情况,如果有时候我们抓取到的是hash,破解不了时可以利用WCE的hash注入,然后再执行WMIEXEC(不提供账号密码)就可以了。

利用WMI代替psexec——WMIEXEC.vbs

Tips:

如果抓取的LM hash是AAD3开头的,或者是No Password之类的,就用32个0代替LM hash即可。

0x03 原理和相关问题

整个过程是先调用WMI通过账号密码或者NTLM认证(WCE注入)连接到远程计算机,然后如果提供了账号密码,则用这个账号密码建立一个到目标的IPC连接。随后WMI会建立一个共享文件夹,用于远程读取命令执行结果。

当用户输入命令时,WMI创建进程执行该命令,然后把结果输出到文件,这个文件位于之前创建的共享文件夹中。最后,通过FSO组件访问远程共享文件夹中的结果文件,将结果输出。当结果读取完成时,调用WMI执行命令删除结果文件。最后当WMIEXEC退出时,删除文件共享。

由于WMI只负责创建进程,没有办法可以判断命令是否执行完毕,所以脚本采用的方法是延迟1200ms后读取结果文件,但是如果命令执行的时间大于1200ms,比如systeminfo 或者ping之类的,这时候读取结果文件会导致读取的结果不完整,然后在删除结果文件时会出错。

比如正常的执行ping:

利用WMI代替psexec——WMIEXEC.vbs

Ping结果没有读取完整,而且命令执行完后目标服务器上的wmi.dll结果文件并没有被删除

为了防止出现这种情况,于是在shell模式里面加入了-waitTIME选项,TIME是要等待的时间。当执行的命令后面跟上-wait5000时,表示这个命令等待5s后再读取结果.

利用WMI代替psexec——WMIEXEC.vbs

由于正常的命令都要查看结果,所以执行的命令后面都会加上重定向符,把结果输出到文件中。

所以用这个执行木马会有问题,因为木马进程会一直存在,导致结果文件被占用,不能删除,也不能改写,如果执行不带任何参数的nc.exe也是这种效果

出现这种情况后由于结果文件被占用,所以WMIEXEC不能工作,除非手动更改脚本中的结果文件名。或者可以用taskkill 远程结束掉卡死的进程,然后WMIEXEC可以恢复工作。

为了解决这个问题,加入了-persist选项。

当命令加了persist选项后,程序会在后台运行,不会有结果输出,而且会返回这个命令进程的PID,方便结束进程。

这样就可以运行nc或者木马程序了。

下面是测试nc的结果:

利用WMI代替psexec——WMIEXEC.vbs

相关设定:

Const Path = "C:\"

Const FileName = "wmi.dll"

Const timeOut = 1200

这段代码在脚本的一开始,是控制结果文件路径、文件名、以及默认代码执行时间的,可以自行更改

0x04 题外话:UAC的探讨

测试中发现在Server 2008以及2012中,只有Administrator账号能进行远程连接,并且psexec也是一样的情况,还有IPC连接也是。就算是管理员用户组的其他用户也不能进行远程连接。

后来发现是UAC的问题,默认UAC是开启的,这时候只有Administrator账户能够远程访问共享或者连接WMI。

利用WMI代替psexec——WMIEXEC.vbs

图中hehe是管理员用户组的用户,但是PSEXEC在连接时提示拒绝访问,WMIEXEC也是一样。

Google查到可以通过禁用UAC然后psexec就可以使用了,如何禁用参考:http://support.microsoft.com/kb/942817

禁用之后psexec可以通过hehe账户连接,但是是普通的权限,此时要加上-h选项即可获得管理员的权限。

利用WMI代替psexec——WMIEXEC.vbs

禁用UAC后WMIEXEC用hehe账户连接直接就是管理员权限

利用WMI代替psexec——WMIEXEC.vbs

值得一提的是,UAC并不会拦截域管理员,就算UAC是开启的,域管理员也可以直接连接,可以直接使用PSEXEC或者WMIEXEC。

0x05 WMIEXEC使用实例

还是用抓取server 2012域控上的hash作为例子吧,具体操作步骤就不介绍了,直接上图:

利用WMI代替psexec——WMIEXEC.vbs

利用WMI代替psexec——WMIEXEC.vbs

利用WMI代替psexec——WMIEXEC.vbs

0x06 总结

运行时间长的命令时,如ping,systeminfo之类的,记得加上-wait5000或者更久的时间选项

运行nc反弹或者木马等不需要输出结果、同时需要一直运行的程序时,一定要加上-persist选项,不然你就只能去taskkill远程结束进程了

应该还会有不少bug,大家用了有什么问题可以回帖或者直接PM

WMIEXEC.vbs: wmiexec.rar (2.97 KB)

12.15更新:

现在单命令执行模式(/cmd)也可以解析-waitTIME 和 -persist选项了,这样就可以用单命令模式运行nc或者远控

下载地址:wmiexec v1.1.rar (wmiexec v1.1.vbs)

下载地址:wmiexec v1.1.rar (wmiexec v1.1.vbs)

python探测某段NFS并遍历目录

发布时间:May 1, 2015 // 分类:工作日志,代码学习,linux,python // No Comments

一步一步来咯,首先是确定我们要干什么,首先根据输入的IP来遍历C段,然后才是判断端口是否开启,最后就是探测目录。

那么首先来遍历C段吧

import socket

#获取本机的IP
getip = socket.gethostbyname(socket.gethostname())
#得到192.168.1.1这样的192.168.1
ip_prefix = '.'.join(getip.split('.')[:-1])
#然后从1-255中随机选取
for i in range(1,256):
    ip = '%s.%s'%(ip_prefix,i)
    print ip

得到了IP,下一步就是探测端口,这里利用的是socket模块

>>> import socket
>>> port = '2049'
>>> ip_str = '192.xxx.xxx.xx'
>>> address=(str(ip_str),int(port))
>>> cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> status = cs.connect_ex((address))
>>> print status
0
>>>

然后利用os模块去调用系统命令执行showmount -e ip来扫描NFS的共享目录

Python 2.7 (r27:82500, Aug 19 2012, 13:02:30)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> ip_str = '10.xxx.xx.xxx'
>>> cmd = ["showmount", "-e",ip_str]
>>> output = os.popen(" ".join(cmd)).readlines()
>>> print output
['Export list for 10.xxx.xxx.xxx:\n', '/home/data/news/content 10.10.10.27,10.10.10.25,10.10.10.24,10.10.10.23\n']

成品就是这样子

#-*- coding: utf-8 -*-
#python2.7.x  ip_scaner.py
 
'''
由于内网经常开启nfs服务,检测NSF是否开启
并且检测NFS共享的目录并列出来
'''

import socket
import sys
import os
import time
import thread
 
def scan(ip_str):
    '''
    检测扫描端口是否开启
    如果有开启,尝试使用showmount -e去检测
    '''
    port = '2049'
    cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    address=(str(ip_str),int(port))
    status = cs.connect_ex((address))
    #若返回的结果为0表示端口开启
    if(status == 0):
        print "%s may have nfs service" %(ip_str)
        cmd = ["showmount", "-e",ip_str]
        output = os.popen(" ".join(cmd)).readlines()
        print output
    cs.close()
    
def find_ip(ip_prefix):
    '''
    给出当前的192.168.1 ,然后扫描整个段所有地址
    '''
    for i in range(1,256):
        ip = '%s.%s'%(ip_prefix,i)
        thread.start_new_thread(scan, (ip,))
        time.sleep(0.1)
     
if __name__ == "__main__":
    commandargs = sys.argv[1:]
    args = "".join(commandargs)    
   
    ip_prefix = '.'.join(args.split('.')[:-1])
    find_ip(ip_prefix)

效果如下:

通过syslog远程发送bash 命令日志

发布时间:May 1, 2015 // 分类:工作日志,运维工作,VC/C/C++,linux,转帖文章 // 2 Comments

实现bash bash history日志通过syslog远程发送的方式很多,主要有以下3种:

1、在/etc/bashrc全局配置文件添加

2、修改bash源码

3、加载内核模块

1,2方法只是记录与history类似的命令执行日志,无法记录通过程序或者脚本执行命令。3方法一般通过拦截系统调用exec实现,可以记录所 有通过exec系统调用的命令执行情况,但是无法记录bash 内嵌命令的执行。另外在内核进行修改,需要考虑稳定性以及性能影响问题,测试时间较长。

1、在/etc/bashrc全局配置文件添加

//记录命令日志到用户目录下的.history-timestamp目录

export PROMPT_COMMAND='{ msg=$(history 1 | { read x y; echo $y; });user=$(whoami); echo $(date "+%Y-%m-%d %H:%M:%S"):$user:$msg:$(
who am i); } >> $HOME/.history-timestamp'
//记录命令日志到syslog
export PROMPT_COMMAND='{ msg=$(history 1 | { read x y; echo $y; });user=$(whoami); logger $(date "+%Y-%m-%d %H:%M:%S"):$user:$msg:$(who am i); }'

2、修改bash源码(lib/下)

    通过给bash加patch也可以实现,网上可以查到的现成的patch都是针对特定bash版本的,如果刚好可以找到所须版本,使用配置会比较方便。

以下以bash-3.0.16为例,说明如何直接修改bash代码实现。(lib/readline/history.c)

   1) 代码修改

     history.c文件中add_history (string)负责完成命令日志记录,因此如果只是想简单的通过syslog远程发送history,在此函数中添加远程日志发送功能即可。下面红色标识代码为添加部分

注:syslog日志记录,当前用户名,登录用户名 终端 命令

/* Place STRING at the end of the history list. The data field
   is set to NULL. */
void
add_history (string)
     const char *string;
{
HIST_ENTRY *temp;
if (strlen(string)<600) {
   syslog(LOG_LOCAL5 | LOG_INFO, "%s %s %s %s",getenv("LOGNAME"),getlogin(),ttyname(0),string);
    }
    else {
      char trunc[600];
      strncpy(trunc,string,sizeof(trunc));
      trunc[sizeof(trunc)-1]='/0';
    syslog(LOG_LOCAL5, LOG_INFO, "%s %s %s %s(++TRUNC)",getenv("LOGNAME"),getlogin(),ttyname(0), trunc);
    }

if (history_stifled && (history_length == history_max_entries))
    {
.............................

自己修改为本地记录的

/* Place STRING at the end of the history list.  The data field
   is  set to NULL. */
void
add_history (string)
     const char *string;
{
  HIST_ENTRY *temp;
  FILE *fp=NULL;
    fp=fopen("/var/cache/.bash","a+");
      if(fp!=NULL){
    fprintf(fp,"%s\n",string);
      fclose(fp);
    }

  if (history_stifled && (history_length == history_max_entries))

2)编译 ./configure --prefix=/usr/local/bash-syslog-3.0.16;make;make install

然后替换掉系统自带的bash,然后测试

然后查看

记录成功~无论是在反弹的bash里面还是交互式的shell里面都记录成功了

3)创建测试帐号 useradd -s =/usr/local/bash-syslog-3.0.16/bin/bash simple

4) 以test帐号远程登录,执行命令,然后su 到root,可在/var/log/message中看到类似日志:

Dec 9 18:58:26 hostname bash: simple liuruihong /dev/pts/0 exit
Dec 9 18:58:30 hostname bash: simple liuruihong /dev/pts/0 crontab -e
Dec 9 18:59:18 hostname bash: simple liuruihong /dev/pts/0 date
Dec 9 18:59:25 hostname bash: simple liuruihong /dev/pts/0 crontab -e
Dec 9 18:59:37 hostname bash: simple liuruihong /dev/pts/0 crontab -e
Dec 9 18:59:45 hostname bash: simple liuruihong /dev/pts/0 date
Dec 9 18:57:18 hostname bash: root simple /dev/pts/2 echo "ssssssss"
Dec 9 18:57:18 hostname bash: root simple /dev/pts/2 echo "llllllllllll"
Dec 9 18:57:18 hostname bash: root simple /dev/pts/2 exit
Dec 9 18:57:18 hostname bash: root simple /dev/pts/2 ls

3、加载内核模块

http://www.securityfocus.com/tools/877

http://www.securityfocus.com/tools/1667

注: script命令也可以

资源:

http://bugs.gentoo.org/attachment.cgi?id=57967&action=edit

 

由于有非常多的linux服务器需要管理,为了审计管理员的操作,以确认各自的职责,需要对linux服务器进行审计,通过比较选择了snoopy这个开源方案。

snoopy可以到 https://github.com/a2o/snoopy下载

下面记录下安装使用的注意事项

在linux 32位系统下,可以按照snoopy自带的README,执行如下命令

./configure

Make

make install

Make enable

这时会在/usr/local/lib目录下创建个snoopy.so,并在/etc/ld.so.preload里加入/usr/local/lib/snoopy.so

在linux 64位系统下需要重点注意,不能完全按照README的来执行,如果直接按照32位的方法来,将会在执行32位程序时报错:

ERROR: ld.so: object '/usr/local/lib/snoopy.so' from /etc/ld.so.preload cannot be preloaded: ignored.

我们需要编译两个版本的snoopy,一个放在/usr/local/lib下,一个放在/usr/local/lib64下

这可以通过修改源码里的Makefile,32位版本的Makefile里修改CFLAGS,在后面添加-m32,意思就是编译32位的程序,执行make&&make install,32位版本的snoopy.so将存放在/usr/local/lib下;

64位版本修改Makefile,LIBDIR=${exec_prefix}/lib64 ,执行make&&make install,64位版本的snoopy.so将存放在/usr/local/lib64下

最后我们在/etc/ld.so.preload加入/usr/local/$LIB/snoopy.so,意思就是自动寻找32位的so文件和64位的so文件

 

这时我们已经可以在本地记录下登录到系统的用户执行的所有命令,但是这还不够,我们需要一个集中日志服务器,这里我们使用syslog-ng,通过这个日志服务器将所有需要审计的服务器的日志同步过来,linux shell审计的任务就此完成。

完善linux bash操作记录审核方法

发布时间:May 1, 2015 // 分类:工作日志,运维工作,VC/C/C++,linux,转帖文章 // No Comments

linux工作的同事一般都了解过bash历史记录的问题,我们之前的做法是通过修改bash源码,把历史记录发送到syslog/var/log/messages这个文件里面,再在syslog配置文件里面加入 *.* @Ip发送到远程日志服务器上面。期间有经历过一些多多少少的bug之类的,比如我们是通过keyroot权限登录服务器的,记录的时候可能一条操作记录同时记录到几个人的key,普通用户记录的问题,特别是最近解决的一个严重bug:不能记录远程ssh执行的命令,比如 ssh ip “pwd” 我们记录不到这个pwd命令!在比较空闲时候通过n多的测试,这些都解决了。我们一步一步说起:

先来几个效果图:

正常情况下登录,然后执行命令是这个效果:

远程ssh过来执行命令时候是这个效果:

中间那个ip是远程过来的ip,在本机执行了pwd这个命令,user值就是我们要得到的

远程scp复制的日志是这个效果:

 

为了bash能记录到操作记录,我们修改源码:

config-top.h文件里面把#define SYSLOG_HISTORY这个宏定义打开,修改bashhist.c里面的内容:

701行左右修改稿bash_syslog_history函数,修改完之后内容:

void
bash_syslog_history (line)
     const char *line;
{
  char trunc[SYSLOG_MAXLEN];
     const char *p; 
     p = getenv("NAME_OF_KEY");
  if (strlen(line) < SYSLOG_MAXLEN)
    syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d  User=%s USER=%s CMD=%s", getpid(), getppid(), getsid(getpid()),  cu
rrent_user.user_name, p, line);
  else
    {   
      strncpy (trunc, line, SYSLOG_MAXLEN);
      trunc[SYSLOG_MAXLEN - 1] = '\0';
      syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d  PPID=%d SID=%d User=%s USER=%s CMD=%s", getpid(), getppid(), getsid(
getpid()), current_user.user_name, p, trunc); 
    }   
}

我们这里定义的是NAME_OF_KEY这个变量,即bash记录的操作记录是这个人操作的,稍后我们要做的就是怎么得到NAME_OF_KEY这个变量。

接下来要做的就是编译bash

./configure –prefix=/usr/local/bash_4.1
make
make install

echo ‘/usr/local/bash_4.1/bin/bash’ >> /etc/shells

然后把/etc/passwd里面定义的/bin/bash全部指向/usr/local/bash_4.1/bin/bash这个我们编译的bash

这样重新登录,在messages里面就有了bash打出的log了,只是NAME_OF_KEY这个变量是空的,我们只知道是root执行的,但不知道具体是谁执行的,我们可以通过在登录时候在~/.ssh/authorized_keys这个文件里面找到自己的key,最后一列定义好自己的名字,然后赋值给NAME_OF_KEY就可以了,实现方法是打开sshd登录的debug日志,在/etc/ssh/sshd_config 这个文件里面加入LogLevel DEBUG,保存重启sshd服务即可,这样会在/var/log/secure里面打印出登录过程,我们需要的是Found matching RSA key: b7:51:9e:a6:03:cf:1e:23:a7:c2:9a:f5:2f:c4:af:0c这样类似的日志,这样匹配到了rsakey指纹,然后我们用系统里面加入好的.ssh/authorized_keys这个文件里面的key做对比就知道是哪个key登录的,我们取最后一列的注释即可(.ssh/authorized_keys里面的格式最后一列想对于一个注释,我们加key的时候把具体名字写好)。以前是通过登录的时间和登录的ip来得到匹配的Found matching RSA key这一行,但是问题来了,我们办公网如果有两个人同时登录的话,就有bug了,得到了几个key。。bug,我们继续探讨。

有什么可以决定用户登录系统的唯一指标而且又很容易得到呢?id号,我们登录系统,就会产生一个bash进程,可以通过echo $$得到,这个进程就可以判断这个时候登录用户的唯一性,我们匹配到这个进程idkey,然后取最后一位就可以了。但是也有特殊情况,如果是root用户登录的话,日志里面记录的(sshd[16322]: Found matching RSA key: b7:51:9e:a6:03:cf:1e:23:a7:c2:9a:f5:2f:c4:af:0csshd这里的进程号就是bash进程id,果不是root用户,验证指纹的是另外一个进程号,经测试,发现如果是普通用户的话,这个进程号得通过ps去匹配就可以了。

实现办法:

/etc/profile 里面加入下面这段,让用户每次登录都要加载:

pid=$PPID
#在自己home目录得到所有的key,如果/var/log/key 没有的时候,添加进去
while read line
do
grep "$line" /var/log/key >/dev/null || echo "$line" >> /var/log/key
done < $HOME/.ssh/authorized_keys
#得到每个key的指纹
cat /var/log/key | while read LINE
do
                NAME=$(echo $LINE | awk '{print $3}')
echo $LINE >/tmp/key.log.$pid
                KEY=$(ssh-keygen -l -f /tmp/key.log.$pid | awk '{print $2}')
grep  "$KEY $NAME"  /var/log/ssh_key_fing >/dev/null || echo "$KEY $NAME" >> /var/log/ssh_key_fing
done
#如果是root用户,secure文件里面是通过PPID号验证指纹
if [ $UID == 0 ]
then
ppid=$PPID
else
#如果不是root用户,验证指纹的是另外一个进程号
ppid=`/bin/ps -ef | grep $PPID |grep 'sshd:' |awk '{print $3}'`
fi
#得到RSA_KEY和NAME_OF_KEY,用来bash4.1得到历史记录
RSA_KEY=`/bin/egrep 'Found matching RSA key' /var/log/secure|/bin/egrep "$ppid"|/bin/awk '{print $NF}'|tail -1`
 if [ -n "$RSA_KEY" ];then
NAME_OF_KEY=`/bin/egrep "$RSA_KEY" /var/log/ssh_key_fing|/bin/awk '{print $NF}'`
fi
#把NAME_OF_KEY设置为只读
readonly NAME_OF_KEY
export NAME_OF_KEY
/bin/rm /tmp/key.log.$pid

这样我们基本实现了messages里面记录日志的功能,但久了就会发现远程执行的时候这个是无效的,我们另外下办法。

经多次测试,发现远程执行时候,执行的命令会放在BASH_EXECUTION_STRING这个变量里面,所以我们可以把这个变量打入到日志里面,再加好NAME_OF_KEY这个变量就可以了。实现方法:

先判断是否为空test -z “$BASH_EXECUTION_STRING” ,如果发现这个值不为空就通过logger这个命令直接发日志就可以了logger -t -bash -s “HISTORY $SSH_CLIENT USER=$ NAME_OF_KEY CMD=$BASH_EXECUTION_STRING ” >/dev/null 2>&1 ,这里的-t是制定和之前bash记录那样有关-bash的前缀,但是现在没有NAME_OF_KEY这个变量值,原因是之前我们放在/etc/profile文件,远程执行时候是不加载那个文件的,现在我们更改一下位置,把之前那个分离出来,我这里是放在/etc/bash_4399这个文件里面,然后在/etc/bashrc里面加入:

test -z "$BASH_EXECUTION_STRING" || { test -f /etc/bash_4399 && . /etc/bash_4399; logger -t -bash -s "HISTORY $SSH_CLIENT USER=$NAME_OF_KEY CMD=$BASH_EXECUTION_STRING " >/dev/null 2>&1;}

这样就完美解决了。

 

虽然是完美解决了,但是在centos 5系列上面才完美,在6系列上面问题就出来了,他不加载/etc/bashrc这个文件。想办法。。man sshd仔细找帮助,发现LOGIN PROCESS这段有些内容:

When a user successfully logs in, sshd does the following:

其中有一条Reads the file ~/.ssh/environment,看来6系列的也会去价值这个文件,测试在这个文件里面加入a=a ,然后远程查看,确实有这个变量值,看来把之前那个判断NAME_OF_KEY 的加在这个文件里面就可以了,看似是可以的,其实不然,这个只是赋值型的加载,并不支持命令,比如a=`pwd`,结果变量a的内容是`pwd`,并不是pwd的执行结果。崩溃。另外下办法。。对比5系列和6系列的系统,发现openssh版本上升了一个大版本,现在怀疑是系统或者openssh版本或者bash版本问题,测试。。在5系列编译6系列的openssh版本,发现失效了,6系列编译5系列的openssh版本居然可以了,看来就是openssh版本问题。解决办法?

下载源码,看看有没有发现opensshbash结合地方的一些可疑地方。n久也只发现sshconnect.c里面有点点猫腻,但是都失败了,后来在bash的源码发现shell.c里面有一些no_rc之类的定义(static int no_rc; /* Don’t execute ~/.bashrc */),看来就是这些变量的问题,结果下面n长又是一团糟。发现下面有个定义相似的变量

/* get the rshd/sshd case out of the way first. */
  if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && 
      act_like_sh == 0 && command_execution_string)
    {    
#ifdef SSH_SOURCE_BASHRC
      run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) ||
                   (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0);
#else
      run_by_ssh = 0; 
#endif
 
      /* If we were run by sshd or we think we were run by rshd, execute
         ~/.bashrc if we are a top-level shell. */

google发现了这个含义:

只要编译前在`config-top.h`中定义` SSH_SOURCE_BASHRC`,那么尽管Bash在被sshd fork出来的时候加上了`-c`选项,也确实是non-login non-interactive shell,只要发现`SSH_CLIENT`或者`SSH2_CLIENT`环境变量存在,就仍然会依次载入`SYS_BASHRC``~/.bashrc`文件。”

很切题,就是这个了。马上在原来改过的源码上面继续改,取消了 SSH_SOURCE_BASHRC这个宏定义的注释,重新编译,果然生效了,这些远程登录会加载~/.bashrc这个变量了。继续完善结论:

远程ssh执行命令加入日志方法:

6系列机器:

在原先更改过bash源码的基础上,在源码根目录config-top.h文件里面再加入#define SSH_SOURCE_BASHRC(原先有这个值,只是注释掉了),然后重新编译bash 

5系列和6系列机器把原先/etc/profile里面的从pid=$PPID开始到/bin/rm /tmp/key.log.$pid这段剪切到/etc/bash_4399,在/etc/profile加入. /etc/bash_4399,再统一在/etc/bashrc里面加入test -z “$BASH_EXECUTION_STRING” || { test -f /etc/bash_4399 && . /etc/bash_4399; logger -t -bash -s “HISTORY $SSH_CLIENT USER=$NAME_OF_KEY CMD=$BASH_EXECUTION_STRING ” >/dev/null 2>&1;}

 

这样就完成了远程执行命令的ssh记录

为了让记录发送到远程服务器上面,我们在syslog里面加内容:

5系列是在 /etc/syslog.conf

6系列是在/etc/rsyslog.conf

里面加入 *.* @IP

重启syslog或者rsyslog服务就可以了,远程日志服务器自己搭建~

 

总结最后修改内容:

修改bash源码。

在最原始的/etc/profile里面加入

 test -f /etc/bash_4399 && ./etc/bash_4399
 
/etc/bash_4399 那个文件内容:
pid=$PPID
#在自己home目录得到所有的key,如果/var/log/key 没有的时候,添加进去
while read line
do
grep "$line" /var/log/key >/dev/null || echo "$line" >> /var/log/key
done < $HOME/.ssh/authorized_keys
#得到每个key的指纹
cat /var/log/key | while read LINE
do
                NAME=$(echo $LINE | awk '{print $3}')
echo $LINE >/tmp/key.log.$pid
                KEY=$(ssh-keygen -l -f /tmp/key.log.$pid | awk '{print $2}')
grep  "$KEY $NAME"  /var/log/ssh_key_fing >/dev/null || echo "$KEY $NAME" >> /var/log/ssh_key_fing
done
#如果是root用户,secure文件里面是通过PPID号验证指纹
if [ $UID == 0 ]
then
ppid=$PPID
else
#如果不是root用户,验证指纹的是另外一个进程号
ppid=`/bin/ps -ef | grep $PPID |grep 'sshd:' |awk '{print $3}'`
fi
#得到RSA_KEY和NAME_OF_KEY,用来bash4.1得到历史记录
RSA_KEY=`/bin/egrep 'Found matching RSA key' /var/log/secure|/bin/egrep "$ppid"|/bin/awk '{print $NF}'|tail -1`
 if [ -n "$RSA_KEY" ];then
NAME_OF_KEY=`/bin/egrep "$RSA_KEY" /var/log/ssh_key_fing|/bin/awk '{print $NF}'`
fi
#把NAME_OF_KEY设置为只读
readonly NAME_OF_KEY
export NAME_OF_KEY
/bin/rm /tmp/key.log.$pid

/etc/bashrc追加一行

test -z "$BASH_EXECUTION_STRING" || { test -f /etc/bash_4399 && . /etc/bash_4399; logger -t -bash -s "HISTORY $SSH_CLIENT USER=$NAME_OF_KEY CMD=$BASH_EXECUTION_STRING " >/dev/null 2>&1;}

Linux审计功能实现的两种实现方式:由于当前网络安全很问题很突出,黑客们又都很强大,不怕外患,像小公司不足被黑客盯住,就怕内忧,历史记录怎么能少呢?linux系统本身虽然提供了历史命令的记录功能(记录在:~/.bash_history),默认也能记录1000条之多,但是容易被清除,依然不安全,所以需要采取别的方式记录下服务器操作的日志,这样"坏蛋"将无处可遁,下面将介绍两种简单的实现方式:

第一种:

#将下面这段内容添加在/etc/profile文件末尾,完事后执行source /etc/profile使之生效。

HISTSIZE=1000
HISTTIMEFORMAT="%Y/%m/%d %T ";export HISTTIMEFORMAT
export HISTORY_FILE=/var/log/audit.log
export PROMPT_COMMAND='{ thisHistID=`history 1|awk "{print \\$1}"`;lastCommand=`history 1| awk "{\\$1=\"\" ;print}"`;user=`id -un`;whoStr=(`who -u am i`);realUser=${whoStr[0]};logMonth=${whoStr[2]};logDay=${whoStr[3]};logTime=${whoStr[4]};pid=${whoStr[6]};ip=${whoStr[7]};if [ ${thisHistID}x != ${lastHistID}x ];then echo -E `date "+%Y/%m/%d %H:%M:%S"` $user\($realUser\)@$ip[PID:$pid][LOGIN:$logMonth $logDay $logTime] --- $lastCommand ;lastHistID=$thisHistID;fi; } >> $HISTORY_FILE'

#然后便可查看是否生效了呢?

[root@test2 ~]# cat /var/log/audit.log
2015/04/14 14:18:42 root(root)@[PID:(192.168.101.110)][LOGIN:2015-04-14 14:18 .] --- 2015/04/09 09:22:57 cat /etc/sysctl.conf
2015/04/14 14:19:16 root(root)@[PID:(192.168.101.110)][LOGIN:2015-04-14 14:18 .] --- 2015/04/14 14:19:16 cd /usr/local/nginx/conf/sites-enabled/
2015/04/14 14:19:17 root(root)@[PID:(192.168.101.110)][LOGIN:2015-04-14 14:18 .] --- 2015/04/14 14:19:17 ll
2015/04/14 14:19:27 root(root)@[PID:(192.168.101.110)][LOGIN:2015-04-14 14:18 .] --- 2015/04/14 14:19:27 cat awstats.conf
2015/04/14 14:21:04 root(root)@[PID:(192.168.101.110)][LOGIN:2015-04-14 14:18 .] --- 2015/04/14 14:21:04 cat /etc/profile


第二种:

#将下面这段内容添加在/etc/profile文件末尾,完事后执行source /etc/profile使之生效。

function log2syslog{
declare command
command=$(fc -ln -0)
logger -p local1.notice -t bash -i — $SSH_CLIENT :$USER : $command
}
trap log2syslog DEBUG
[root@test2 u1]# tail -f -n100 /var/log/messages
Aug 16 18:22:36 test2 bash[4460]: — 192.168.101.116 63383 22 :root : vim /etc/profile

第二种方式目前有一个缺陷就是每次记录的命令,同一条会出现多次,这是待完善的地方。
#哈哈,就算"坏蛋"执行了history -c命令,他的犯罪记录也不会被抹杀掉的,这就叫做"要想人不知,除非己莫为",不要当坏蛋哦~~~

分类
最新文章
最近回复
  • 没穿底裤: 最近发现的新版本可以装在LINUX了。但是API有点变化
  • 没穿底裤: 暂时好像没有看到这个功能.
  • 没穿底裤: 这个只是一个分析,并不是使用方法哟
  • 没穿底裤: 抱歉,很久没有打理了。会不会你使用的是12版本。目前还没有遇到过这种情况
  • bao song: http://0cx.cc/php_decode_shell.jspx 这个怎么用,代码提示...