Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1649541
  • 博文数量: 631
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3920
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-06 21:58
个人简介

博客是我工作的好帮手,遇到困难就来博客找资料

文章分类

全部博文(631)

文章存档

2022年(2)

2021年(4)

2020年(40)

2019年(4)

2018年(78)

2017年(213)

2016年(41)

2015年(183)

2014年(66)

我的朋友

分类: 系统运维

2017-02-25 22:28:35

最近一台服务器被攻击了,攻击者在服务器上替换了一个系统命令,如ps,ss,netstat,lsof等文件。怎么排查的就不说了。本文的主要目的是写一个检查系统用户的一个脚本,检查哪些系统用户有家目录,哪些用户没有家目录,以及哪些用户可以登录系统。


我们这里的环境有点乱,有的服务器上的web用户可以登录系统,有的系统上却不能登录系统,很是不规范,因此写了这么一个脚本来做检查。接下来,就直接上代码了,主要用到了pwd及spwd模块,比起使用读入/etc/passwd及/etc/shadow文件,然后对其进行处理要方便的多。

# encoding: utf8

# written by lavenliu at 20170211


import pwd

import spwd


sys_users = {}

usr_no_passwd = []

usr_has_passd = []


users_entry = pwd.getpwall()

for entry in users_entry:

    sys_users[entry.pw_name] = entry.pw_shell


for username in sys_users.keys():

    pass_entry = spwd.getspnam(username)

    if pass_entry.sp_pwd == '!!' or pass_entry.sp_pwd == '*':

        usr_no_passwd.append(pass_entry.sp_nam)

    else:

        usr_has_passd.append(pass_entry.sp_nam)


print "These users have home directory:"

for user, home in sys_users.items():

    if home == '/sbin/nologin':

        continue

    else:

        print "%15s: %s" % (user, home)


print

print "These users can login system:"

for user in usr_has_passd:

    print user

执行结果为:

#  chkuser.py 

These users have home directory:

           sync: /bin/sync

       shutdown: /sbin/shutdown

           halt: /sbin/halt

           root: /bin/bash


These users can login system:

root

一个检测TCP端口的Python脚本程序,默认需要两个参数,一个是-a参数,后面接要检测的IP地址,另一个是-p参数,后面接要检测的IP地址的端口,如果省略该选项,默认是IP地址80端口。以下是脚本源文件为:


# cat tcp_checker.py 

#!/usr/bin/env python


import socket

import re

import sys


def check_server(address, port):

    # Create a TCP socket

    s = socket.socket()

    print "\033[33mAttempting to connect to %s on port %s\033[0m" % (address, port)

    try:

        s.connect((address, port))

        print "\033[32mConnected to %s on port %s\033[0m" % (address, port)

        return True

    except socket.error, e:

        print "\033[31mConnection to %s on port %s failed: %s\033[0m" % (address, port, e)

        return False



if __name__ == "__main__":

    from optparse import OptionParser

    parser = OptionParser()


    parser.add_option("-a", "--address", dest="address", default='localhost',

                       help="ADDRESS for server, default is localhost", metavar="ADDRESS")

    parser.add_option("-p", "--port", dest="port", type="int", default=80,

                      help="PORT for server, default is 80", metavar="PORT")

    (options,args) = parser.parse_args()

    print "options: %s, args: %s" % (options, args)

    check = check_server(options.address, options.port)

    print "check_server returned %s" % check

    sys.exit(not check)

运行结果为:

# python tcp_checker.py -a 192.168.56.108 -p 4000

options: {'port': 4000, 'address': '192.168.56.108'}, args: []

Attempting to connect to 192.168.56.108 on port 4000

Connected to 192.168.56.108 on port 4000

check_server returned True

一个生成随机密码的python脚本,默认生成6个20位的随机字符与数字的组合。可以用来当做服务器的密码


 cat genpass.py


from random import choice


import string


def GenPasswd(length=20, chars=string.letters+string.digits):


    return ''.join([choice(chars) for i in range(length)])
 
 
for i in range(6):
    print GenPasswd(20)



#用python打印出直角三角形:
1 #!/usr/bin/env python
  2 # coding=utf-8
  3 i = 0
  4 while i < 5:
  5     j = 0
  6     while j <= i:
  7         print "*",
  8         j+=1
  9     print ""
 10     i+=1             
  
 输出效果如下:
