CTF 學習筆記 03--Linux運維
阿新 • • 發佈:2019-01-06
注:linux上很少出現遠端溢位漏洞,攻進linux一般拷爆破或通過控制Windows監視Linux行為進入(鍵盤記錄器)
##運維流程-SSH
* 金鑰登入
#禁止密碼登入並配置公私鑰登入
#編輯sshd_config檔案
vi /etc/ssh/sshd_config
#禁用密碼驗證
PasswordAuthentication no
#啟用金鑰驗證
RSAAuthentication yes
PubkeyAuthentication yes
#指定公鑰資料庫檔案
AuthorsizedKeysFile .ssh/authorized_keys
#或者直接輸入下面的命令sed -i "s/^PasswordAuthentication.*/PasswordAuthentication no/g" /etc/ssh/sshd_config sed -i "s/^#RSAAuthentication.*/RSAAuthentication yes/g" /etc/ssh/sshd_config sed -i "s/^#PubkeyAuthentication.*/PubkeyAuthentication yes/g" /etc/ssh/sshd_config sed -i "s/^#AuthorizedKeysFile.*/AuthorizedKeysFile .ssh\/authorized_keys/g" /etc/ssh/sshd_config
#重啟SSH服務前建議多保留一個會話以防不測
#RHEL/CentOS系統
service sshd restart
#ubuntu系統
service ssh restart
#debian系統
/etc/init.d/ssh restart
* ssh弱密碼爆破
##web原始碼備份
遠端獲取檔案
scp -r Web1:/var/www/html/ webbak/
備份最好基於時間備份,每隔一個小時備份一次,最好保留原始備份。
#!/bin/bash time=`/bin/date +%F` bak_file="/data/backup/$time.tar.gz" webdir="/data/www/" tar zcvf $bak_file $webdir >/dev/null 2>&1 &
計劃任務
crontable -e
30 * * * * /bin/bash /data/bak.sh #新增定時執行任務
ctl+o #儲存 ctl+x #退出##資料庫備份
mysqldump -uroot -p --single-transaction --all-databases > backup.sql # 所有
mysqldump -u root -p --single-transaction dataname > dataname.sql #單個
mysqldump --skip-lock-tables -uxxxx -pxxxxxx -h 166.111.9.173 -R 資料庫名 > ./urlevent20180319.sql
mysqldump -h127.0.0.1 -uroot -ppassword database |gzip >$backupDir/$database-$today.sql.gz`然後,scp回來。
shell指令碼原理:
#備份目錄
backupDir=/home/backup/database
#mysqlDump
mysqldump=/usr/local/mariadb/bin/mysqldump
host=127.0.0.1
username=root
password=42342342
today=`date +%Y%m%d`
#要備份的資料庫陣列
databases=(blog chinese_medicine)
# echo $databaseCount
for database in ${databases[@]}
do
echo '開始備份'$database
$mysqldump -h$host -u$username -p$password $database | gzip > $backupDir/$database-$today.sql.gz
echo '成功備份'$database'到'$backupDir/$database-$today.sql.gz
done
恢復mysql
mysql -uroot -p TEST < bak.sql
##資料庫運維
取消遠端登入(不需要遠端管理)
取消mysql密碼認證:
修改my.cnf ,新增 skip-grant-tables
修改mysql密碼
update mysql.user set password=PASSWORD('skyboy') where user='root' and host='localhost';
flush privileges;
最好先修改mysql,再修改php。一般不存在需要修改mysql密碼的情況。
禁止資料庫的遠端連線:
use mysql;
update user set host='localhost' where user='root';
flush privileges;
資料庫降權
CREATE USER ‘dog’@‘localhost’ IDENTIFIED BY ‘123456’;
GRANT ALL ON databasename.* TO ‘dog’@‘localhost
flush privileges;
調整站點配置檔案,修改資料庫連線的使用者名稱和密碼。通過本機或ssh登入。
##許可權配置--Linux的精髓
對於非必須可寫的目錄:
許可權設定為755,擁有者設為非www-data使用者;從而防止檔案被篡改/刪除。
對於必須可寫的目錄:
根據伺服器型別,上一個.htaccess, 或者修改nginx的目錄配置檔案,去除此路徑的指令碼執行許可權。
對於apache:
<FileMatch ".(pjp|php3|php4|php5)|phtml)">
Order Allow.Deny
Deny from all
<FilesMaych> #禁止惡意指令碼的上傳
對於Nginx:修改配置檔案
location ~ /mm/(data|uploads|templets)/*.(php)$ {
deny all;
}
location ~ .php$ {
try_files $uri /404.html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
修改完成之後,nginx -S reload
##防禦指令碼
* waf指令碼 WAF需要同時具備攔截和抓取流量的作用。
php-WAF的批量新增:
find /var/www/html -type f -path "*.php" | xargs sed -i "s/<?php/<?php require_once('/tmp/waf.php');n/g“
port-forwarding.pyimport socket
import threading
import sys
def handle(buffer):
return buffer
def transfer(src, dst, direction):
src_name = src.getsockname()
src_address = src_name[0]
src_port = src_name[1]
dst_name = dst.getsockname()
dst_address = dst_name[0]
dst_port = dst_name[1]
while True:
buffer = src.recv(0x400)
if len(buffer) == 0:
print "[-] No data received! Breaking..."
break
# print "[+] %s:%d => %s:%d [%s]" % (src_address, src_port, dst_address, dst_port, repr(buffer))
if direction:
print "[+] %s:%d >>> %s:%d [%d]" % (src_address, src_port, dst_address, dst_port, len(buffer))
else:
print "[+] %s:%d <<< %s:%d [%d]" % (dst_address, dst_port, src_address, src_port, len(buffer))
dst.send(handle(buffer))
print "[+] Closing connecions! [%s:%d]" % (src_address, src_port)
src.shutdown(socket.SHUT_RDWR)
src.close()
print "[+] Closing connecions! [%s:%d]" % (dst_address, dst_port)
dst.shutdown(socket.SHUT_RDWR)
dst.close()
def server(local_host, local_port, remote_host, remote_port, max_connection):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((local_host, local_port))
server_socket.listen(max_connection)
print '[+] Server started [%s:%d]' % (local_host, local_port)
print '[+] Connect to [%s:%d] to get the content of [%s:%d]' % (local_host, local_port, remote_host, remote_port)
while True:
local_socket, local_address = server_socket.accept()
print '[+] Detect connection from [%s:%s]' % (local_address[0], local_address[1])
print "[+] Trying to connect the REMOTE server [%s:%d]" % (remote_host, remote_port)
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
print "[+] Tunnel connected! Tranfering data..."
# threads = []
s = threading.Thread(target=transfer, args=(
remote_socket, local_socket, False))
r = threading.Thread(target=transfer, args=(
local_socket, remote_socket, True))
# threads.append(s)
# threads.append(r)
s.start()
r.start()
print "[+] Releasing resources..."
remote_socket.shutdown(socket.SHUT_RDWR)
remote_socket.close()
local_socket.shutdown(socket.SHUT_RDWR)
local_socket.close()
print "[+] Closing server..."
server_socket.shutdown(socket.SHUT_RDWR)
server_socket.close()
print "[+] Server shuted down!"
def main():
if len(sys.argv) != 5:
print "Usage : "
print "\tpython %s [L_HOST] [L_PORT] [R_HOST] [R_PORT]" % (sys.argv[0])
print "Example : "
print "\tpython %s 127.0.0.1 8888 127.0.0.1 22" % (sys.argv[0])
exit(1)
LOCAL_HOST = sys.argv[1]
LOCAL_PORT = int(sys.argv[2])
REMOTE_HOST = sys.argv[3]
REMOTE_PORT = int(sys.argv[4])
MAX_CONNECTION = 0x10
server(LOCAL_HOST, LOCAL_PORT, REMOTE_HOST, REMOTE_PORT, MAX_CONNECTION)
if __name__ == "__main__":
main()
* 監控指令碼
#!/usr/bin/env python
# encoding:utf-8
import sys
import pyinotify
import os
import time
def detect_waf(pathname):
try:
with open(pathname) as f:
content = f.read()
black_list = ["<?", "<%"]
black_list += ['eval', 'assert']
black_list += ['passthru', 'exec', 'system', 'shell_exec', 'popen', 'proc_open']
black_list += ['hightlight_file', 'show_source', 'php_strip_whitespace', 'file_get_contents', 'readfile', 'file', 'fopen', 'fread', 'include', 'include_once', 'require', 'require_once', 'fread', 'fgets', 'fpassthru', 'fgetcsv', 'fgetss', 'fscanf', 'parse_ini_file']
black_list += ['glob', 'opendir', 'dir', 'readdir', 'scandir']
FLAG = False
for black in black_list:
if black in content:
print "[!] Dangerous php script! (%s)" % (black)
print "[*] Content : "
print content.rstrip("\n")
FLAG = True
break
if FLAG:
target_path = "webshells/%s.log" % (time.strftime('%Y-%m-%d-%H:%M:%S',time.localtime(time.time())))
print "[+] Detect webshell , moving from %s to %s" % (pathname, target_path)
os.rename(pathname, target_path)
except Exception as e:
print "[-] %s" % (str(e))
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
if event.dir:
print "Create Directory : %s" % (event.pathname)
else:
print "Create File : %s" % (event.pathname)
def process_IN_DELETE(self, event):
if event.dir:
print "Delete Directory : %s" % (event.pathname)
else:
print "Delete File : %s" % (event.pathname)
def process_IN_CLOSE_WRITE(self, event):
if event.dir:
print "Close Writable Directory : %s" % (event.pathname)
else:
print "Close Writable File : %s" % (event.pathname)
detect_waf(event.pathname)
def main():
if len(sys.argv) != 2:
print "Usage : "
print "\tpython %s [PATH]" % (sys.argv[0])
exit(1)
path = sys.argv[1]
wm = pyinotify.WatchManager()
wm.add_watch(path, pyinotify.ALL_EVENTS, rec=True)
eh = EventHandler()
notifier = pyinotify.Notifier(wm, eh)
notifier.loop()
if __name__ == "__main__":
main()
* 一句話木馬 用以後期運維 具有web的許可權以便於web操作(運維人員的許可權往往不是web許可權)
<?php
$serverList = array(
"127.0.0.1",
"::1"
);
$ip = $_SERVER['REMOTE_ADDR'];
foreach ($serverList as $host){
if( $ip===$host){
$a = $_POST['n985de9'];
if(isset($a)) {
eval(base64_decode($a));
}
}else{
die();
}
}
## 檢視網路拓撲 檢視別人的防禦機制 通過跳板機接入內網
masscan(一般用這個就好):
masscan -p 80 172.16.0.0/24
masscan -p0-65535 172.16.0.0/24 -oJ result.json
Nmap:
nmap -sn -T4 ip/24
nmap -Pn ip/24
##木馬查殺
運維選手需要隨時:
* 關注服務的可用性狀況* 檢視檔案監控情況
* 在被攻擊的時候進行響應,儲存相應的流量,查詢/清除後門;
檢視木馬流程:
需要用www-data 許可權進行查詢 (web許可權,如apache;具體可以通過上面一句話木馬實現)crontab -l #檢視計劃任務
ps aux|grep www-data #檢視以www-data許可權執行的可疑流程
清除計劃任務:
crontab -r
crontab -r -u USERNAME
殺死記憶體馬:
ps aux|grep www-data|awk '{print $2}'|xargs kill -9
殺死檔案馬: 通過檔案監控指令碼或流量監視定位木馬
需要以www-data許可權
rm -rf
webshell實在不好刪的話(三種掛馬方式如果是環鏈的啟用關係),直接恢復備份。