Redacting 2024.05.18
This commit is contained in:
commit
9212febae2
2 changed files with 279 additions and 0 deletions
183
README.org
Normal file
183
README.org
Normal file
|
@ -0,0 +1,183 @@
|
|||
#+title: Readme
|
||||
#+author: Phil Bajsicki
|
||||
#+options: finline toc:nil
|
||||
|
||||
* Intro
|
||||
This is a coding task from [redacted], which I found
|
||||
rather fun to tinker with.
|
||||
|
||||
This is an org-mode file. The code blocks are tangled using =org-babel= into =cl-secninja.lisp=.
|
||||
|
||||
* Dependencies:
|
||||
- curl
|
||||
- sbcl with quicklisp
|
||||
* Usage:
|
||||
1. Load in SBCL with ~sbcl --load cl-secninja.lisp~.
|
||||
2. Run ~(four)~
|
||||
3. Copy the base64 encrypted message into a file called =email=.
|
||||
4. Run ~(base64)~.
|
||||
5. Done.
|
||||
* Code:
|
||||
** Quicklisp:
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(ql:quickload '(:cl-ppcre
|
||||
:cl-base64
|
||||
:ironclad
|
||||
:jsown))
|
||||
#+end_src
|
||||
|
||||
** Defpackage and in-package
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defpackage #:cl-secninja
|
||||
(:use #:common-lisp #:cl #:uiop #:cl-ppcre #:ironclad #:cl-base64))
|
||||
|
||||
(in-package #:cl-secninja)
|
||||
#+end_src
|
||||
|
||||
** URL var
|
||||
The trailing slash is important for consolidating the URL later.
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defvar *url* "redacted")
|
||||
#+end_src
|
||||
** Run cURL
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defun run-curl (command)
|
||||
(let* ((curl-command (concatenate 'string "curl -i " command))
|
||||
(result (uiop:run-program curl-command
|
||||
:output :string
|
||||
:error-output T)))
|
||||
result))
|
||||
|
||||
#+end_src
|
||||
|
||||
** First page
|
||||
Grab first page, print out the command and result, and return the parameter string.
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defun one ()
|
||||
(let* ((command *url*)
|
||||
(result (run-curl *url*)))
|
||||
(format t "~%COMMAND: curl ~a" command)
|
||||
(format t "~%RESULT: curl ~a" result)
|
||||
(car (ppcre:all-matches-as-strings "\\?.*" result))))
|
||||
#+end_src
|
||||
** Second page
|
||||
This function calls ~(one)~, so calling it directly for seeing the second page
|
||||
works.
|
||||
|
||||
Concatenate the URL with the parameter string from the first function, and grab
|
||||
and return the second page.
|
||||
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defun two ()
|
||||
(let* ((command (concatenate 'string
|
||||
"\"" *url* (one) "\""))
|
||||
(result (run-curl command)))
|
||||
result))
|
||||
#+end_src
|
||||
** Third
|
||||
This is where we get interesting. This function calls ~(two)~, which returns the
|
||||
second page for processing, and then calls ~(run-curl)~ on the command it
|
||||
constructs, and returns the output.
|
||||
|
||||
|
||||
I wanted to see what the values of the variables are while testing, thus the
|
||||
print statements and triple let. I know I could consolidate that, but I feel
|
||||
like this way is more transparent than having a ~(let* (...))~ that does
|
||||
everything in the background.
|
||||
|
||||
The thing that was most tricky here was getting the double quotes to work
|
||||
properly between this function and ~(run-curl)~, because the =command= string is
|
||||
being passed around, and it itself includes quotes.
|
||||
|
||||
|
||||
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defun three ()
|
||||
(let ((headers (ppcre:all-matches-as-strings "X-.*" (two))))
|
||||
(print headers)
|
||||
(print (car headers))
|
||||
(print (cadr headers))
|
||||
(let ((command (concatenate 'string
|
||||
"\"" *url* "\?step=2" "\""
|
||||
" -H \"" (car headers) "\""
|
||||
" -H \"" (cadr headers) "\"")))
|
||||
(let ((result (run-curl command)))
|
||||
(format t "~%RESULT: curl ~a" result)
|
||||
result))))
|
||||
|
||||
#+end_src
|
||||
** Four
|
||||
This was the most fun one, given all the processing. I can't say that the loop
|
||||
worked the first time around.
|
||||
|
||||
After running ~(four)~, your terminal will print out the base64 encoded string.
|
||||
I can't say I want to mess with extracting the base64 string with another
|
||||
regexp, so I just manually copied the string into a file called =email=.
|
||||
|
||||
Then...
|
||||
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
|
||||
(defun four ()
|
||||
(let*
|
||||
((data (three))
|
||||
(input
|
||||
(car (ppcre:all-matches-as-strings "(?sm)\{.*}$" data)))
|
||||
(challenge
|
||||
(string-left-trim "challenge: " (car (ppcre:all-matches-as-strings "challenge:(.*)" data))))
|
||||
(timestamp
|
||||
(string-left-trim "timestamp: " (car (ppcre:all-matches-as-strings "timestamp:(.*)" data))))
|
||||
(sorted (sort (cdr (jsown:parse input)) #'string<= :key #'first))
|
||||
(connected
|
||||
(string-right-trim "\&"
|
||||
(format nil "~{~A~}"
|
||||
(loop
|
||||
for item in sorted
|
||||
collect
|
||||
(concatenate 'string (car item) "\=" (cdr item) "\&")))))
|
||||
(hash (sha-256 connected))
|
||||
(command
|
||||
(string-right-trim "\-"
|
||||
(concatenate 'string
|
||||
"-X POST \"" *url* "\?step=3" "\""
|
||||
" -H \"Content-Type: application/x-www-form-urlencoded\" "
|
||||
" -d \"challenge=" challenge "\""
|
||||
" -d \"timestamp=" timestamp "\""
|
||||
" -d \"hash=" hash "\""
|
||||
))))
|
||||
(terpri)
|
||||
(print challenge)
|
||||
(print timestamp)
|
||||
(print hash)
|
||||
(terpri)
|
||||
(format t "~%COMMAND: curl ~a" command)
|
||||
(terpri)
|
||||
(let ((result (run-curl command)))
|
||||
(format t "~%RESULT: curl ~a" result))
|
||||
(terpri)))
|
||||
|
||||
#+end_src
|
||||
|
||||
*** Sha256
|
||||
Util function for the above code.
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defun sha-256 (str)
|
||||
(ironclad:byte-array-to-hex-string
|
||||
(ironclad:digest-sequence :sha256
|
||||
(ironclad:ascii-string-to-byte-array str))))
|
||||
|
||||
#+end_src
|
||||
** Base64
|
||||
Put the contents of the file into a variable.
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defvar *email* (alexandria:read-file-into-string "email"))
|
||||
#+end_src
|
||||
Then, run the base64 decoder over it until the string can't be decoded any more.
|
||||
#+begin_src lisp :tangle cl-secninja.lisp
|
||||
(defun base64 ()
|
||||
(let ((email *email*))
|
||||
(loop repeat 100 do
|
||||
(if (ppcre:scan "@" email)
|
||||
(print email)
|
||||
(setf email (cl-base64:base64-string-to-string email))))))
|
||||
#+end_src
|
96
cl-secninja.lisp
Normal file
96
cl-secninja.lisp
Normal file
|
@ -0,0 +1,96 @@
|
|||
(ql:quickload '(:cl-ppcre
|
||||
:cl-base64
|
||||
:ironclad
|
||||
:jsown))
|
||||
|
||||
(defpackage #:cl-secninja
|
||||
(:use #:common-lisp #:cl #:uiop #:cl-ppcre #:ironclad #:cl-base64))
|
||||
|
||||
(in-package #:cl-secninja)
|
||||
|
||||
(defvar *url* "redacted")
|
||||
|
||||
(defun run-curl (command)
|
||||
(let* ((curl-command (concatenate 'string "curl -i " command))
|
||||
(result (uiop:run-program curl-command
|
||||
:output :string
|
||||
:error-output T)))
|
||||
result))
|
||||
|
||||
(defun one ()
|
||||
(let* ((command *url*)
|
||||
(result (run-curl *url*)))
|
||||
(format t "~%COMMAND: curl ~a" command)
|
||||
(format t "~%RESULT: curl ~a" result)
|
||||
(car (ppcre:all-matches-as-strings "\\?.*" result))))
|
||||
|
||||
(defun two ()
|
||||
(let* ((command (concatenate 'string
|
||||
"\"" *url* (one) "\""))
|
||||
(result (run-curl command)))
|
||||
result))
|
||||
|
||||
(defun three ()
|
||||
(let ((headers (ppcre:all-matches-as-strings "X-.*" (two))))
|
||||
(print headers)
|
||||
(print (car headers))
|
||||
(print (cadr headers))
|
||||
(let ((command (concatenate 'string
|
||||
"\"" *url* "\?step=2" "\""
|
||||
" -H \"" (car headers) "\""
|
||||
" -H \"" (cadr headers) "\"")))
|
||||
(let ((result (run-curl command)))
|
||||
(format t "~%RESULT: curl ~a" result)
|
||||
result))))
|
||||
|
||||
(defun four ()
|
||||
(let*
|
||||
((data (three))
|
||||
(input
|
||||
(car (ppcre:all-matches-as-strings "(?sm)\{.*}$" data)))
|
||||
(challenge
|
||||
(string-left-trim "challenge: " (car (ppcre:all-matches-as-strings "challenge:(.*)" data))))
|
||||
(timestamp
|
||||
(string-left-trim "timestamp: " (car (ppcre:all-matches-as-strings "timestamp:(.*)" data))))
|
||||
(sorted (sort (cdr (jsown:parse input)) #'string<= :key #'first))
|
||||
(connected
|
||||
(string-right-trim "\&"
|
||||
(format nil "~{~A~}"
|
||||
(loop
|
||||
for item in sorted
|
||||
collect
|
||||
(concatenate 'string (car item) "\=" (cdr item) "\&")))))
|
||||
(hash (sha-256 connected))
|
||||
(command
|
||||
(string-right-trim "\-"
|
||||
(concatenate 'string
|
||||
"-X POST \"" *url* "\?step=3" "\""
|
||||
" -H \"Content-Type: application/x-www-form-urlencoded\" "
|
||||
" -d \"challenge=" challenge "\""
|
||||
" -d \"timestamp=" timestamp "\""
|
||||
" -d \"hash=" hash "\""
|
||||
))))
|
||||
(terpri)
|
||||
(print challenge)
|
||||
(print timestamp)
|
||||
(print hash)
|
||||
(terpri)
|
||||
(format t "~%COMMAND: curl ~a" command)
|
||||
(terpri)
|
||||
(let ((result (run-curl command)))
|
||||
(format t "~%RESULT: curl ~a" result))
|
||||
(terpri)))
|
||||
|
||||
(defun sha-256 (str)
|
||||
(ironclad:byte-array-to-hex-string
|
||||
(ironclad:digest-sequence :sha256
|
||||
(ironclad:ascii-string-to-byte-array str))))
|
||||
|
||||
(defvar *email* (alexandria:read-file-into-string "email"))
|
||||
|
||||
(defun base64 ()
|
||||
(let ((email *email*))
|
||||
(loop repeat 100 do
|
||||
(if (ppcre:scan "@" email)
|
||||
(print email)
|
||||
(setf email (cl-base64:base64-string-to-string email))))))
|
Loading…
Reference in a new issue