* * 
* * * 
* * * * 
* * * * *


#对上面的程进行深化,可以得到两个相对的三角形:


#!/usr/bin/env python
  2 # coding=utf-8
  3 i = 0
  4 while i < 5:
  5     j = 0
  6     while j <= i:
  7         print "*",
  8         j+=1
  9     print ""
 10     i+=1
 11 i = 5·
 12 while i > 0:
 13     j = 0
 14     while j <= i:
 15         print "*",
 16         j+=1                                                                                                                                  
 17     print ""
 18     i-=1

输出结果如下:

* * 

* * * 

* * * * 

* * * * * 

* * * * * 

* * * * 

* * * 

* * 

#最后上个心形:

1
print'\n'.join([''.join([('PYTHON!'[(x-y)%7]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3

输出结果如下:
                                                         
                                                             
                THON!PYTH           YTHON!PYT               
            !PYTHON!PYTHON!PY   N!PYTHON!PYTHON!P           
          N!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTH         
         N!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON        
        N!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!P       
        !PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PY       
        PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYT       
        YTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTH       
        THON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHO       
        HON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON       
         N!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON        
          PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON         
          YTHON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON!         
            ON!PYTHON!PYTHON!PYTHON!PYTHON!PYTHON           
             !PYTHON!PYTHON!PYTHON!PYTHON!PYTHON            
              YTHON!PYTHON!PYTHON!PYTHON!PYTHON             
                ON!PYTHON!PYTHON!PYTHON!PYTHO               
                  PYTHON!PYTHON!PYTHON!PYTH                 
                    HON!PYTHON!PYTHON!PYT                   
                       PYTHON!PYTHON!P                      
                          ON!PYTHON                         
                             YTH                            
                              H

pwd模块,提供了一个Unix 密码数据库(/etc/passwd)的接口,这个数据库包含本地机器用户账户信息。


pwd.getpwuid(uid):


返回对应uid的用户信息


pwd.getpwnam(name):


返回对应name的用户信息


pwd.getpwall():


返回所有用户信息



pwd 模块

(只用于 Unix) pwd 提供了一个到 Unix 密码/password "数据库"( /etc/passwd 以及相关文件 )的接口.

这个数据库(一般是一个纯文本文件)包含本地机器用户账户的信息

---------------------------------------------------------

 使用 pwd 模块

getpwall 函数返回一个包含所有可用用户数据库入口的列表. 你可以使用它搜索一个用户.

---------------------------------------------------------

import pwd

import os


print pwd.getpwuid(os.getgid())


print pwd.getpwnam("root")



('effbot', 'dsWjk8', 4711, 4711, 'eff-bot', '/home/effbot', '/bin/bosh')

('root', 'hs2giiw', 0, 0, 'root', '/root', '/bin/bash')

---------------------------------------------------------

当需要查询很多名称的时候, 你可以使用 getpwall 来预加载一个字典

---------------------------------------------------------

import pwd

import os


# preload password dictionary

_pwd = {}

for info in pwd.getpwall():

    _pwd[info[0]] = _pwd[info[2]] = info


def userinfo(uid):

    # name or uid integer

    return _pwd[uid]


print userinfo(os.getuid())


print userinfo("root")


('effbot', 'dsWjk8', 4711, 4711, 'eff-bot', '/home/effbot', '/bin/bosh')

('root', 'hs2giiw', 0, 0, 'root', '/root', '/bin/bash')





grp模块,提供了一个Unix 用户组/group(/etc/group)数据库的接口。


grp.getgrgid(gid):


返回对应gid的组信息


grp.getgrname(name):


返回对应group name的组信息


grp.getgrall():


返回所有组信息


pwd和grp的用法都十分相似,对于操作linux系统用户和组十分方便灵活,推荐使用。



1、os


  (1)os.path--常用来提取、分离文件名


    os.path.basename('path') 提取文件基名


    os.path.dirname('path') 提取路径名,去掉基名


    os.path.split('path') 将基名和路径名分离


    os.path.splitext('path') 同上,只不过返回的元组中基名在前,路径名在后


    os.path.join('a','b','c') 将合并成'a/b/c'文件名


    os.path.exists('path') 查询文件是否存在


    os.path.isfile(file) 判断指定对象是否为文件


    os.path.isdir(dir) 判断指定对象是否为目录


    os.path.getsize(path路径) 提取文件的大小


    跟多方法见os.path.[tab][tab]


  (2)os.system(cmd)--调用shell命令(不过不能获取输出,要想获取输出可使用os.popen(cmd).read()、subprocess.Popen等)

    例:os.system('pwd')

  (3)os.getcwp()--获取当前目录

  (4)os.mkdir(dir) 创建目录

  (5)os.remove(file) 删除指定文件

  (6)os.rmdir(dir) 删除指定目录

  (7)os.stat(file) 获取文件信息 


os模块


os模块的作用:


  os,语义为操作系统,所以肯定就是操作系统相关的功能了,可以处理文件和目录这些我们日常手动需要做的操作,就比如说:显示当前目录下所有文件/删除某个文件/获取文件大小……


  另外,os模块不受平台限制,也就是说:当我们要在linux中显示当前命令时就要用到pwd命令,而Windows中cmd命令行下就要用到这个,额...我擦,我还真不知道,(甭管怎么着,肯定不是pwd),这时候我们使用python中os模块的os.path.abspath(name)功能,甭管是linux或者Windows都可以获取当前的绝对路径。


os模块的常用功能:


1  os.name      #显示当前使用的平台

2  os.getcwd()      #显示当前python脚本工作路径

3  os.listdir('dirname')        #返回指定目录下的所有文件和目录名

4  os.remove('filename')       #删除一个文件

5  os.makedirs('dirname/dirname')     #可生成多层递规目录

6  os.rmdir('dirname')     #删除单级目录

7  os.rename("oldname","newname")    #重命名文件

8  os.system()    #运行shell命令,注意:这里是打开一个新的shell,运行命令,当命令结束后,关闭shell

9  os.sep    #显示当前平台下路径分隔符

10  os.linesep    #给出当前平台使用的行终止符

11  os.environ    #获取系统环境变量

12  os.path.abspath(path)    #显示当前绝对路径

13  os.path.dirname(path)    #返回该路径的父目录

14  os.path.basename(path)    #返回该路径的最后一个目录或者文件,如果path以/或\结尾,那么就会返回空值。

15  os.path.isfile(path)     #如果path是一个文件,则返回True

16  os.path.isdir(path)    #如果path是一个目录,则返回True

17  os.stat()    #获取文件或者目录信息

18  os.path.split(path)  #将path分割成路径名和文件名。(事实上,如果你完全使用目录,它也会将最后一个目录作为文件名而分离,同时它不会判断文件或目录是否存在)

19  os.path.join(path,name)   #连接目录与文件名或目录 结果为path/name




2、sys

  (1)sys.exit(n):

    执行至主程序的末尾时,解释器会自动退出. 但是如果需要中途退出程序, 你可以调用sys.exit 函数, 它带有一个可选的整数参数返回给调用它的程序. 这意味着你可以在主程序中捕获对sys.exit 的调用。(注:0是正常退出,其他为不正常,可抛异常事件供捕获!)

  (2)sys.argv[] 给程序提供参数,第一个参数是程序路径本身 ,sys.argv     #将python脚本运行时的脚本名以及参数作为一个list,并输出。



#/usr/bin/python3

import sys


print('the script name is:',sys.argv[0])

if len(sys.argv) > 1:

    print("there are", len(sys.argv)-1, "arguments:")  # 使用len(sys.argv)-1采集参数个数-1为减去[0]脚本名称

    for arg in sys.argv[1:]:            #输出除了[0]外所有参数

        print(arg)

else:

    print("there are no arguments!")




[root@slyoyo ~]# python3 test_py.py haha

the script name is: test_py.py

there are 1 arguments:

haha


    例:

    Test.py脚本内容:

    import sys

 

    print sys.argv[0]

    print sys.argv[1]

    print sys.argv[2]

    print sys.argv[3]

    [root@databak scripts]# python test.py arg1 arg2 arg3

    test.py

    arg1

    arg2

    arg3

 sys.stdout   sys.stdin   #标准输出/输入


print 'Dive in'        # 标准输出

saveout = sys.stdout        # 终在重定向前保存stdout,这样的话之后你还可以将其设回正常

fsock = open('out.log', 'w')      # 打开一个新文件用于写入。如果文件不存在,将会被创建。如果文件存在,将被覆盖。

sys.stdout = fsock                 # 所有后续的输出都会被重定向到刚才打开的新文件上。


print  'This message will be logged instead of displayed'    # 这样只会将输出结果“打印”到日志文件中;屏幕上不会看到输出


sys.stdout = saveout   # 在我们将 stdout 搞乱之前,让我们把它设回原来的方式。    


fsock.close()     # 关闭日志文件。


  (3)sys. path 查看模块的搜索路径

    增加模块搜索路径:

    1)python中动态临时增加

    import sys

    sys.path.append(tmppath)

    2).pth文件增加

    site-packages路径下增加.pth文件,文件中每行记录代表一个有效路径

    3)PYTHONPATH中添加模块路径

    PYTHONPATH是系统环境变量,能够被所有的python识别,比如同时安装了python2.7和python3.4

  (4)sys.platform 返回当前系统平台,如:win32、Linux等。

3、urllib、urllib2

  urllib2可以接受一个Request对象,并以此可以来设置一个URL的headers,但是urllib只接收一个URL。这意味着,你不能伪装你的用户代理字符串等。

  urllib模块可以提供进行urlencode的方法,该方法用于GET查询字符串的生成,urllib2的不具有这样的功能。这就是urllib与urllib2经常在一起使用的原因。

  (1)urllib2.urlopen(url[,data,timeout]) 用来获取网页内容

  (2)urllib2.Response(url) 提供一个response,可在urllib2.urlopen中使用

  (3)urllib2.urlopen(Response) 获取请求,(2)、(3)步一起用和(1)效果一样

  (4)urllib.urlopen(url)  效果同(1)

  获取网页内容后可用read()方法读取

    a = urllib2.urlopen('')

    b = a.read()


4、re 

  详见python正则表达式


正则表达式是非正常重要的知识点,他在许许多多的地方都有应用,既是重点,也是难点。


使用正则表达式需要调用re模块


re模块常用的方法:


1、re.serach()


re.search 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回,如果字符串没有匹配,则返回None。


2、re.match()


re.match 尝试从字符串的开始匹配一个模式,也等于说是匹配第一个单词


3、re.findall


re.findall 在目标查找符合模式的匹配项


4、re.complie()


re.complie 把正则表达式编译成一个对象,这样在re.findall中就可以直接使用了,而不用使用复杂的规则


5、re.split()


re.split 负责把字符分割


6、re.sub()


re.sub 用于替换字符串的匹配项


1

2

>>> help(re.sub)

sub(pattern, repl, string, count=0)

正则匹配模式


^ 匹配字符串的开头

$ 匹配字符串的末尾。

. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。

[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'

[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

re* 匹配0个或多个的表达式。

re+ 匹配1个或多个的表达式。

re? 匹配0个或1个由前面的正则表达式定义的片段,贪婪方式

re{ n}  

re{ n,} 精确匹配n个前面表达式。

re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式

a| b 匹配a或b

(re) G匹配括号内的表达式,也表示一个组

(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。

(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。

(?: re) 类似 (...), 但是不表示一个组

(?imx: re) 在括号中使用i, m, 或 x 可选标志

(?-imx: re) 在括号中不使用i, m, 或 x 可选标志

(?#...) 注释.

(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。

(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功

(?> re) 匹配的独立模式,省去回溯。

\w 匹配字母数字

\W 匹配非字母数字

\s 匹配任意空白字符,等价于 [\t\n\r\f].

\S 匹配任意非空字符

\d 匹配任意数字,等价于 [0-9].

\D 匹配任意非数字

\A 匹配字符串开始

\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c

\z 匹配字符串结束

\G 匹配最后匹配完成的位置。

\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

\n, \t, 等. 匹配一个换行符。匹配一个制表符。等

\1...\9 比赛第n个分组的子表达式。

\10 匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。

太多了懒得手打,直接摘自


贪婪模式:


表示尽可能匹配多的匹配要匹配的内容,可用"?"来取消贪婪匹配,因为?表示匹配前边字符0次或一次


正则中的转义:


可使用"\",不过常用"r"


阅读(825) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~